[gelöst] CheckBox reagiert nicht, bzw. zu spät

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

[gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Hallo,
möchte in meinem Programm eine CheckBox: TCheckBox verwenden.
Die CheckBox soll auf Linksklick reagieren, dh. Häkchen (j/n) umschalten.

Ich hab jetzt im Programm eine for..do Schleife die ca. 5sec braucht.
Während dieser 5sec reagiert die CheckBox nicht auf Clicks.
Möchte den Status der CheckBox aber genau in diesem Zeitraum umschalten.
Was könnte ich da machen ?
Zuletzt geändert von oliver2104 am Fr 16. Dez 2022, 13:24, insgesamt 1-mal geändert.

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

Re: CheckBox reagiert nicht, bzw. zu spät

Beitrag von theo »

Hmm, riecht für mich etwas nach Holzweg, aber mach mal in die Schleife: Application.ProcessMessages

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

Re: CheckBox reagiert nicht, bzw. zu spät

Beitrag von wp_xyz »

Was passiert denn innerhalb dieser 5 sek? Bekommt die Anwendung überhaupt die Gelegenheit, die Checkbox neu auszugeben? Wenn du nämlich in deinem Code die Anweisung "Checkbox.Checked := true" hast, so wird diese nicht sofort ausgeführt, sondern wird erstmal als Befehl in der Nachrichtenwarteschlage des Betriebssystems abgelegt, und erst wenn nichts mehr zu tun ist, wird die Warteschlange abgearbeitet. Während der Laufzeit einer For-Schleife ist aber das System normalerweise ununterbrochen beschäftigt. Du kannst aber die Arbeitung der Warteschlange erzwingen, wenn du "Application.ProcessMessages" aufrufst. Also, wenn in deiner langen Rechnung irgendwann der Zustand der checkbox geändert wird, das danach aufrufen, so dass die Änderung gleich sichtbar wird:

Code: Alles auswählen

for i := 0 to MAX do
begin
  // rechne irgendwas
  if (Ergebnis > 0) and not Checkbox.Checked then begin
    Checkbox.Checked := true;
    Application.ProcessMessages;
  end;
end;
Aber sparsam einsetzen, sonst werden aus den 5 Sekunden gleich 50 (jede kleinste Mausbewegung hinterlässt eine Vielzahl von Nachrichten in der Warteschlage).

oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

Re: CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Eigentlich gehts um Datenvisualisierung.
Bekomme von einem Raspberry Pico alle 5ms einen Integerwert.
Möchte in der for..do Schleife 1000 Werte einlesen, dauert eben ca. 5sec
Diese Werte möchte zu Pixelkoordinaten umformen und in einem TImage ausgeben.
Mein TImage hat eine Breite von 1000 Pixel (x-Koordinate, Anzahl der eingelesenen Werte)
Die jeweilige y-Koordinate entspricht dann der Höhe des gelieferten Werts.

Damit man den Aufbau der Kurve Pixel für Pixel betrachten kann,
verwende ich in der for..do Schleife den Befehl

Code: Alles auswählen

Image.Refresh;
So wird das Image aktualisiert und jedes neue Pixel sofort sichtbar.
Sowas ähnliches bräuchte ich auch für die CheckBox.
Die CheckBox soll eine Bearbeitung der y-Werte triggern. (zb. Filter anwenden )
Möchte die Auswirkung der CheckBox sofort sehen, also wenn das Image Pixel für Pixel aufgebaut wird.

Code: Alles auswählen

Application.ProcessMessages;
innerhalb der for..do Schleife hat das geleistet.
Vielen Dank !!!

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von af0815 »

Wozu in einer Schleife. Werte einlesen kann ich auch in einem Event und dann mitzählen wann 1000 erreicht sind. Da brauche ich nicht 5 sek. alles blockieren.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Danke für die Antwort, bin froh über jeden Verbesserungsvorschlag.
Hab aber keine Ahnung wie ich deinen Vorschlag umsetzen soll.
Mein Problem war ja, das die CheckBox nicht sofort auf das Event OnClick reagiert hat.
Ein Event das mir sagt, wenn ein neuer Wert ausgelesen werden kann, kenn ich nicht.
Kann man sowas selbst definieren ?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von af0815 »

oliver2104 hat geschrieben:
Sa 17. Dez 2022, 13:04
Ein Event das mir sagt, wenn ein neuer Wert ausgelesen werden kann, kenn ich nicht.
Kann man sowas selbst definieren ?
Du hast aber auch noch nirgends verraten, wie du deine Werte bekommst bzw. ausliest :-) Du hast nur verraten das du von einem RasPi alle 5ms einen Wert bekommst, aber nicht wo deine Applikation läuft und wie dei Werte übertragen werden.

Normal löste man sowas, indem man die Werte nicht blockierend für den Hauptprozess ausliest und wenn alle Werte vorhanden sind, einen Event für den Hauptthread auslöst. DIeser kann dann anzeigen, während die Daten im Hintergrund weiter gesammelt werden.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Ausgelesen werden die Pico Werte durch eine function LiesZeile (mit Rückgabewert String) innerhalb der for..do Schleife.
Der Pico (auf serieller Schnittstelle) sendet nicht wirklich Integerwerte, sondern Char für Char nacheinander.
Die einzelnen Werte bewegen sich zwischen $30 und $39 (ASCII für Ziffern 1-9) und ein $0A (ASCII für NewLine)
markiert das Ende einer Sendezeile. Die einzelnen Char-Werte bauen dann den Rückgabestring auf, der
dann nur mehr zu Integer umgewandelt werden muß.

Die function LiesZeile innerhalb der for..do Schleife, stopt die Schleife bis ein Wert zum plotten vorhanden ist.
Ich denke die function LiesZeile baut Werte schneller auf als sie vom RasPi angeliefert werden.
Also das dürfte kein Problem sein.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von af0815 »

Also über die serielle Schnittstelle kommen die Daten. Und du liest sie blockierend aus.

Normalerweise hat die serielle Komponente die Möglichkeit das ganze über einen Event zu arbeiten. Daher immer wenn etwas ankommt so wird der Event gefeuert und man kann die Daten abholen. Damit ist man nicht in einer Schleife gefangen und blockiert alles. Man kann jetzt ganz einfach Zeichen für Zeichen lesen, das zwischenspeichern und wenn das NewLine erkannt wird, dann die Daten gesammelt übergeben. Das ist bei manchen Komponenten sogar konfigurierbar nur bei einem NewLine den Event auszulösen.

Der Plotter wartet wiederum bis der Datenevent ausgelöst wurde, verarbeitet die Daten und zeigt sie an.

Somit ist alles Eventgesteuert und dein RasPi ist genaugenommen fast immer im Leerlauf und blockiert nichts.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von fliegermichl »

Ich würde das mit einem separaten Thread lösen. Der darf gern blockierend auslesen und übergibt die eingelesenen Daten an den Mainthread.

Code: Alles auswählen

interface
type

  { TReaderThread }

  TReaderThread = class ( TThread )
  private
    fgelesen : string;
    procedure LiesPort;
    procedure Uebergabe;
  public
    procedure Execute; override;
  end;

implementation

procedure TReaderThread.LiesPort;
var c : Char;
begin
  c := ReadCharFromSerial;
  if c = #$0A then Synchronize(Uebergabe) else
   fGelesen := fGelesen + c;
end;

procedure TReaderThread.Uebergabe;
begin
  Form1.Memo1.Lines.Add(fGelesen); // Zugriffe auf Variablen des MainThreads dürfen nur aus Methoden erfolgen, welche per Synchronize aufgerufen wurden.
  fGelesen := '';
end;

procedure TReaderThread.Execute;
begin
 while not Terminated do
 begin
   LiesPort;
 end;
end;
Der gezeigte Code ist nicht ganz vollständig (Die Funktion die vom Seriellen Port liest), zeigt aber, wie man die Kommunikation mit dem HauptThread der Anwendung machen kann.

oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Danke für eure Antworten !
Also über die serielle Schnittstelle kommen die Daten. Und du liest sie blockierend aus.
Bin schon froh, es geschafft zu haben, überhaupt irgendwas auszulesen.
Verwende zum Auslesen die Unit Serial (funktioniert unter Win und Linux)
Das ist aber gar keine Komponente mit Events (glaub ich zumindest).
Hab diese Unit verwendet, um die Grundlagen der seriellen Schnittstelle zu verstehen.
Das war für mich Neuland und eigentlich bin ich ganz zufrieden so wie's jetzt läuft.

Meinst du mit serieller Komponente Synaser ?
Das müsst ich mir erst genauer anschauen, ebenso wie Programmierung mit Threads.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von af0815 »

oliver2104 hat geschrieben:
Mo 19. Dez 2022, 12:33
Meinst du mit serieller Komponente Synaser ?
Das müsst ich mir erst genauer anschauen, ebenso wie Programmierung mit Threads.
Synaser hat das eingebaut was du brauchst, da kommst du ohne Threads aus.

Im OPM gibt es LazSerial, die kapselt dir alles, auch synaser und ist sehr Anwenderfreundlich.
Komponente auf die Form bringen, Parameter im OI einstellen und den OnRxData Event erzeugen.
Im OnRXData liest du einfach alles herein, bis du im String dein 0A findest.

Aber wenn der Pico ein CRLF senden würde, so könntest du RcvLineCRLF und würdest immer einen kompletten String erhalten. Das kann die Komponente von alleine (Genaugenommen Synaser und der kann noch vieles mehr).

Synaser und LazSerial verstecken auch das Betriebssystem vor dir. Das heistt der Code läuft dann unter Windows genauso, wie unter Linux und den RasPi.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

oliver2104
Beiträge: 22
Registriert: Sa 26. Dez 2020, 13:22

Re: [gelöst] CheckBox reagiert nicht, bzw. zu spät

Beitrag von oliver2104 »

Nochmals danke für die Anregungen !
Es ging ja nur um die CheckBox und das passt jetzt
Werd mir Synaser und LazSerial aber für später merken.
Zur Zeit bin ich schwer beschäftigt mit der "Signal to Noise Ratio" die im RasPi ADC Converter ankommt.
Aber dieses Problem gehört hier nicht her.
L.G.

Antworten