Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi drawgrid: zelle einfärben (https://www.delphipraxis.net/66592-drawgrid-zelle-einfaerben.html)

Mr. Pink 31. Mär 2006 23:14


drawgrid: zelle einfärben
 
hallo,
ich weiß dass diese frage schon oft gestellt wurde, habs auch in der suche gefunden, bin aber aus den antworten nicht schlau geworden, da diese oft sehr komplex waren und damit mir zum teil unverständlich, da ich mich nich wirklich gut mit delphi auskenne.
ich möchte eigentlich nur, dass wenn ich auf eine zelle im drawgrid klicke, diese z.b. rot eingefärbt wird, mehr nicht.
hatte die überlegung dass mit OnSelectCell zu machen, weiß aber nicht den TDrawgrid-befehl.

wär schön wenn mir jemand da einfach weiter helfen könnte, thx

p.s.: schön wär es, wenn man mehrere cells auf einmal einfärben könnte, indem man einfach durch ziehen mehrere selektiert

Der_Unwissende 1. Apr 2006 10:09

Re: drawgrid: zelle einfärben
 
Hi,
alles was du benötigst bietet dir das Ereignis OnDrawCell.
Dieses tritt immer dann ein, wenn eine Zelle gezeichnet werden soll. Erstell einfach eine Methode, die alle zur Methode gehörigen Parameter besitzt (Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState). Nun musst du nur den State überprüfen, ist die Zelle Selektiert (gdSelected in State), so zeichnest du die Zelle rot.

Die Fläche die Rot gefärbt werden musst geht dabei aus Rect hervor. Der Canvas auf den du zeichnest ist natürlich der Canvas des DrawGrid. Mittels
Delphi-Quellcode:
DrawGrid.Canvas.Brush.Color := clRed;
DrawGrid.Canvas.FillRect(Rect);
solltest du dir ein rotes Rechteck in die entsprechende Zelle zeichnen können. Achtung, hier überschreibst du natürlich auch jeglichen Inhalt der Zelle, du musst also eventuellen Text noch mal selbst rüber zeichnen (Canvas.TextOut).

Sollte das DrawGrid keine mehrfach-Auswahl unterstützen, so müsstest du dir nur eine Liste anlegen, die halt alle Zellen speichert, die gerade selektiert sind (und dann im OnSelectCell die entsprechende Zelle hinzufügen und in OnDrawCell prüfen ob die Zelle in deiner Liste liegt).

Ist alles ungetestet und komplett der OH entnommen, also nicht wundern wenn's nicht ganz so klappt.

Gruß Der Unwissende

[Edit]übersehen, dass TGridDrawState ein set ist und korrigiert[/edit]

Alexander Roth 1. Apr 2006 10:12

Re: drawgrid: zelle einfärben
 
http://alexander.f-u-p.org/faq/faq.p...2=Delphi&id=25
Das dürfte dir helfen!!!

Mr. Pink 1. Apr 2006 10:53

Re: drawgrid: zelle einfärben
 
danke für die antworten, aber hat immer noch nicht so ganz geklapt!

@Der_Unwissende: Wenn ich das richtig verstanden habe, dann beschreibt 'rect' die zelle, die eingefärbt werden soll, nur weiß ich jetzt nicht, wie ich rect mit der selectierten zelle gleichsetze.

:wall: also, mit diesem string- und drawgridzeuch komm ich irgendwie überhaupt nicht klar, weiß auch nicht wieso. :wall:

wenns nicht zu viel verlngt ist, könnte dann vllt jemand den code dafür schreiben? (nur das einfärben einer selektierten zelle, ist auch nicht für die schule^^), komm mir ja auch doof dabei vor, aber ich bin durch kein/-e erklärung/tutorial im i-net durchgestiegen...

Der_Unwissende 1. Apr 2006 11:11

Re: drawgrid: zelle einfärben
 
Nochmal, du schreibst dir einfach eine eigene Methode DeinDrawGridCell

Delphi-Quellcode:
procedure DeinDrawGridCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
begin
  // prüfen ob die Zelle selektiert ist
  if gdSelected in State then
    begin
      // rotes Rechteck zeichnen
      DeinDrawGrid.Canvas.Brush.Color := clRed;
      DeinDrawGrid.Canvas.FillRect(Rect);
    end; //  if gdSelected in State
end; // of procedure DeinDrawGridCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
Das solltest du dann einfach jeder Zelle zuweisen als OnDrawCell-Ereignisbehandlung (Zelle.OnDrawGrid := DeinDrawGridCell;) fertig.

Mr. Pink 1. Apr 2006 11:48

Re: drawgrid: zelle einfärben
 
okay, danke, dass du dir nochmal die mühe gemacht hast :love:
probleme bereitete mir dieser teil:
Delphi-Quellcode:
if gdSelected in State then
da ich einen solchen ausdruck noch nie gesehen habe, mir wäre
Delphi-Quellcode:
if state=gdselected
richtig vorgekommen, was aber anscheinend nicht funktioniert, deshalb konnte ich auch deinen pseudocode nicht umsetzen :cry:

also, soweit funtioniert das alles, nur habe ich alles in die OnDraw-procedure gepackt, da ich nicht weiß, mit welchen parametern ich 'DeinDrawGridCell' aufrufen muss, slo was ich z.b. bei sender, rect und state hin schreiben muss. mit welcher procedure mus ich denn nun diese aufrufen?
ich weiß hier echt nicht wie ich das alles implementieren muss, sry!

so wie ich es gemacht habe, sind die zellen nur rot wenn ich die maustaste gedrückt habe, wenn es anders ist, wenn ich es so mache wie du es meintest, dann vergiss folgendes:
ich wollte, da haben ich mich wohl unverständlich ausgedrückt, dass diese zellen dauerhaft rot bleiben. hab mir überlegt, dass ich ein array für die zellen mache und dieses array dann inner OnDraw-procedure überprüft, und dann alles neu gezeichnet wird. oder gibt es da einfacherere methoden, dies zu verwirklichen???
thx Mr. Pink.

Der_Unwissende 1. Apr 2006 13:25

Re: drawgrid: zelle einfärben
 
Also was das gdSelected in State angeht, so hat das was mit sets zu tun.
Du kannst in Delphi verschiedene Typen anlegen, eine Möglichkeit sind einfache Datentypen TDeinTyp = (dt1, dt2, ...), diesen wird dann intern ein Ordinaler Wert zugeordnet (explizit mit TDeinTyp = (dt1 = 1038) => ord(dt1) = 1038).

Genau so kannst du dir z.B. auch ein Char vorstellen. Eine Variable von einem solchen Typ kann natürlich nur genau einen Wert speichern.

Alternativ gibt es noch Klassen (gehe ich jetzt nicht näher drauf ein) und Verbundstypen (Records). Ein Record speichert nun eine Kombination von Werten, z.B.
Delphi-Quellcode:
TPunkt = record
  x : Integer;
  y : Integer;
end;
Das ist schön, aber du kannst auch hier wieder nur einen Wert zuweisen (in dem Fall allerdings ein x und ein y).

Desweiteren gibt es halt noch Bitfelder. Diese sind intern auch nur eine Zahl, bei der man nur prüft ob ein gewisses Bit gesetzt ist. Dies bietet dir den Vorteil, dass du mehrere Dinge gleichzeitig markieren kannst. Klingt alles ein wenig kompliziert, aber nimm zum Beispiel die Key-Events.
Wenn du eine Taste drückst, willst du vielleicht auf anders reagieren wenn
  • Alt gedrückt ist
  • Shift gedrückt ist
  • Strg gedrückt ist
  • Alt + Shift gedrückt ist
  • Strg + Shift gedrückt ist
  • ..

Du siehst, es gibt eine Menge Möglichkeiten. Dabei ist wichtig, dass keine oder alle Tasten genauso gedrückt sein können wie eine beliebige Kombination. Weißt du nun einfach jeder Taste ein Festes Bit zu und kodierst es, kämst du vielleicht auf (000 <- Nichts gedrückt, 001 <- Shift gedrückt, 010 <- Alt gedrückt, 011 <- Shift und Alt gedrückt, ...)

Wichtig ist, dass Delphi dass alles automatisch macht (und sicherlich nicht in 3 Bits kodiert, sondern sinnvoller und effizienter). Dazu verwendet man das Schlüsselwort set.
Ja und mit in prüfst du dann eigentlich nur ob eine Taste auch gedrückt war (also ob das Bit gesetzt ist).
Im Beispiel mit den Tasten kennt Delphi den TShiftstate, du kannst dann gucken ob
Delphi-Quellcode:
state : TShiftState;
begin
...
// nur Shift gedrückt ist
if state [ssShift] then
  begin
   ...
  end

// genau Shift und Alt gedrückt sind
else if state = [ssShift, ssAlt] then
  begin
   ...
  end

// Auch Shift gedrückt ist
else if ssShift in State then
  begin
   ...
  end;
Was das zeichnen mit dem roten Kasten angeht, so wußte ich halt nicht, wie der sich etwas als markiert merkt. Am einfachsten (da hast du Recht) ist es ein Feld zu benutzen. Nimm einfach ein zwei Dimensionales Array of Boolean und merk dir welche Zellen markiert sind (wenn die Anzahl der Zellen fest ist und nicht zu groß). Dann kannst du leicht in der Methode anhand von Row und Column prüfen ob eine Zelle markiert ist oder nicht.
Sollte die Anzahl der Zellen hingegen Variabel sein bietet sich eher eine Liste an. Diese wachsen dynamisch mit der Anzahl der enthaltenen Elemente (und du musst dich nicht drum kümmern, dass macht Delphi). Allerdings musst du dann auch immer über alle Elemente iterieren und schauen ob du eine Zelle hier findest oder nicht.

Mr. Pink 1. Apr 2006 15:36

Re: drawgrid: zelle einfärben
 
vielen dank für die ausführliche erklärung :thumb: :thumb: :thumb:

ich habs jetzt mit dem array, das in der OnDraw-procedure überprüft wird, funnktioniert gut, nur wird es leider nicht erkannt, wenn mehrere gleichzeitig durch ziehen markiert werden.
ich hab das mit OnSelectCell gemacht, geht das irgendwie anders, dass alle markierten zellen erfasst werden?

Mr. Pink 1. Apr 2006 17:13

Re: drawgrid: zelle einfärben
 
ich habe mir überlegt, dass man ja alle zellen mit einer for-to-schleife auf selektion überprüfen könnte, allerdings weiß ich nicht, wie ich jetzt eine zelle nach folgender art ansprechen kann:
Delphi-Quellcode:
for i:=1 to 32 do
begin
 for j:=1 to 32 do
 begin
  if drawgrid1.cell[i,j].selected then ...
 end;
end;
so geht es ja nicht, aber wie denn???? :gruebel:

Der_Unwissende 1. Apr 2006 20:09

Re: drawgrid: zelle einfärben
 
Ich weiß ehrlich gesagt nicht genau was du machen möchtest.
Ich meine
Zitat:

Zitat von Mr. Pink
if drawgrid1.cell[i,j].selected then ...

ist ja eine lustige Idee, aber es gibt keine Eigenschaft Cell. Von welchem Typ sollte die denn sein? Also wenn Delphi da erahnen kann, was du möchtest, dann wäre der Stand der AI doch deutlich weiter als mir bekannt ist.
Dein DrawGrid kümmert sich nur für dich ums Zeichnen der Gitterstruktur. Du kannst auch alle per Hand machen, benötigst halt nur einen Zeichencanvas. Wenn du die Eigenschaften veränderst, so wird nur neu gezeichnet.
Sobald eine bestimmte Zelle gezeichnet werden soll, wird ein Ereignis ausgelöst. Das heißt, für ein 32 x 32 Gitter, wird auch 32 x 32 dieses Ereignis ausgelöst. Hier musst du in deiner eigenen Struktur nachschauen ob eine Zelle markiert ist oder nicht. Wie du dir das merkst ist mehr oder weniger deine Sache. Wie gesagt eine Matrix von Boolean wäre eine Möglichkeit.
Dazu musst du dir natürlich auch überlegen, wann eine Zelle markiert wurde (bzw. das Gegenteil).


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:49 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz