Autor Beitrag
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Di 31.10.23 14:24 
Hallo,

ich möchte in einem DrawGrid eine bestimmte Zelle einfärben. Scheint einfach zu sein. Ich habe ein kleines Testprogramm gemacht, dass nacheinander alle Zellen einer Zeile rot färben soll, immer mit 500 ms Pause zwischen den einzelnen Zellen.

In meinem Beispiel (Code unten und als Projekt im Anhang) geht das bis Spalte 3 wie geplant. Bei Spalte 4 wird nur noch eine schmale Linie gezeichnet und ab dann geht nichts mehr. Das Tabellenraster ist auf dem Monitor klar zu sehen.

Ein Breakpoint nach der Zeile "Rect := ..." zeigt, dass hier was falsch läuft:

Zeile 1: Rect = ( 0,102),(10,152): OK, Breite = 10, Hoehe=50
Zeile 2: Rect = (11,102),(21,152): OK
Zeile 3: Rect = (22,102),(32,152): OK
Zeile 4: Rect = (33,102),(32,152): FALSCH
Zeile 5: Rect = ( 0, 0),( 0, 0): FALSCH

Mache ich was falsch oder hat die Funktion da eine Macke? Hat jemand eine Idee? (Windows 10)

Grüße
GuaAck

ausblenden volle Höhe Delphi-Quelltext
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:
47:
48:
49:
50:
51:
UNIT UGridfaerben2;

INTERFACE

USES
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids;

TYPE
  TForm1 = CLASS(TForm)
    DrawGrid1: TDrawGrid;
    Button1: TButton;
    PROCEDURE Button1Click(Sender: TObject);
  PRIVATE
    { Private-Deklarationen }
  PUBLIC
    { Public-Deklarationen }
  END;

VAR
  Form1: TForm1;

IMPLEMENTATION

{$R *.dfm}

PROCEDURE TForm1.Button1Click(Sender: TObject);
VAR
  Breite, Hoehe: integer;
  Rect: TRect;
  Col, Row: integer;
BEGIN
  Breite := 10;
  Hoehe := 3;
  DrawGrid1.FixedCols := 0;
  DrawGrid1.FixedRows := 0;
  DrawGrid1.DefaultColWidth := 10;
  DrawGrid1.DefaultRowHeight := 50;
  DrawGrid1.RowCount := Breite;
  DrawGrid1.ColCount := Hoehe;
  Row := 2;
  DrawGrid1.Canvas.Brush.Color := clred;
  FOR Col := 0 TO Breite - 1 DO
    BEGIN
      Rect := DrawGrid1.CellRect(Col, Row);
      DrawGrid1.Canvas.FillRect(Rect);
      sleep(500);
    END;
END;

END.


Moderiert von user profile iconTh69: Titel leicht geändert.
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 31.10.23 15:22 
Hallo,

s. TCustomDrawGrid.CellRect:
Zitat:
Ist die angegebene Zelle nicht sichtbar, gibt CellRect ein leeres Rechteck zurück.

Und bei dir für die 4. Zeile also nur der anteilig sichtbare Bereich.

Du solltest nie den UI-Thread blockieren (wie mit dem Sleep(...)) -> "Fenster reagiert nicht mehr"...
Zeichnen solltest du also nur im OnDrawCell-Ereignis - für das Animieren dann zusätzlich einen Timer benutzen, der das DrawGrid aktualisiert.
GuaAck Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Di 31.10.23 23:29 
Hallo,

Danke zunächst, mir war nicht klar, dass Sleep so blockierend wirkt.

In meinem realen Projekt wäre das kein Problem, da ändert sich der abzubildende Prozess nur langsam. Mein Haupt-Thread hat wenig zu tun, die Arbeit erledigen verschiedene andere Threads.

Da ich eigentlich nur farbige Flecken in einem Raster darstellen will, nehme ich jetzt ein Image und male in der Canvas selbst meine Flecken.

Gruß
GuaAck

Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 01.11.23 10:17 
In GUI-Programmen darf der UI/Main-Thread nicht länger als einige 10ms blockiert werden, da ansonsten die Windows-Nachrichtenschleife (message loop) nicht mehr ausgeführt wird, d.h. jegliche Benutzeraktionen sowie Fensteraktualisierungen werden unterbunden.
In deinem Code hast du dies für 5s (= 10 * 500ms) getan, ehe die OnButtonClick-Funktion beendet wird und zur Nachrichtenschleife (Application.Run) zurückgekehrt wird.

Für C# verlinke ich immer myCSharp.de: [FAQ] Warum blockiert mein GUI?
Und für z.B. UWP habe ich Aufrechterhalten der Reaktionsfähigkeit des UI-Threads gefunden.

GuaAck hat folgendes geschrieben:
Da ich eigentlich nur farbige Flecken in einem Raster darstellen will, nehme ich jetzt ein Image und male in der Canvas selbst meine Flecken.

Dies liest sich aber nicht so, als ob dies an der Problematik etwas ändert (zumindestens wenn es sich zeitbasiert ändern soll).