![]() |
VCL Elemente in geblocktem Ereignishandler disablen
Moin.
Wie im Titel schon geschrieben möchte ich VCL Elemente (vier Buttons) in einer Ereignishandler eines Buttons disablen. Dieser Ereignishandler ist für eine gewisse Zeit geblockt und während dieser Zeit sollen die Buttons disabled sein. Da beim Blocken ja keine Window Messages verarbeitet werden können, habe ich es mit repaint, refresh und processmessages probiert. Alles ohne Erfolg:
Delphi-Quellcode:
Es wird nur der geklickte Button disabled. Alle anderen Buttons werde erst nach den fünf Sekunden disabled und sofort wieder enabled.
procedure TForm2.Button2Click(Sender: TObject);
begin button1.Enabled := false; button1.Refresh; button1.Repaint; button2.Enabled := false; button2.Refresh; button2.Repaint; button3.Enabled := false; button3.Refresh; button3.Repaint; button4.Enabled := false; button4.Refresh; button4.Repaint; Form2.Refresh; Form2.Repaint; Application.ProcessMessages; sleep(5000); button1.Enabled := true; button2.Enabled := true; button3.Enabled := true; button4.Enabled := true; end; Wie muss ich es richtig machen? |
AW: VCL Elemente in geblocktem Ereignishandler disablen
Vielleicht solltest du nicht Sleep verwenden, sondern z.B. einen Timer. Der blockiert den MainThread nicht und du hättest das, was du willst.
|
AW: VCL Elemente in geblocktem Ereignishandler disablen
Man kann mit der VCL nicht so umgehen, als ob jeder Aufruf einer Methode einen unmittelbaren Effekt hätte. Insbesondere die Methoden/Eigenschaften zur Veränderung des Aussehens (Enable, Visible, Caption etc.) sollten eher nach dem Motto: "Bitte ausführen, wenn die Anwendung mal wieder Zeit hat" gehandhabt werden.
So ein Formular wartet ja eigentlich immer, das der Anwender irgendwo raufklickt oder sonstwas anstellt. Und nur in der Zeit werden die o.g. Anforderungen an Layoutänderungen abgearbeitet. Man kann z.T. mit 'Update', 'Repaint' usw. das Neuzeichnen forcen, aber so richtig schick ist das nicht, da das Formular dann zwar u.U. statisch neu gezeichnet wird, aber nur einmalig. Du willst bei einem Buttonklick eine Aktion starten und solange diese Aktion läuft, soll der Button nicht klickbar sein? Aber das Fenster soll man ja noch verschieben dürfen, oder? Verwende einen Thread. Im OnClick des Start-Buttons startest Du dem Thread und disablest den Button. Dem Thread sagst Du, das er bei Beendigung (OnTerminate) den Button wieder enablen soll. Dann musst Du nur im OnClose-Ereignis des Formulars eine ggfs. aktive Instanz des Threads terminieren. |
AW: VCL Elemente in geblocktem Ereignishandler disablen
Das ganze ist für kleines Tool eine Quick and Dirty Lösung. Das sleep ist hier nur ein Platzhalter. Eigentlich wird eine Funktion aufgerufen die für eine gewisse Zeit blockiert...
Habe für das Tool eigentlich keine Lust mit mehreren Threads zu hantieren. Mit ist klar, dass das Fenster für die Zeit nicht verschiebbar bzw. für Benutzereingaben nicht empfänglich ist. Es soll durch das disablen nur eine optisches Feedback gegeben werden, dass das Tool beschäftigt ist. Zitat:
|
AW: VCL Elemente in geblocktem Ereignishandler disablen
Also bei mir funktioniert es, allerdings ohne das ganze Repaint/Refresh-Gedöns.
Im Zweifelsfall rufst Du in deiner Schleife immer mal wieder Application.Processmessages auf. |
AW: VCL Elemente in geblocktem Ereignishandler disablen
SO sollte das aussehen:
Delphi-Quellcode:
procedure TForm2.EnableButtons(en:Boolean);
begin button1.Enabled := en; button2.Enabled := en; button3.Enabled := en; button4.Enabled := en; end; procedure TForm2.MachDieArbeit; var i : Integer; begin for i:= 1 to ANZAHL_HAARE_IM_WASCHBECKEN do begin // der "Trick" ist, immer mal wieder Application.ProcessMessages aufzurufen // um die GUI upzudaten und auf Messages zu reagieren // Macht man dies aber zu oft, dann verlängert sich die Gesamtzeit // mit der Modulo-Abfrage kann man die Anzahl der Aufrufe entsprechend reduzieren // es kommt halt immer auf den konkreten Fall an if (i mod 10) = 0 then Application.ProcessMessages; Sleep(20); // Platzhalter für blockierenden Code end; end; procedure TForm2.Button2Click(Sender: TObject); begin EnableButtons(False); try MachDieArbeit; finally EnableButtons(True); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz