Eigene Komponente und Repaint

Rund um die LCL und andere Komponenten
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Eigene Komponente und Repaint

Beitrag von Mathias »

Von meinem ColorString, will ich ein Memo machen.

Nun habe ich 2 Probleme.

Wie kann ich es machen, wen ich meine ColorStringListe um Einträge ergänze, das die in meinem Panel aktualisiert werden.

Code: Alles auswählen

ColorMemo.Lines.Add('He....


Als Test habe ich einen Print-Button, welcher die Anzeige im Panel manuell aktualisieren soll, nur bleibt da die Ausgabe in einer Endlosschleife hängen. Unter Windows sieht man dies besser als unter Linux.

Die Ausgabe soll bei meinem TColorMemo kommen, welches von TCustomPanel abgeleitet ist.
Ich denke, man muss da irgendwie das Add abfangen.

Weis jemand einen Rat ? :?:
Dateianhänge
TList_ColorString.zip
(126.18 KiB) 56-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Eigene Komponente und Repaint

Beitrag von Michl »

Du änderst im OnPaint vom TPanel den TPanel.Font, damit wird ein Neuzeichnen des Panels angeregt. Sicherlich wolltest du nur die Farbe vom TPanel.Canvas.Font ändern.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigene Komponente und Repaint

Beitrag von wp_xyz »

Wow! Das habe ich nicht gesehen!

Requion
Beiträge: 106
Registriert: Mi 3. Feb 2016, 09:39
OS, Lazarus, FPC: Linux(Arch Linux(+ARM)/Minibian) (L 1.6.0 FPC 3.0.0)
CPU-Target: 32/64Bit,ARM(RPi)
Wohnort: nahe Grimma

Re: Eigene Komponente und Repaint

Beitrag von Requion »

wp_xyz hat geschrieben:Wow! Das habe ich nicht gesehen!

Und ich wusste nicht das eine Änderung am Font ein neuzeichnen anregt.

Michl hat geschrieben:Du änderst im OnPaint vom TPanel den TPanel.Font, damit wird ein Neuzeichnen des Panels angeregt. Sicherlich wolltest du nur die Farbe vom TPanel.Canvas.Font ändern.

Sind das Erfahrungswerte oder kann man solche Infos nachlesen (und wenn ja wo?) oder muss man das einfach wissen?
Ich bin ja auch noch am lernen und möchte mich verbessern.
Mfg Requion

Das beste an Standards ist, dass es so viele davon gibt.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigene Komponente und Repaint

Beitrag von wp_xyz »

Requion hat geschrieben:Und ich wusste nicht das eine Änderung am Font ein neuzeichnen anregt.

TFont besitzt ein Ereignis OnChange, das immer dann feuert, wenn sich eine Font-Eigenschaft ändert. Die Klassen, die einen Font verwenden, haben in der Regel einen Eventhandler für dieses Ereignis, das ein Neuzeichnen bewirkt.

Requion hat geschrieben:Sind das Erfahrungswerte oder kann man solche Infos nachlesen (und wenn ja wo?) oder muss man das einfach wissen?
Ich bin ja auch noch am lernen und möchte mich verbessern.

Ich glaube nicht, dass es dazu eine Dok gibt. Lies hier im Forum, und auch im englischen Forum. Schreibe viele Programme, versuche z.B. die Probleme, die die Leute im Forum beschreiben, nachzuvollziehen. Mache viele Fehler. Aus Erfahrung wird man klug. Und: Programmieren lernt man nicht innerhalb einer Woche.

Requion
Beiträge: 106
Registriert: Mi 3. Feb 2016, 09:39
OS, Lazarus, FPC: Linux(Arch Linux(+ARM)/Minibian) (L 1.6.0 FPC 3.0.0)
CPU-Target: 32/64Bit,ARM(RPi)
Wohnort: nahe Grimma

Re: Eigene Komponente und Repaint

Beitrag von Requion »

wp_xyz hat geschrieben:
Requion hat geschrieben:Und ich wusste nicht das eine Änderung am Font ein neuzeichnen anregt.

TFont besitzt ein Ereignis OnChange, das immer dann feuert, wenn sich eine Font-Eigenschaft ändert. Die Klassen, die einen Font verwenden, haben in der Regel einen Eventhandler für dieses Ereignis, das ein Neuzeichnen bewirkt.

Okay, danke für die Erklärung :). Wieder was dazugelernt.

wp_xyz hat geschrieben:
Requion hat geschrieben:Sind das Erfahrungswerte oder kann man solche Infos nachlesen (und wenn ja wo?) oder muss man das einfach wissen?
Ich bin ja auch noch am lernen und möchte mich verbessern.

Ich glaube nicht, dass es dazu eine Dok gibt. Lies hier im Forum, und auch im englischen Forum. Schreibe viele Programme, versuche z.B. die Probleme, die die Leute im Forum beschreiben, nachzuvollziehen. Mache viele Fehler. Aus Erfahrung wird man klug. Und: Programmieren lernt man nicht innerhalb einer Woche.

Das hatte ich schon gemerkt :D. Ich beschäftige mich auch schon länger als eine Woche damit. Ich merk ja auch wie ich immer wieder neu Dinge lerne und Probleme löse die ich vor X Monaten/Jahren für unlösbar befunden hätte.
Das lesen ist nicht das Problem. Und ich hab begriffen das auch Eigenmotivation dazu gehört (also das ich mich auch privat damit beschäftige und nicht nur auf Arbeit).
Nur die Sache mit den vielen Programmen schreiben klappt nicht so recht. Bisher hatte ich entweder keine Ideen oder es waren dann Dinge die zu schnell zu komplex geworden wären (Bsp.: als blutiger Anfänger nen IRC Client).
Mfg Requion

Das beste an Standards ist, dass es so viele davon gibt.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Eigene Komponente und Repaint

Beitrag von Michl »

Requion hat geschrieben:Sind das Erfahrungswerte oder kann man solche Infos nachlesen (und wenn ja wo?) oder muss man das einfach wissen?
Ich bin ja auch noch am lernen und möchte mich verbessern.
Meine 2 Cents:

Ich bin Freizeitprogrammierer, ein schlechter Theoretiker und auch ständig am lernen. Wahrscheinlich bin ich einer hier im Forum, der am wenigsten allgemeine Fachliteratur gelesen hat (wenn ich Zeit habe lese ich lieber mal einen guten Roman). Wenn ich ein kongretes Problem habe, war mir das Netz in den letzten Jahren ein guter Ratgeber. Allerdings sollte man Englisch halbwegs verstehen können.

Die Dokumentation der Windows API finde ich recht gut, Ratschläge von stackoverflow sind oft zielführend oder ich wühle mich durch Foren. Das meiste Wissen habe ich mir durch Learning by doing und immer wieder kleiner Testprojekte erarbeitet.

Allerdings, um so einen Bug zu finden (derartige Schusseligkeiten passieren mir auch), sollte man mit dem Debugger umgehen können, mal einen Breakpoint setzen, sich den Aufrufstack anzeigen lassen oder/und auch Ausgaben in der Console machen.

Ansonsten ist es mMn immer sinnvoll ein kleines Testprojekt zu erstellen, um Dinge auszuprobieren. Wenn man dabei nicht weiter kommt, besteht z.B. hier im Forum die Möglichkeit, sich mit anderen Programmierern und alten Hasen zu unterhalten. Das hat mir nach einer recht langen Programmier-Pause den Wiedereinstieg sehr vereinfacht.

Gerne versuche ich auch Lösungen für mir völlig fremde Probleme anderer Forenuser zu finden, da anderer Code, andere Lösungsansätze und andere Aufgabenstellungen den eigenen Horizont erweitern.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigene Komponente und Repaint

Beitrag von Mathias »

Michl hat geschrieben:Du änderst im OnPaint vom TPanel den TPanel.Font, damit wird ein Neuzeichnen des Panels angeregt. Sicherlich wolltest du nur die Farbe vom TPanel.Canvas.Font ändern.

Das Problem mit der Endlos-Schleife ist jetzt gelöst. Danke.

Was aber noch nicht geht, ist ein Repaint bei Add.

Ich habe nun Lines in ein propety gesetzt. Nur komischerweise wird bei Add(.. GetLine und nicht SetLines aufgerufen.
Das wäre nicht so schlimm, aber es wird immer eine Zeile zu wenig geschrieben. GetLines wird auch bei jedem Klick 2x aufgerufen.

Klicke ich aber auf Print, dann werden alle Zeilen geschrieben, somit müsste die Methode Paint in Ordnung sein.
Dateianhänge
TList_ColorString.zip
(126.63 KiB) 42-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigene Komponente und Repaint

Beitrag von wp_xyz »

Mathias hat geschrieben:Was aber noch nicht geht, ist ein Repaint bei Add.

Mach's doch so wie bei der "echten StringList: Gib der Liste ein Event OnChange (Typ TNotifyEvent), das bei jeder Listenänderung ausgelöst wird, insbesondere bei "Add". Dein Memo implementiert dann einen Eventhandler, der ein Neuzeichnen veranlasst. Der Eventhandler wird im Konstructor des Memo an die Liste eingehängt. Etwa so (nicht getestet):

Code: Alles auswählen

type
  TColorStringList = class(TList)
  private
    FOnChange: TNotifyEvent;
  ...
  public
    function Add(s: String; c: TColor): Integer;
    ...
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;
 
  TColorMemo = class(TCustomPanel)
  private
    FLines: TColorStringList;
    procedure LinesChanged(Sender: TObject);
    ...
  public
    constructor Create(AOwner: TComponent); override;
    ...
  end;
 
  function TColorStringList.Add(s: String; c: TColor): Integer;
  begin
    ...
    if Assigned(FOnChange) then FOnChange(self);
  end;
 
  constructor TColorMemo.Create(AOwner: TComponent); override;
  begin
    inherited Create(AOwner);
    ...
    FLines := TColorStringList.Create;
    FLines.OnChange := @LinesChanged;
  end;
 
  procedure TColorMemo.LinesChanged(Sender: TObject);
  begin
    Invalidate;
  end;
 

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigene Komponente und Repaint

Beitrag von Mathias »

Danke, jetzt geht dies auch.

Für was ist diese property ?

Code: Alles auswählen

property OnChange: TNotifyEvent read FOnChange write FOnChange;   

würde dies nicht auch mit

Code: Alles auswählen

OnChange: TNotifyEvent;

gehen ?
Oder willst du damit einfach auf direkte Bezeichner im Public-Teil verzichten ?

Was ist eigentlich der Unterschied zwischen

Code: Alles auswählen

Invalidate;
Refresh;
Repaint;

?



Schreibe viele Programme, versuche z.B. die Probleme, die die Leute im Forum beschreiben, nachzuvollziehen. Mache viele Fehler. Aus Erfahrung wird man klug. Und: Programmieren lernt man nicht innerhalb einer Woche.
Da muss ich voll zustimmen.
Dateianhänge
TList_ColorString.zip
(126.51 KiB) 44-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigene Komponente und Repaint

Beitrag von wp_xyz »

Mathias hat geschrieben:würde dies nicht auch mit

Code: Alles auswählen

OnChange: TNotifyEvent;
gehen ?

Klar, da habe ich nicht dran gedacht, dass TList ja selbst schon ein OnChange hat.

Mathias hat geschrieben:Was ist eigentlich der Unterschied zwischen

Code: Alles auswählen

Invalidate;
Refresh;
Repaint;

Zwischen Refresh und Repaint keiner. Beide bewirken eine sofortige Ausgabe. Invalidate dagegen reiht den Befehl zum Neuzeichnen in die Ereigniswarteschlange des Betriebssystems ein, d.h. es wird nicht sofort ausgeführt, sondern verzögert. Dabei wird (ich hoffe das stimmt jetzt...) berücksichtigt, ob dasselbe Objekt schon mehrfach einen Paint-Befehlt eingereiht hat, so dass nur eine einzige Paint-Aktion stattfindet. Also: In 99% aller Fälle ist Invalidate die bessere Wahl. In den Settern von 10 Properties von visuellen Komponenten kannst du daher bedenkenlos Invalidate aufrufen, weil das objekt nur 1x neu gezeichnet wird. Bei Repaint/Refresh würde sich das Object 10x übermalen.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigene Komponente und Repaint

Beitrag von Mathias »

Mathias hat geschrieben:
würde dies nicht auch mit
CODE: ALLES AUSWÄHLEN
OnChange: TNotifyEvent;
gehen ?

Klar, da habe ich nicht dran gedacht, dass TList ja selbst schon ein OnChange hat.

Ich habe eher gedacht, wieso OnChange nicht direkt in Public deklarierst.
Oder hat das auch damit zu tun, das man es vermeiden soll, Bezeichner direkt im Public-Teil zu deklarieren ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Eigene Komponente und Repaint

Beitrag von m.fuchs »

Mathias hat geschrieben:Ich habe eher gedacht, wieso OnChange nicht direkt in Public deklarierst.
Oder hat das auch damit zu tun, das man es vermeiden soll, Bezeichner direkt im Public-Teil zu deklarieren ?

Du meinst Felder bzw. Variablen, nicht Bezeichner. Ja, die lässt man im allgemeinen private und greift nur mit Hilfe einer Property von Außen auf sie zu.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Eigene Komponente und Repaint

Beitrag von wp_xyz »

wp_xyz hat geschrieben:
Mathias hat geschrieben:würde dies nicht auch mit

Code: Alles auswählen

OnChange: TNotifyEvent;
gehen ?

Klar, da habe ich nicht dran gedacht, dass TList ja selbst schon ein OnChange hat.

Nein, das war schon richtig, TList hat kein OnChange-Ereignis.Stattdessen könnte man über Observer mit der Liste kommunizieren:
* procedure FPOAttachObserver(AObserver: TObject),
* procedure FPODetachObserver(AObserver: TObject);
* procedure FPONotifyObservers(Sender: TObject; AOperation: TFPObservedOperation; Data: Pointer).

Warum OnChange nicht direkt als Variable im public-Teil steht, hat m.fuchs schon erklärt. Ich mache das eigentlich nie, weil dies einer späteren Verwendung als published property im Objekt Inspector im Wege steht (auch wenn's hier eher unwahrscheinlich ist - aber man weiß nie...)

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Eigene Komponente und Repaint

Beitrag von Michl »

wp_xyz hat geschrieben:Warum OnChange nicht direkt als Variable im public-Teil steht, hat m.fuchs schon erklärt.
...weitere Vorteile von Properties: Wenn man später merkt, daß der Bezeichner doch eher nur gelesen werden werden darf, kann man dies einfach ändern oder unkompliziert auf Getter und Setter umändern.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Antworten