![]() |
User klicken unterbinden während Querry läuft
Hallo zusammen,
ich habe ein Form wo in einem Memofeld ein SQL-Statement geschrieben werden kann, und das dann auf Knopfdruck ausgeführt wird indem es an eine TADOQuerry übergeben wird. Die Daten werden dann in einem DBGrid angezeigt. Funktioniert alles soweit ganz gut. Es gibt aber Selects, die ganz schön lange laufen, unter Umständen Minuten. Ich möchte verhindern, dass der User in der Zeit wild auf dem Form rumklickt. Z.Zt. ist es so, dass der User auf irgendwelche Buttons klicken kann, aber nichts passiert, während die Querry läuft. Aber danach werden alle diese Klicks mit Verspätung ausgeführt. Das möchte ich aber so nicht. Es soll auf keinen Klick reagiert werden, der geschieht, während die Querry läuft. Ich hab schon versucht die ActionList auf asSuspended zu setzen und später dann auf asNormal zurück aber das Hilft nicht. Vllt. hab ich es aber auch an falscher Stelle getan? Quelle ist die TADOQuerry:
Code:
Hat wer eine Idee, warum das nicht klappt?
Quelle.SQL.Clear;
Quelle.SQL.Text:= Memo1.Lines.Text; try ActionList1.State:= asSuspendedEnabled; Quelle.Open; Application.ProcessMessages; ActionList1.State:= asNormal; Danke, Jumpy |
AW: User klicken unterbinden während Querry läuft
Form1.Enabled := false;
und danach wieder auf true |
AW: User klicken unterbinden während Querry läuft
... und dazu dann noch den Cursor auf crSQLWait oder crHourGlass setzen und anschließend wieder zurück.
Dann sieht der Anwender gleich, dass er warten soll. |
AW: User klicken unterbinden während Querry läuft
Ich würde nicht das ganze Form deakivieren, sondern nur die Schaltfläche.
|
AW: User klicken unterbinden während Querry läuft
Danke erstmal. Das Problem ist halt, dass es massig andere Buttons auf dem Form gibt, und ich nicht 20 mal ButtonXY.Enabled im Code haben will. Daher mein versuch über die ActionList. Versuch jetzt mal den Vorschlag mit dem Form.Enabled.
Jumpy |
AW: User klicken unterbinden während Querry läuft
Das dürfte aber dazu führen, dass die Form nicht mehr reagiert und der Benutzer denkt das Programm wäre abgestürzt.
|
AW: User klicken unterbinden während Querry läuft
Nee das hat schon gepasst, da ich hinterher ja Enabled wieder auf true setze. Aber es hat nix gebracht. Wie zuvor kann man wild auf Buttons klicken, ohne das zunächst was passiert, aber wenn die Querry dann fertig geöffnet ist und ein Ergebnis zurückgebracht hat, passiert alles, was nach drücken der Buttons geschehen sollte.
Was den Eindruck des Absturzes angeht, so ist das ja genrell ein Problem, da ja wie geschildert nix passiert, während die Querry läuft und jeder Knopfdruck scheinbar ignoriert wird, so dass ein User denken könnte, das Prog. wäre abgestürzt. Aber damit muss man bei langen Abfragen halt leben. Was halt nur stört ist, das evtl. Buttonklicks während der "Todzeit" des Progs trotzdem irgendwie registriert und dann anschließend ausgeführt werden. Weitere Ideen gerne willkommen. Vllt. ist ja wirklich der Zeitpunkt bzw. das Ereignis wichtig, bei dem alles wieder aktiviert wird. Jumpy |
AW: User klicken unterbinden während Querry läuft
Erst disablen, dann Abfrage ausführen, dann wieder enablen. Sonst laufen die Clicks und sonstigen Aktionen in der Botschaftswarteschlange auf.
|
AW: User klicken unterbinden während Querry läuft
Und so lange Operationen verlagert man üblicherweise in einen Thread.
|
AW: User klicken unterbinden während Querry läuft
Du kannst auch die Buttons über eine Schleife mit FindComponents abfragen und entsprechend das Enabled auf true oder false setzen.
Edit: Oder im OnMouseClick - Event die Maustasten abfragen, wenn die Eigenschaft Active von der Query auf True ist, die Mausklicks ins leere laufen lassen. Wenn Active gleich False ist, dann die Mausklicks ausführen. |
AW: User klicken unterbinden während Querry läuft
Zitat:
|
AW: User klicken unterbinden während Querry läuft
Aber dann reagiert das Fenster wem falls noch und der Benutzer kann es bei Seite schieben oder minimieren oder man kann eine Animation einblenden. Zumindest hat der Benutzer nicht mehr den Eindruck, das Programm wäre abgestürzt.
|
AW: User klicken unterbinden während Querry läuft
Zitat:
|
AW: User klicken unterbinden während Querry läuft
Erstmal danke für das rege Interesse und
hier mal der momentane Code, der nicht funzt wie gesagt Quelle = TADOQuerry:
Code:
Mit self.enabled scheints da noch komischer zu werden. Manchmal (nicht immer) wird die Anzeige der Daten im Grid nicht aktualisiert. Erst wenn man aus dem Fenster klickt, dann wieder rein, ist es auf einmal da. Luckie scheint recht zu haben, dass das disablen des ganzen Forms "gefährlich" ist.
procedure TSelector.acOpenExecute(Sender: TObject);
begin if Quelle.State in [dsedit,dsinsert] then Quelle.Post; Quelle.Close; pnltab.Caption:= 'Bitte warten'; self.Repaint; Quelle.SQL.Clear; Quelle.SQL.Text:= Memo1.Lines.Text; try self.Enabled:=false; //Disabled Application.ProcessMessages; Quelle.Open; Application.ProcessMessages; pnltab.Caption:= ''; except on e: exception do begin pnltab.Caption:= e.message; Application.ProcessMessages; self.Enabled:=true; end; end; Application.ProcessMessages; self.Enabled:=true; //enabled end; Hab Alternativ auch mal nur einen Button disabled und den dann gedrückt während die Query lief. Nachdem mir die Daten angezeigt wurden, ging das Fenster auf, dass der Button öffnen sollte. Was hat es mit der Botschafterwarteschlange auf sich. Kann man da was machen? Das benutzen eines Threads überleg ich noch, allein um dem User mit einem Fortschrittsbalken Aktivität vorzugaukeln. Das sollte aber unabhängig von dem jetzigen Problem sein, dass ich erst mal gelöst haben will, nämlich das ignorieren von User-Aktionen während die Daten aus der Datenbak geholt werden. Jumpy |
AW: User klicken unterbinden während Querry läuft
Du könntest ein Panel(alClient) auf die Form legen, da die Controls hinein und dann das Panel disablen statt des Formulars. Und zur Botschaftswarteschlange: Windows legt die Botschaften, die an Dein Fensterhandle gehen, in dieser Schlange ab. Während zeitintensiver Berechnungen wird diese aber nicht abgearbeitet (außer man ruft Application.ProcessMessages auf, was genau dies tut). So kann es dann kommen, dass Benutzereingaben erst mit einiger Verspätung Wirkung zeigen.
|
AW: User klicken unterbinden während Querry läuft
Zitat:
|
AW: User klicken unterbinden während Querry läuft
Zitat:
Hab mal einfach nach dem Quelle.Open; showmessage('AAAAhhhhrg'); eingebaut. Und siehe da. Das ganze rumgeklicke wird ignoriert. Ich vermute daher, dass die Klicks in der Botschafterschlange landen, dann geht aber das modale showmessage auf. Nun werden alle Klicks abgearbeitet, laufen aber ins leere, wenn sie nicht gerade die OK-Taste des Messagefensters treffen (wg. modal) und das wars dann. Ich denk jetzt ernstahft darüber nach ein modales Mini-Form aufzumachen, dass die Klicks abfängt und es dann wieder zuzumachen, aber das kann es doch nicht sein... |
AW: User klicken unterbinden während Querry läuft
Dieses Form.Enabled auf False setzen ist nicht gerade sehr schön imho. Wenn es wirklich längere Operationen sind (>2 Sek.) dann sollte man sich wahrlich überlegen das ganze in einen Thread auszulagern, so wie Luckie gesagt hat. Ebenso sollte man sich überlegen, so wenig wie möglich zu disablen oder evtl. gleich ein modale Ladeform einzubauen. Stellt dir mal vor du bist der User und bekommst sehr wenig Feedback darüber, was deine Anwendung denn gerade macht.
Stell dir vor Windows kopiert Dateien ohne den Kopier-Dialog!? Was würdest denn davon halten? Und was würdest davon halten, wenn Windows komplett anhält (bzw. sich disabled) bis so ein Kopiervorgang abgeschlossen ist?! Mir ist schon klar, dass der Vergleich aufgrund der Multitaskfähigkeit von Windows etwas hinkt, aber ich denke es ist klar, was ich meine ;) Der Startup großer Anwendungen wird bei mir z.B. immer in einen Thread ausgelagert. Dort werden alle Objekte erzeugt, Daten aus der DB geladen etc. Von diesem Thread aus werden Nachrichten an einen Ladescreen (Stichwort: Splashscreen) geschicht und so bekommt der User Feedback über den aktuellen Fortschritt. |
AW: User klicken unterbinden während Querry läuft
Hast Du das Disablen auch vor das Öffnen der Query gesetzt?
|
AW: User klicken unterbinden während Querry läuft
Zitat:
Wenn einer 'ne Idee hat wieso, her damit, denn ich lerne gerne neues. Hab jetzt auch wieder die Version genommen, wo nur die ActionList suspended wird.
Code:
Damit ist mein Problem gelöst, das der User keine Buttons mehr klicken kann. Gleichzeitig ist aber das Form noch enabled was mir auch lieber ist (und z.B. Verschiebbar). Ich werd jetzt morgen noch einen Thread dafür aufsetzen, damit ich dem User Fortschritt vorgaukeln kann und bin happpy.
procedure TSelector.acOpenExecute(Sender: TObject);
begin if Quelle.State in [dsedit,dsinsert] then Quelle.Post; Quelle.Close; ActionList1.State:= asSuspendedEnabled; //hier ist es jetzt pnltab.Caption:= 'Bitte warten'; self.Repaint; Quelle.SQL.Clear; Quelle.SQL.Text:= Memo1.Lines.Text; try //hier war es vorher Quelle.Open; pnltab.Caption:= ''; except on e: exception do pnltab.Caption:= e.message; end; Application.ProcessMessages; ActionList1.State:= asNormal; //hier wieder alles möglich end; Danke für die viele Hilfe bei meinem ertsen Post und Problem hier. Wird bestimmt nicht das letzte bleiben, da ich gerade erst mit Delphi angefangen hab, Jumpy. |
AW: User klicken unterbinden während Querry läuft
Hallo Jumpy,
Zitat:
die TButtons (bzw. TCheckBoxes oder TRadioButtons oder TEdits) sind und diese dann Enabled:=False setzen. So hast Du nur eine Schleife, die du auch nicht bearbeiten mußt, wenn Buttons wegfallen bzw. hinzukommen sollten:)) Das crHourGlas und crDefault setzen ist ein guter Tipp von einem anderen Antworter hier. Allerdings genügt ein nur setzen nicht ohne ein UpDate bzw. Refresh und danach ein kurzes Sleep() einzufügen. Alles klar, MfG Manfred Zenns PS: Ich gebe hier nur "meine" Erfahrungen mit Delphi wieder. Oops: Ist mir noch was eingefallen. Bevor du die Action startest, setze ein Form-großes TPanel (über alle Objekte) mit Text, was nun läuft. Erhalten dann die Objekte in deinem Form Änderungen, und sind diese abgeschlossen (!?!) entferne das Panel über Visible wieder. Alle Klicks in der Zwischenzeit hat dann das Panel abgefangen. Aber ich gebe dir recht, es muß eine elegantere Lösung geben. |
AW: User klicken unterbinden während Querry läuft
So müsste es eigentlich funktionieren:
Delphi-Quellcode:
ActionList1.Enabled := False;
Application.ProcessMessages; // evtl. Unnötig try // jetzt das ganze Geraffel ausführen finally Application.ProcessMessages; ActionList1.Enabled := True; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:06 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-2025 by Thomas Breitkreuz