[gelöst] onClick nur einmal..

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
atroesch
Beiträge: 62
Registriert: Mo 7. Jul 2025, 10:05

[gelöst] onClick nur einmal..

Beitrag von atroesch »

Ich habe eine grafik mit onClick procedure.
ich will das während die procedure durchläuft
kein weiterer onclick möglich ist.
scheint unmöglich....

erster versuch: die grafik am anfang der procedure auf enabled:=false, am ende wieder auf true..
geht nicht. also dachte ich ok, nehm ich den code der durchlaufen werden soll aus der onclick procedure
raus und in eine eigene. geht auch nicht.

zweiter versuch: ich lege nach dem onclick eine andere grafik drüber und lösche sie nach dem durchlaufen wieder, auch nix.

dritter versuch: die grafik auf ein panel, bei onclick das panel disabled, danach wieder enabled, nix..

vierter versuch: onclick auf nil, nach dem durchlauf wieder auf die @procedure... auch nix..

wie mche ich es nun richtig?
Zuletzt geändert von atroesch am Fr 24. Okt 2025, 20:28, insgesamt 1-mal geändert.

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

Re: onClick nur einmal..

Beitrag von theo »

Wie testest du das?

Bei mir geht das so problemlos:

Code: Alles auswählen

procedure TForm1.Image1Click(Sender: TObject);
begin
  Image1.OnClick:=nil;
  Sleep(2000);
  Memo1.Lines.Add(TimeToStr(Now));
  Application.ProcessMessages;
  Image1.OnClick:=@Image1Click;
end;  
Linux, GTK2

atroesch
Beiträge: 62
Registriert: Mo 7. Jul 2025, 10:05

Re: onClick nur einmal..

Beitrag von atroesch »

:lol:
Application.ProcessMessages;

Danke...

Benutzeravatar
Zvoni
Beiträge: 468
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: [gelöst] onClick nur einmal..

Beitrag von Zvoni »

Sofern das keine Multithread-Anwendung, müsste der Code in OnClick doch die Message-Queue der GUI blockieren, oder?
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6984
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] onClick nur einmal..

Beitrag von af0815 »

Zvoni hat geschrieben: Mo 27. Okt 2025, 08:58 Sofern das keine Multithread-Anwendung, müsste der Code in OnClick doch die Message-Queue der GUI blockieren, oder?
Meiner Erfahrung nach -> Nein, nicht unbedingt. Ist auch vom BS abhängig.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: [gelöst] onClick nur einmal..

Beitrag von theo »

Zvoni hat geschrieben: Mo 27. Okt 2025, 08:58 Sofern das keine Multithread-Anwendung, müsste der Code in OnClick doch die Message-Queue der GUI blockieren, oder?
Das OS-GUI und deine App sind ja heute unterschiedliche Threads.
Weil es eben eine Queue ist, sammelt das OS die Nachrichten an deine Anwendung, welche diese dann bei Gelegenheit abholt.
Mit Application.ProcessMessages leerst du Quasi die Queue.
Bin nicht sicher, ob das so technisch korrekt beschrieben ist, aber so erkläre ich mir das.
Klar scheint, dass ohne Application.ProcessMessages du die Mehrfach-Clicks nachgereicht bekommst.

Benutzeravatar
Zvoni
Beiträge: 468
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: [gelöst] onClick nur einmal..

Beitrag von Zvoni »

theo hat geschrieben: Mo 27. Okt 2025, 12:01
Zvoni hat geschrieben: Mo 27. Okt 2025, 08:58 Sofern das keine Multithread-Anwendung, müsste der Code in OnClick doch die Message-Queue der GUI blockieren, oder?
Das OS-GUI und deine App sind ja heute unterschiedliche Threads.
Weil es eben eine Queue ist, sammelt das OS die Nachrichten an deine Anwendung, welche diese dann bei Gelegenheit abholt.
Mit Application.ProcessMessages leerst du Quasi die Queue.
Bin nicht sicher, ob das so technisch korrekt beschrieben ist, aber so erkläre ich mir das.
Klar ist, dass ohne Application.ProcessMessages du die Mehrfach-Clicks nachgereicht bekommst.
Da hab ich mich vielleicht falsch ausgedrückt:
"müsste der Code in OnClick doch die Message-Queue des Formulars blockieren, oder?"

Mir gings eher um das ursprüngliche Problem, so wie ich OP verstanden habe:
Er clickt auf sein Bild, und will verhindern, dass WÄHREND seine OnClick-Prozedur läuft, nochmal geclickt werden kann (and er damit einen Reentrance bekommt).
Das würde nur passieren, wenn er denn tatsächlich die Messages in der Queue abholt innerhalb seiner OnClick.

Oder will er generell verhindern, dass wenn der User mehrfach auf das Bild clickt, dass der Code dann im Nachhinein nochmal ausgeführt wird?
Weil das ist für mich die einzige Erklärung für deinen Ansatz mit dem Nil-en des Event-Handlers, aber innerhalb des Codes dann die Queue leer zu machen
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6984
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] onClick nur einmal..

Beitrag von af0815 »

theo hat geschrieben: Mo 27. Okt 2025, 12:01
Zvoni hat geschrieben: Mo 27. Okt 2025, 08:58 Sofern das keine Multithread-Anwendung, müsste der Code in OnClick doch die Message-Queue der GUI blockieren, oder?
...
Klar ist, dass ohne Application.ProcessMessages du die Mehrfach-Clicks nachgereicht bekommst.
Bei Windows ist der Queuce Scheduler angehalten mehrfache gleiche Paint Einträge zusammenzufassen und als einen Auszuliefern.

https://learn.microsoft.com/de-de/windo ... age-queues sieh Nachrichten in der Warteschlange.

Zitat:
Die WM_PAINT Nachricht, die WM_TIMER Nachricht und die WM_QUIT Nachricht werden jedoch in der Warteschlange beibehalten und nur dann an die Fensterprozedur weitergeleitet, wenn die Warteschlange keine anderen Nachrichten enthält. Darüber hinaus werden mehrere WM_PAINT Nachrichten für dasselbe Fenster in einer einzelnen WM_PAINT Nachricht kombiniert, wodurch alle ungültigen Teile des Clientbereichs in einem einzelnen Bereich konsolidiert werden. Durch das Kombinieren WM_PAINT Nachrichten wird die Anzahl der Wiederholungen reduziert, mit denen ein Fenster den Inhalt des Clientbereichs neu zeichnen muss.
Das heisst im Umkehrschluss, das es doppelte OnClick (und andere) geben kann. Ich gehe daher schon öfters her und mache mir ein Sperrbit. Ist das gesetzt, steige ich sofort aus der Routine aus. Das Bit über try/finally natürlich absichern.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: [gelöst] onClick nur einmal..

Beitrag von theo »

Zvoni hat geschrieben: Mo 27. Okt 2025, 12:30 Oder will er generell verhindern, dass wenn der User mehrfach auf das Bild clickt, dass der Code dann im Nachhinein nochmal ausgeführt wird?
So habe ich das verstanden. Jedenfalls scheint er mit der Lösung zufrieden zu sein, was die Frage eigentlich beantwortet. :wink:

atroesch
Beiträge: 62
Registriert: Mo 7. Jul 2025, 10:05

Re: [gelöst] onClick nur einmal..

Beitrag von atroesch »

Oder will er generell verhindern, dass wenn der User mehrfach auf das Bild clickt, dass der Code dann im Nachhinein nochmal ausgeführt wird?
Ja genau das war das Problem.
Ist aber mit der Antwort von Theo und Application.ProcessMessages; gelöst.
Danke nochmal...

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

Re: [gelöst] onClick nur einmal..

Beitrag von Mathias »

Ich hätte dies ein wenig anders gelöst.
Einfach den EventHandle sicheren und dieser nachher wieder zurück geben.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  oldhandle: TNotifyEvent;
begin
  oldhandle := Button1.OnClick;
  Button1.OnClick := nil;
  Sleep(2000); // Mache irgend etwas
  Application.ProcessMessages;
  Button1.OnClick := oldhandle;
end;     
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

atroesch
Beiträge: 62
Registriert: Mo 7. Jul 2025, 10:05

Re: [gelöst] onClick nur einmal..

Beitrag von atroesch »

es ging um dieses Spiel:
viewtopic.php?t=17406

wenn man auf den Würfelbecher geklickt hat,
konnte man den nochmal anklicken bevor der Wurf beendet war.

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

Re: [gelöst] onClick nur einmal..

Beitrag von wp_xyz »

wenn man auf den Würfelbecher geklickt hat,
konnte man den nochmal anklicken bevor der Wurf beendet war.
Das würde ich mit einer Statusvariablen, z.B. "WuerfelnAktiv", lösen. Durch diese wird der Klick auf den Würfelbecher gesperrt und erst dann wieder freigegeben, wenn die eigentliche Würfel-Prozedur ausgeführt ist und die Statusvariable wieder zurückgesetzt hat.

Ungetestet:

Code: Alles auswählen

type
  TForm1 = class(TForm)
    procedure WuerfelBecherClick(Sender: TObject); 
  private
    WuerfelnAktiv: Boolean;
    procedure Wuerfeln;
  end;
  
procedure TForm1.WuerfelBecherClick(Sender:TObject);
begin
  if not WuerfelnAktiv then
  begin
    WuerfelnAktiv := true;
    Wuerfeln;
  end;
end;

procedure TForm1.Wuerfeln;
begin
  if WuerfelnAktiv then exit;
  // Hier Code für das Würfeln
  WuerfelnAktiv := false;
end;

Antworten