Autor |
Beitrag |
Deviljho452
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 24.04.12 16:27
Hallo liebe Community,
ich sitze seit tagen verzweifelt an der Komponente des Stringgrids bzw. an dem Drawgrid, weil ich gerne das Game of Life programmieren möchte.
Man kann wunderbar mit der Maus eine Zelle auswählen, jedoch mit welchem event (ondrawcell,onclick....) und mit welchen Befehlen im Event kann ich die selektierte Zelle färben?
Danke für jeden Gedankenstrom
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Di 24.04.12 16:57
Zuletzt bearbeitet von Delphi-Laie am Mi 25.04.12 11:00, insgesamt 1-mal bearbeitet
Für diesen Beitrag haben gedankt: Deviljho452
|
|
Narses
Beiträge: 10182
Erhaltene Danke: 1255
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 24.04.12 17:23
Moin und in der EE!
Schonmal in die Suche geschaut? STRINGGRID HINTERGRUND
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
Für diesen Beitrag haben gedankt: Deviljho452
|
|
Deviljho452
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 24.04.12 17:28
Danke Narses
in der SuFu hab ich natürlich schon gestöbert , jedoch liegt mein problem beim Klicken, also beim Färben einer Zelle via Mausklick und die SuFu liefert mir nur Quelltext und Lösungsansätze, bei denen beim Öffnen des Programms bestimmte Zellen gefärbt werden.
Ich suche einfach nur etwas wie stringgrid1.cells[acol,arow].color:=clred , natürlich geht es so nicht
Moderiert von Th69: Delphi-Tags hinzugefügt
|
|
Narses
Beiträge: 10182
Erhaltene Danke: 1255
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 24.04.12 19:12
Moin!
Deviljho452 hat folgendes geschrieben : | jedoch liegt mein problem beim Klicken, also beim Färben einer Zelle via Mausklick |
Nein, dein Problem liegt im Verständnis der Funktionsweise einer ereignisorientierten Anwendung bzw. VCL-Komponente.
Man kann keine Zelle "via Mausklick" färben, weil das String-/Draw-Grid so nicht arbeitet. Es gibt das Ereignis OnDrawCell, in dem du die Gelegenheit bekommst, das aussehen dieser speziellen Zelle selbst festzulegen. Also musst du dir in einem (zusätzlichen) Speicherbereich, der idealerweise genau so groß ist, wie das Grid selbst, merken, welche z.B. in deinem Fall (Hintergrund-)Farbe diese Zelle bekommen soll. Diese Information verwendest du dann im OnDrawCell dazu, entsprechendes zu zeichnen.
Im OnClick des Grids musst du also in dem von Delphi-Laie bereits vorgeschlagenen 2D-Array lediglich die Farbe setzen (und ggfs. ein Neuzeichnen auslösen), das ist alles.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Mi 25.04.12 11:24
Deviljho452 hat folgendes geschrieben : | Ich suche einfach nur etwas wie stringgrid1.cells[acol,arow].color:=clred , natürlich geht es so nicht |
Ich gebe Dir grundsätzlich recht. Das Einfärben der Zellenhintergründe und/oder Schriftfarben in Stringgrids ist m.E. verunglückt, verkompliziert, nichtintuitiv, ich weiß allerdings nicht, ob man das besser hätte lösen können. Diesbezügliche Anfragen sind in den Foren mehr oder weniger ein Dauerbrenner, das allein spricht doch schon eine deutliche Sprache. Auch ich suchte stundenlang (!) nach einer Lösung.
Narses, ich bestreite, daß diese Anfrage zu der Verallgemeinerung berechtigt, einem ein gewisses Verständnis für Ereignisorientierung abzusprechen. Gewiß wollte Deviljho452 den (Ein-)Färbbefehl in irgendeine Ereignisbehandlungsroutine oder einen Unitanfang packen. Quellcode an Stellen zu plazieren, die keinem Ereignis zugrundeliegen, ist sogar ziemlich schwierig.
Fatalerweise findet die automatische Codevervollständigung ("Code insight") - jedenfalls in meinem Delphi 4 - nur Stringgrid1.Canvas.BrushCopy, doch die Suchfunktion hier im Forum liefert schon im zweiten Falle die Lösung für die Zellen(hintergrund)färbung: StringGrid1.Canvas.Brush.Color:=Farbe[ACol,ARow]. Klappt jedenfalls bei mir.
Ergänzung: Daß Stringgrid und individuelle (Ein-)Färbbarkeit irgendwie auf Kriegsfuß stehen, zeigt sich auch daran, wenn man mal versucht, Schrift und Zellenhintergrund - natürlich mit verschiedenen - Farben zu versehen. Die Ergebnisse sind i.d.R. inkonsistent.
Moderiert von Th69: Delphi-Tags hinzugefügt
Zuletzt bearbeitet von Delphi-Laie am Fr 04.05.12 13:51, insgesamt 1-mal bearbeitet
Für diesen Beitrag haben gedankt: Deviljho452
|
|
Deviljho452
Hält's aus hier
Beiträge: 3
|
Verfasst: Mi 25.04.12 16:51
Hi Laie,
ich hab mich gestern Nacht noch etwas mit dem Problem beschäftigt und jetzt via OnMouseDown bei Mausklick schon die Kennzeichnung des Feldes mit 'X' hinbekommen.
Daraufhin wollte ich einfach eine Schleife durchlaufen lassen und bei jeder Zelle, deren Caption X ist, soll die Hintergrundfarbe clred werden. Ich habe dabei deinen Befehl eingebaut, jedoch verlangt er bei [ARow,ACol] einen Array Typen o.O . Da bin ich ratlos und weiß nicht was der Debugger von mir verlangt
Moderiert von Th69: Delphi-Tags hinzugefügt
|
|
Narses
Beiträge: 10182
Erhaltene Danke: 1255
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 25.04.12 17:48
Moin!
Deviljho452 hat folgendes geschrieben : | Daraufhin wollte ich einfach eine Schleife durchlaufen lassen und bei8 jeder Zelle, deren Caption X ist, soll die Hintergrundfarbe clred werden. |
Narses hat folgendes geschrieben : | dein Problem liegt im Verständnis der Funktionsweise einer ereignisorientierten Anwendung bzw. VCL-Komponente. |
An dieser Tatsache hat sich leider noch nichts geändert.
Deviljho452 hat folgendes geschrieben : | Ich habe dabei deinen Befehl eingebaut, jedoch verlangt er bei [ARow,ACol] einen Array Typen o.O . Da bin ich ratlos und weiß nicht was der Debugger von mir verlangt |
Eine Array-Referenz, die du natürlich auch selbst anlegen und verwalten musst.
Da wohl doch leider noch zu viele Grundlagen und zu viel Verständnis für ereignisorientiertes Programmieren fehlen (wobei es völlig egal ist, ob das nun einfach oder nicht sei, es ist halt so, wie es ist), hier mal ein Beispiel für ein StringGrid:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin if (Sender as TStringGrid).Cells[ACol, ARow] <> '' then begin (Sender as TStringGrid).Canvas.Brush.Color := clRed; (Sender as TStringGrid).Canvas.FillRect(Rect); end; end; | Damit wird jede Zelle, deren Inhalt nicht-leer ist, mit rotem Hintergrund gezeichnet (ohne Inhalt). Wenn du in den Optionen des StringGrids goEditing auf TRUE setzt, kann man das schön zur Laufzeit ausprobieren.
Der Schlüssel zum Verständnis ist: es gibt keine irgendwie geartete Anweisung, mit der man den Hintergrund einer Zelle färben kann, sondern man muss beim Zeichnen des Grids eingreifen und die gewünschten/betroffenen Zellen anders (selbst) malen. Warum? Weil du (=dein Programm) nicht wissen kannst, wann das Grid gezeichnet wird, das passiert ausserhalb deines Einflussbereiches. Deshalb musst du "von hinten durch die Brust ins Auge" und darauf reagieren, dass etwas gezeichnet werden soll.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Delphi-Laie
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Mi 25.04.12 22:04
Deviljho452 hat folgendes geschrieben : | jedoch verlangt er bei [ARow,ACol] einen Array Typen o.O . Da bin ich ratlos und weiß nicht was der Debugger von mir verlangt |
array of array of TColor deklarieren (definieren) und dieses Array vor dem ersten Zugriff mit setlength([Arrayvariable],xmax-1,ymax-1) ausreichend groß dimensionieren. Ich nannte mein Array bzw. konkreter die Arrayvariable einfach "Farbe", s.o. .
Oder, wenn die Größe für immer feststeht, gleich statisch definieren: array[0..xmax-1,0..ymax-1] of TColor (nicht: array[1..xmax,1..ymax], weil das Stringgrid bei den Zeilen und Spalten auch die Indizes 0 besitzt).
Moderiert von Th69: Delphi-Tags hinzugefügt
Zuletzt bearbeitet von Delphi-Laie am Do 26.04.12 09:53, insgesamt 1-mal bearbeitet
|
|
Narses
Beiträge: 10182
Erhaltene Danke: 1255
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 25.04.12 23:59
Moin!
Deviljho452 hat folgendes geschrieben : | Da bin ich ratlos und weiß nicht was |
Ich denke mittlerweile, ein StringGrid (oder sonstiges Grid) ist einfach die falsche Komponente für dich und diesen Zweck.
Warum probierst du nicht mal Shapes aus? Die lassen sich prima imperativ "befingern" und sind auch nicht langsamer oder schneller, als ein Grid.
Wenn man die Shapes dynamisch auf das Formular packt, dann ist das auch relativ leicht zu handeln:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| uses ..., ExtCtrls; const MAX_X = 5; MAX_Y = 5; FIELDSIZE = 32; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure ShapeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
implementation
procedure TForm1.FormCreate(Sender: TObject); var i, j: Integer; ThisShape: TShape; begin Self.ClientWidth := (MAX_X +2) *FIELDSIZE; Self.ClientHeight := (MAX_Y +2) *FIELDSIZE; for i := 1 to MAX_Y do for j := 1 to MAX_X do begin ThisShape := TShape.Create(Self); ThisShape.Parent := Self; ThisShape.Left := j*FIELDSIZE; ThisShape.Top := i*FIELDSIZE; ThisShape.Width := FIELDSIZE; ThisShape.Height := FIELDSIZE; ThisShape.Tag := i*MAX_Y +j; ThisShape.OnMouseDown := ShapeMouseDown; end; end;
procedure TForm1.ShapeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Sender as TShape).Brush.Color = clWhite then (Sender as TShape).Brush.Color := clBlack else (Sender as TShape).Brush.Color := clWhite; end; | Im Anhang das entsprechende Demo-Projekt, einfach mal ausprobieren. Fragen? Fragen!
cu
Narses
Einloggen, um Attachments anzusehen!
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
DelphiJogi
Beiträge: 19
Win11
Delphi 10.4
|
Verfasst: So 01.10.23 22:24
Ich experimentiere seit einiger Zeit Zellen eines StringGrids zu färben. Es will mir einfach nicht gelingen! Habe schon so einige Codebeispiele ausprobiert, ohne Erfolg. Es kann doch nicht so schwierig sein !!!
Sogar dieser einfache Code macht nicht da was er soll...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm5.StatistikListeSparDrawCell(Sender: TObject; ACol, ARow: Integer;Rect: TRect; State: TGridDrawState); begin for i := 1 to 10 do begin If StatistikListeSpar.Cells[2, i] <> '' then begin StatistikListeSpar.RePaint; StatistikListeSpar.Canvas.Brush.Color := clRed; StatistikListeSpar.Canvas.FillRect(Rect); end; end; end; |
Moderiert von Narses: Full-Quote entfernt und Delphi-Tags hinzugefügt
|
|
mandras
Beiträge: 430
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: Mo 02.10.23 00:48
Versuche es einmal so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TForm5.StatistikListeSparDrawCell(Sender: TObject; ACol, ARow: Integer;Rect: TRect; State: TGridDrawState); begin If StatistikListeSpar.Cells[2, i] <> '' then begin StatistikListeSpar.Canvas.Brush.Color := clRed; StatistikListeSpar.Canvas.FillRect(Rect); end; end; |
DrawCell wird für jede sichtbare Zelle automatisch einmal aufgerufen,
insofern sind die for-Schleife und das Repaint nicht sinnvoll.
Moderiert von Th69: Delphi-Tags hinzugefügt
|
|
Th69
Beiträge: 4785
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 02.10.23 09:46
Auch das ist noch nicht ganz richtig, sondern eher so
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TForm5.StatistikListeSparDrawCell(Sender: TObject; ACol, ARow: Integer;Rect: TRect; State: TGridDrawState); begin if ACol = 2 and StatistikListeSpar.Cells[ACol, ARow] <> '' then begin StatistikListeSpar.Canvas.Brush.Color := clRed; StatistikListeSpar.Canvas.FillRect(Rect); end; end; |
|
|
DelphiJogi
Beiträge: 19
Win11
Delphi 10.4
|
Verfasst: Mo 02.10.23 19:04
Th69 hat folgendes geschrieben : | Auch das ist noch nicht ganz richtig, sondern eher so
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TForm5.StatistikListeSparDrawCell(Sender: TObject; ACol, ARow: Integer;Rect: TRect; State: TGridDrawState); begin if ACol = 2 and StatistikListeSpar.Cells[ACol, ARow] <> '' then begin StatistikListeSpar.Canvas.Brush.Color := clRed; StatistikListeSpar.Canvas.FillRect(Rect); end; end; | |
Danke, aber so komme ich nicht weiter! Also mache ich mal einen Versuchsaufbau.
Ich lege ein StringGrid mit den StandardOptionen auf meine Form.
Erzeuge folgende DrawCell-Procedure ...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm5.StringGrid1DrawCell(Sender: TObject; ACol,ARow: Integer; Rect: TRect; State: TGridDrawState); begin if not Odd(ARow) and not (gdFixed in State) then with StringGrid1 do begin Canvas.Brush.Color := clRed; Canvas.FillRect(Rect); Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);
end; end; |
Dieser Code soll jede zweite Zeile rot färben.
Der Aufruf der Procedure ....
Delphi-Quelltext 1:
| StringGrid1DrawCell(Sender, Acol, Arow, Rect, State); |
Ist das richtig? Was ist mit Acol und Arow? Müssen da nicht Parameter übergeben werden?
Moderiert von Th69: Delphi-Tags hinzugefügt
Zuletzt bearbeitet von DelphiJogi am Mo 02.10.23 19:48, insgesamt 2-mal bearbeitet
|
|
mandras
Beiträge: 430
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: Mo 02.10.23 19:33
Kann es sein, daß Du Deine DrawCell-Methode manuell angelegt hast und nicht über die Ereignisspalte im Formulardesigner?
Normalerweise würde man wie folgt vorgehen, um jede 2. Zeile mit einer bestimmten Farbe anzuzeigen:
Das Grid im Formular anwählen, links im Objektinspektor auf die rechte Spalte ("Ereignisse") wechseln und dann einen Doppelklick auf das weiße Eingabefeld neben " OnDrawCell" machen.
Delphi erstellt dann das "Drumherum" (Deklaration der Prozedur am Anfang des Quellcodes, erstellen des Prozedurrumpfs, die Prozedur heißt dann automatisch zB StringGrid1DrawCell).
Dann ergänzt Du den Prozedurrumpf mit Deinem Code (der ist übrigens korrekt, bei mir färbt er den Hintergrund jeder 2. Zeile).
Nebenbei hat Delphi die Prozedur StringGrid1DrawCell als Ereignis des Stringgrids eingetragen.
Das bedeutet, daß StringGrid1DrawCell nun automatisch für jede Zelle des Grids aufgerufen wird, die gezeichnet werden muß.
Ich hoffe, daß ich damit Dein Problem richtig erfaßt habe.
Moderiert von Th69: Delphi-Tags hinzugefügt
Für diesen Beitrag haben gedankt: DelphiJogi
|
|
DelphiJogi
Beiträge: 19
Win11
Delphi 10.4
|
Verfasst: Mo 02.10.23 20:15
Vielen Dank Mandras,
das war mein Fehler. OnDrawCell im EreignisHandler habe ich total ignoriert.
Moderiert von Th69: Delphi-Tags hinzugefügt
|
|
DelphiJogi
Beiträge: 19
Win11
Delphi 10.4
|
Verfasst: Mo 02.10.23 21:07
Bleibt noch eine Frage ...
Wie ist "FocusColor" des Grids zu ermitteln? Und ist die Focusfarbe auch zu ändern?
|
|
Th69
Beiträge: 4785
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 03.10.23 09:48
Diese Eigenschaft heißt SelectedColor und zum Selberzeichnen s. ...change the default cell selection color in a TStringGrid?
Und ändern kannst du diese Farbe auch mit z.B. StringGridX.SelectedColor := clBlue;
Für diesen Beitrag haben gedankt: DelphiJogi
|
|
Sinspin
Beiträge: 1332
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Fr 13.10.23 16:46
Wäre ich dein Arbeitgeber und Du würdest mir diesen Code abliefern... dann wäre ich die längste Zeit dein Arbeitgeber gewesen.
DelphiJogi hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm5.StringGrid1DrawCell(Sender: TObject; ACol,ARow: Integer; Rect: TRect; State: TGridDrawState); begin if not Odd(ARow) and not (gdFixed in State) then with StringGrid1 do begin Canvas.Brush.Color := clRed; Canvas.FillRect(Rect); Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);
end; end; | |
Das Verwenden von with führt zu sofortiger Degradierung auf das Level eines Arbeitssuchenden.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
DelphiJogi
Beiträge: 19
Win11
Delphi 10.4
|
Verfasst: Mi 18.10.23 17:58
Moderiert von Narses: Komplett-Zitat des vorigen Beitrags entfernt.
Dann erkläre doch Mal warum der Code so schlecht ist und wie du diesen schreiben würdest!
Übrigens ist dieser Code ein "Code-Beispiel" der nicht von mir selbst stammt.
|
|