Panels sehr langsam (beim Neuzeichnen)

Rund um die LCL und andere Komponenten
Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

FlashBurn hat geschrieben:Ich habe allerdings eine Idee woran es liegen kann, den Anchors. Ich muss nur mal gucken wie ich die alle deaktivieren kann.
Ja, stimmt, die haben wohl einen Defaultwert<>null.
Mach mal beim createn:

mPanels[_y][_x].Anchors:=[];

FlashBurn
Beiträge: 12
Registriert: Mi 16. Jun 2010, 16:39

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von FlashBurn »

Ok, ein Problem weniger ;)

Fragt sich nur, warum ab immer der gleichen Stelle die Panels mit einmal trotzdem richtig positioniert wurden.

Das Zeichnen ist aber trotzdem slow-as-hell ;) Was ich ein wenig komisch finde. Ich weiß das Lazarus bzw die LCL alles abstrahiert, wie bei Java, um Plattformunabhängig zu sein, aber das es dann sogar langsamer als Java ist, verwundert mich ein wenig.

Wenn Du mir jetzt noch sagen könntest, wie ich in einer PaintBox (oder halt nem Panel) zeichnen kann oder mich an eine Stelle verweist wo ich dazu was finde (habe schon gegooglelt aber nichts brauchbares gefunden), bin ich schon fast zufrieden ;)

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

Ich hab dir mal ein Beispiel mit Paintbox gemacht. Minimal, und nur horizontal, aber du verstehst das schon:
Das reicht:

Code: Alles auswählen

uses ExtCtrls;
 
....
  TForm1 = class(TForm)
    procedure FormCreate(Sender:TObject);
    procedure FormResize(Sender:TObject);
    procedure PBPaint(Sender:TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
...
Procedure TForm1.FormCreate(Sender:TObject);
Var aPB: TPaintBox;
  i: integer;
Begin
  For i:=0 To 4 Do
    Begin
      aPB := TPaintBox.Create(self);
      aPB.Parent := Self;
      aPB.Anchors := [];
      aPB.Tag := i;
      aPB.OnPaint := @PBPaint;
    End;
End;
 
Procedure TForm1.FormResize(Sender:TObject);
Var i,num,w: integer;
Begin
  For i:=0 To ComponentCount-1 Do
    Begin
      If Components[i] is TPaintBox Then
        Begin
          num := TPaintBox(Components[i]).Tag;
          w := ClientWidth Div 5;
          TPaintBox(Components[i]).SetBounds(w*num+2,2,w-4,40);
        End;
    End;
End;
 
Procedure TForm1.PBPaint(Sender:TObject);
Begin
  TPaintBox(Sender).Canvas.Brush.color := clLtGray;
  TPaintBox(Sender).Canvas.Pen.color := clGray;
  TPaintBox(Sender).Canvas.Rectangle(TPaintBox(Sender).ClientRect);
End;

FlashBurn
Beiträge: 12
Registriert: Mi 16. Jun 2010, 16:39

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von FlashBurn »

Erstmal danke für das Bsp.!

Ich habe das ganze zwar nicht so gemacht wie du jetzt, ich habe einfach meinen alten Code genommen, die Panels gegen PaintBoxes eingetauscht und in der FromPaint Methode gehe ich dann alle PaintBoxes durch, ändere die Farbe und zeichne ein gefülltes Rechteck ("FillRect"). Das funktioniert so nicht, da ich mal vermute, das nachdem ich gezeichnet habe, die OnPaint Methode der PaintBoxes aufgerufen wird und die halt wieder alles standardmäßig zeichnen, aber was ich dabei wieder beobachten konnte ist, das es wieder slow-as-hell ist :(

Woran liegt das, ich meine ich zeichne noch nicht mal viel (20*10 Objekte) und trotzdem ist es schon so langsam.

Ich werds dann nochmal versuchen in dem ich die OnPaint Methode "überschreibe" (so wie du in deinem Bsp.), aber ich glaube irgendwie nicht, das es dadurch schneller wird :(

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

K.A. bei mir geht das schnell. Aber was musst du auch dauernd resizen? :lol:

Hast du denn meinen Code so wie er ist mal getestet? Ist das bei dir auch langsam?

FlashBurn
Beiträge: 12
Registriert: Mi 16. Jun 2010, 16:39

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von FlashBurn »

Hab gerade mal meinen Code umgeschrieben, so dass ich auch ne PBPaint procedure habe und diese bei OnPaint reinschreibe.

Jetzt zeichnet er wunderbar, aber immernoch slow-as-hell ;) Ich habe zwar nicht nur 5 Objekte (da läuft es einigermaßen schnell), aber 200 Objekte sollten jetzt auch nicht so schlimm sein!

So langsam habe ich den Verdacht, dass es an Win7 liegt, denn wenn ich mir anschaue, wie viel schneller mein Java Programm unter XP läuft und jetzt mit Lazarus scheint es das selbe zu sein, nur habe ich leider keinen PC mit XP hier (nur in der Uni) und kann es daher leider nicht testen.
bei mir geht das schnell. Aber was musst du auch dauernd resizen?
Ich sags mal so, ich habe nur geresizt, um zu testen ob mein Code der die Größe und Position berechnet auch funktioniert und wenn man als Benutzer ein Fenster einfach mal ein wenig größer macht, dann sollte das wirklich nicht so langsam ablaufen. Vorallem zeichne ich ja nicht mal viel und unter Java geht es schneller und Java läuft noch in einer VM. Eigentlich nimmt man ja (zumindest ich und viele andere auch) Lazarus/Delphi um schnell mal ne Anwendung mit ner GUI zusammen zu basteln, die dann auch wesentlich performanter als Java ist, aber wenn das immer so ist wie jetzt bei mir. Dann kann ich gleich alles in Java machen.

Ich habe mir auch mal den Code für Lazarus besorgt, konnte dort aber leider nicht wirklich den Code finden, wo das Panel dann mal gezeichnet wird. Ich weiß nur das TPanel von CustomPanel abgeleitet ist.

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

Meine Frage war: Hast du denn meinen Code so wie er ist mal getestet?

Wenn das auch langsam ist, liegt's an deinem System.

FlashBurn
Beiträge: 12
Registriert: Mi 16. Jun 2010, 16:39

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von FlashBurn »

Meine Frage war: Hast du denn meinen Code so wie er ist mal getestet?
Antwort:
Hab gerade mal meinen Code umgeschrieben, so dass ich auch ne PBPaint procedure habe und diese bei OnPaint reinschreibe.
Also jein. Ich habe deinen Code nicht 1:1 übernommen, sondern habe meinen alten Code verwendet, aber habe ne PBPaint procedure und schreibe diese bei den PaintBoxes in das OnPaint Event rein. Habe ich nur 5 Objekte, so wie du in deinem Bsp., dann läuft es so wie ich es mir vorstelle, aber auch wenn ich 200 Objekte habe, sollte es so laufen!

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

Wie gesagt, Komponenten rumschieben ist nun mal nicht das schnellste was man machen kann.

Ich würde das ansatzweise so lösen:

Code: Alles auswählen

uses types...
 
Procedure TForm1.FormPaint(Sender:TObject);
Var i,w,h,x,y: integer;
Begin
  x := 0;
  y := 0;
  Canvas.Brush.color := clLtGray;
  Canvas.Pen.color := clGray;
  w := ClientWidth Div 10;
  h := ClientHeight Div 10;
  For i:=0 To 99 Do
    Begin
      If  (i>0) Then
        If (i Mod 10=0) Then
          Begin
            inc(y,h);
            x := 0;
          End
      Else inc(x);
      Canvas.Rectangle(w*x+2,2+y,w*x+2+w-4,h+2+y-4);
    End;
End;
 
function TForm1.ItemFromPoint(Point:TPoint; var ARect:TRect):integer;
Var i,w,h,x,y: integer;
Begin
  Result:=-1;
  x := 0;
  y := 0;
  w := ClientWidth Div 10;
  h := ClientHeight Div 10;
  For i:=0 To 99 Do
    Begin
      If  (i>0) Then
        If (i Mod 10=0) Then
          Begin
            inc(y,h);
            x := 0;
          End
      Else inc(x);
      if PtInRect(Rect(w*x+2,2+y,w*x+2+w-4,h+2+y-4),Point) then
        begin
        ARect:=Rect(w*x+2,2+y,w*x+2+w-4,h+2+y-4);
        Result:=i;
        exit;
        end;
    End;
end;
 
procedure TForm1.FormMouseDown(Sender:TObject;Button:TMouseButton;Shift:
  TShiftState;X,Y:Integer);
var ARect:TRect;
item:integer;
begin
  item:=ItemFromPoint(Point(X,Y),Arect);
  if item>-1 then
  begin
  Canvas.Brush.Color:=clred;
  Canvas.FillRect(ARect);
  ShowMessage(Inttostr(Item));
  Canvas.Brush.color := clLtGray;
  end;
end;
Der Code ist vollständig und läuft, allerdings nur eben runtergehackt.

FlashBurn
Beiträge: 12
Registriert: Mi 16. Jun 2010, 16:39

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von FlashBurn »

Ich hatte sowas ähnlich in Java auch, nur wollte ich nicht selbst berechnen ob der User nun nen Stein und dann noch welchen er getroffen hat ;) Aber das mit dem ARect sieht interessant aus. Das werde ich bei Gelegenheit mal probieren!

Danke!

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von theo »

Idealerweise würde man natürlich ein Array of Record oder eine TList halten, wo man dann die Rects und sonstige Eigenschaften der einzelnen Felder speichern würde. Dann wird das Feld-finden noch einfacher.
Alles schneller als ein Haufen Komponenten.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von pluto »

Du brauchst nichts zu "berechnen". Mach einfach alle "Steine" gleich groß. Ist das einfachste. Die verwaltest du einfach in ein 2D Array. Wenn der User jetzt klickt bekommst du die richtigen Positionen für das 2D Array über:
x div FeldBreite und y div FeldHöhe.

So einfach geht das. Zeichnen würde ich das in einer PaintBox und vielleicht sogar ein Buffer nutzen, aber das musst du sehen ob das notwendig ist.
MFG
Michael Springwald

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von Scotty »

Wieso nicht ein TDrawGrid benutzen?
Ansonsten sind mir letztlich auch eigenartige Phänomene unter W7 berichtet worden. Ein LM_Paint wird dort (zeitlich?) anders gehandhabt als unter XP. Ein workaround war, den Kompatibilitätsmodus zu aktivieren.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von pluto »

Ein LM_Paint wird dort (zeitlich?) anders gehandhabt als unter XP. Ein workaround war, den Kompatibilitätsmodus zu aktivieren.
Dann würde ich behaupten, dass Lazarus in diesen Fall "Unschuldig" ist.... Ich habe aber noch von ganz anderen "Sachen" gehört. MS macht einfach sein Windows von Version zu Version Inkompatibel zu einander. Um den Nutzer zu zwingen umzusteigen.
MFG
Michael Springwald

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Panels sehr langsam (beim Neuzeichnen)

Beitrag von Socke »

Ich melde mich zwischenzeitlich zu Wort, auch wenn ich zu den aktuellen Entwicklungen nichts sagen kann.

Performance: vielleicht wäre ein Form.BeginFormUpdate/Form.EndFormUpdate hilfreich, um evtl. irgendetwas während des Resizens auszuschalten. Sonst könnte alles bei jedem Panel neu gezeichnet werden, es reicht aber, wenn alles einmal gezeichnet wird. Über diese Methoden bin ich auch nur gerade gestolpert und bin mir deren Bedeutung/Funktion nicht bewusst.

Mit AnchorSide kann man jedem Anker ein anderes Steuerelement (TControl) zuordnen. Im Normalfall (wenn man also nur Anchors := [akXY] setzt), ist das einfach NIL und das Control bleibt dort wo es ist, richtet sich also nach dem Parent (in der Regel ein TForm). Mit TAnchorSide kann man aber auch sagen: Control A, richte deine rechte Seite an der linken Seite von Control B aus, dazu positionierst du dich bitte noch einer Horizontalen mit diesem. In Code sieht das so aus:

Code: Alles auswählen

ControlA.AnchorSide[akLeft].Side := asrLeft;
  ControlA.AnchorSide[akLeft].Control := ControlB;
  ControlA.AnchorSide[akTop].Side := asrCenter;
  ControlA.AnchorSide[akLeft].Control := ControlB;
Entsprechende Abstände können zusätzlich noch über Borderspacing gesetzt werden (also bitte 3 Pixel vom linken Rand von Control B entfernt).
Die Dokumentation (mit Text-Bildchen) gibts unter http://lazarus-ccr.sourceforge.net/docs ... rside.html
Damit kann man wunderbare Layouts zusammenbasteln; zu Fuß im Quelltext ist das aber ein wenig mühselig und schlecht lesbar, da man für jedes Control einige Zeilen (AnchorSides für 1-4 Seiten und Borderspacing für 1-4 Seiten) und in jeder Zeile steht jedesmal das gleiche drin, es ändern sich etwa 3 Werte (Ankerseite, Control und Anker-Control). Bequemer gehts über den IDE-Dialog (aber nur zur Design-Zeit), den man über "Ansicht -> Ankereditor anzeigen" oder den Objektinspektor (Eigenschaft: Align auswählen, dann auf den Butten mit den drei Punkten klicken) aufrufen kann.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten