Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Statusbar/Uhrzeit einblenden (https://www.delphipraxis.net/131853-statusbar-uhrzeit-einblenden.html)

Errraddicator 1. Apr 2009 13:20


Statusbar/Uhrzeit einblenden
 
Hiho!

Ich wollte so als Spielerei - und zum Testen - in mein Programm 2 Dinge einbauen:
- unten Rechts die aktuelle Uhrzeit
- Einen Statusbalken der wahllos durchläuft, ähnlich wie der beim Hochfahren von Windows

Jetzt habe ich das versucht über Timer zu regeln, aber das funktioniert nur, wenn mein Hauptprogramm selbst nicht wirklich beschäftigt ist.
Sobald ich die eigentliche Verarbeitung anstarte, hängen diese Timer und aktualisieren nur noch, wenn ich im Hauptprogramm selbst ein Update/ProcessMessages mache.

Dass ich das Problem via Threading lösen kann ist mir zwar klar, aber sowas "großes" wollte ich eigentlich für solche Spielereien vermeiden.
Oder komme ich da gar nich drum herum?


cu

Patrick

Luckie 1. Apr 2009 13:38

Re: Statusbar/Uhrzeit einblenden
 
Wenn deine Anwendung beschäfftigt ist, dann kann eben die Nachrichtenschleife nicht mehr abgearbeitet werden und somit auch keine WM_TIMER Nachrichten verarbeitet werden. Lagere also den Code, der deine Anwendung blockiert in einen Thread aus.

taaktaak 1. Apr 2009 15:35

Re: Statusbar/Uhrzeit einblenden
 
Zitat:

unten Rechts die aktuelle Uhrzeit
Hmmm, mache ich auch oft. Und das funktioniert mit 'nem Timer eigentlich immer. Oder willst du auch die Sekunden anzeigen? Für eine "normale" Uhrzeitanzeige genügen doch Stunden:Minuten und da müsste dein Programm aber sehr beschäftigt sein, wenn das nicht funktionieren sollte.

BullsEye 1. Apr 2009 16:36

Re: Statusbar/Uhrzeit einblenden
 
So kannst du die aktuelle Uhrzeit in deiner Statusleiste einblenden:

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  StatusBar1.Panels[1].Text := TimeToStr(time);
end;
Musst nur im OI halt Panels hinzufügen ;)

RWarnecke 1. Apr 2009 18:39

Re: Statusbar/Uhrzeit einblenden
 
Es gibt noch eine andere Möglichkeit. Dazu brauchst Du die Komponente TJvClock von den Jedi's und eine Statusbar mit mehreren Panels. In diesem Beispiel wird die Uhr ins 3 Panel eingefügt. Diese paar Zeilen in das Ereignis FormShow und schon hast Du Deine aktuelle Uhrzeit in der Statusleiste.

Delphi-Quellcode:
  // Die Uhr in das dritte Panel setzen von der Statusbar
  Statusbar.Perform(SB_GETRECT, 2, Integer(@R));
  Clock.Parent := Statusbar; //Clock adoptieren
  Clock.Top := r.Top; //Größe der
  Clock.Left := r.Left; //Clock setzen
  Clock.Width := r.Right - r.Left; //und an Panel anpassen
  Clock.Height := r.Bottom - r.Top;

Noedel 1. Apr 2009 18:40

Re: Statusbar/Uhrzeit einblenden
 
Zitat:

Zitat von BullsEye
So kannst du die aktuelle Uhrzeit in deiner Statusleiste einblenden:

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  StatusBar1.Panels[1].Text := TimeToStr(time);
end;
Musst nur im OI halt Panels hinzufügen ;)

oder statusbar1.simpletext, dann hast du´s aber linksbündig :)

Luckie 1. Apr 2009 18:46

Re: Statusbar/Uhrzeit einblenden
 
Zitat:

Zitat von BullsEye
So kannst du die aktuelle Uhrzeit in deiner Statusleiste einblenden:

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  StatusBar1.Panels[1].Text := TimeToStr(time);
end;
Musst nur im OI halt Panels hinzufügen ;)

Genau das hat er wahrscheinlich gemacht und musse festellen, dass die Anzeige "hängt" wenn sein Programm beschäftigt ist und die Nachrichten aus der Nachrichtenschleife nicht abholen kann.

Errraddicator 2. Apr 2009 09:29

Re: Statusbar/Uhrzeit einblenden
 
Zitat:

Zitat von Luckie
Genau das hat er wahrscheinlich gemacht und musse festellen, dass die Anzeige "hängt" wenn sein Programm beschäftigt ist und die Nachrichten aus der Nachrichtenschleife nicht abholen kann.

Genau.
Und deshalb war jetzt meine eigentlich Frage, ob ich das Problem auch ohne Threads lösen kann, oder nicht? *G*

Aber anscheinend nicht, so wie es aussieht. ^^

RWarnecke 2. Apr 2009 09:33

Re: Statusbar/Uhrzeit einblenden
 
Hallo Patrick,

hast Du meinen Beitrag #5 hier gelesen und auch mal ausprobiert ?

Errraddicator 2. Apr 2009 12:40

Re: Statusbar/Uhrzeit einblenden
 
Zitat:

Zitat von RWarnecke
Hallo Patrick,

hast Du meinen Beitrag #5 hier gelesen und auch mal ausprobiert ?

Gelesen ja, ausprobiert nich.. :D
Liegt einfach daran, dass ich
a) ungern Drittanbietersachen nehme, sondern sie gerne - grade wenns so kleine Sachen sind - selber programmiere
und
b) da die Uhr nur ein Beispiel für div. andere ähnliche Anwendungsgebiete ist, die ich nacher ma umsetzen möchte.

Aber trotzdem Danke! :)

RWarnecke 2. Apr 2009 13:17

Re: Statusbar/Uhrzeit einblenden
 
Du musst ja nicht unbedingt die TJvClock nehmen. Ich habe das ja nur als Beispiel gesehen. Du kannst auch jede andere Uhrzeit-Komponente dazu nehmen. Aber trotzdem würde ich mal einen Blick darein werfen, vielleicht findest Du ja einen Ansatzpunkt wie Du es realisieren kannst. Warum willste das Rad wieder neu erfinden ?

taaktaak 2. Apr 2009 14:52

Re: Statusbar/Uhrzeit einblenden
 
Moin, Moin.
Das du keine Dritanbieter-Komponenten verwenden willst verstehe ich ja. Manches möchte man eben gern selbst realisieren, auch wenn es andere schon zig-fach gelöst haben.
Aber - wo liegt denn nun das Problem?
Ich kann nicht glauben, dass dein Programm so beschäftigt ist, dass eine Minuten-Anzeige nicht realisiert werden kann. Wenn es unbedingt Sekunden sein müssen, oder es ums Prinzip geht, dann ist der Lösungesweg ja schon beschrieben worden: Verwende Threads! Oder baue überall wo es in deinem Programm besonders lange dauert das leidige ProcessMessages ein.

Errraddicator 9. Apr 2009 09:32

Re: Statusbar/Uhrzeit einblenden
 
So, nachdem ich das Programm in dem es hier eigentlich ging, ohne Uhrzeit/Statusbalken fertig gemacht habe, versuche ich das Prinzip mit den Threads jetzt auf ein neues Programm, was ich jetzt machen soll.
Das Programm is an sich ma wieder nix wildes, durchforstet die Datenbank nach gewissen Daten, filtert/sortiert/etc und gibt diese dann aus.

...

Jetzt habe ich einen Thread geschrieben, der dann im Hauptfenster einen Laufbalken immer via "StepIt()" aktualisieren soll.
Das Ganze hat keinen Zusammenhang zu den eigentlichen Daten, sondern dient nur der Unterhaltung des Benutzers, d.h. der ist zu ende, fänge vorne wieder an, usw.

Hier der Quelltext des Threads
Delphi-Quellcode:
{*--- TProgressSimulator ---*}
procedure TProgressSimulator.Execute();
begin
  // do as long as thread isn´t terminated
  while self.Terminated = False do
  begin
    // Kommentar fürs Forum: Variante 1
    Synchronize(frmMain.simulateProgress);
    Application.ProcessMessages();

    // Kommentar fürs Forum: Variante 2
    frmMain.barProgress.StepIt();
    Application.ProcessMessages();

    Sleep(100);
  end;
end;
Beide Varianten funktionieren übrigens nicht!
(Das die 2. nicht Threadsicher ist, weiß ich, aber damit wollte ich nur testen, ob das was mit Synchronize zu tun hat).

Dieser Thread hat also via Synchronize eine Methode von TfrmMain aufgerufen, welche so aussieht:
Delphi-Quellcode:
// simulates progress
procedure TfrmMain.simulateProgress();
begin
  try
    barProgress.StepIt();
    updateGui();
  except
    on e: Exception do begin ; end;
  end;
end;
Ich habe aber wieder das Gleiche Problem wie zuvor: Das geht nur so lange gut, wie mein Programm nix macht.
Sobald die eigentliche Verarbeitung in "TfrmMain" anfängt und das Programm die Datenbank durchsucht etc. "hängt" der Thread.
Das äussert sich dann so, dass der Code in "Execute" immer nur dann ausgeführt wird, wenn das Programm an sonsten grade nix zu tun hat.
Ist das Programm beschäftigt, macht der Thread einfach gar nix mehr ... exakt solange bis das Programm fertig mit der Verarbeitung ist.

Ein "Application.ProcessMessages" innerhalb der Verarbeitung löst das Problem zwar - DANN macht der Thread auch was er soll, nämlich genau 1x je "Application.ProcessMessages" - aber das ist ja etwas witzlos, denn der Balken soll ja konstant laufen und nich nur, wenn im eigentlichen Quelltext ma ein "ProcessMessage" vorkommt.

Hat wer ne Ahnung, woran das liegt, bzw. wie ich das lösen kann?

...

Ok, ich könnte jetzt die Verarbeitung an sich noch in einen extra Thread auslagern, aber das gefällt mir nich wirklich, da dass die Verarbeitung, bzw. Kommunikation mit dem Benutzer/der GUI unnötig verkomplizieren würde.

...

Hier noch ma die Methode, die die eigentliche Verarbeitung und den Thread steuert
Delphi-Quellcode:
procedure TfrmMain.btnStartClick(Sender: TObject);
var
  logMsg: String;
begin
  // check params for errors
  // <unnötig hier>

  // disable gui & start threads
  enableGui(false);
  progSimulator.Resume();

  // do processing
  try
    startProcessing();

    writeStatus('Verarbeitung abgeschlossen', ML_BOTH);
    ShowMessage('Verarbeitung abgeschlossen');
  except
    on e: Exception do
    begin
      logMsg := 'Unerwarteter Fehler aufgetreten: ' + e.Message;
      writeStatus(logMsg, ML_LOG_ONLY);
      ShowMessage(logMsg);
    end;
  end;

  // stop threads & re-enable gui
  progSimulator.Suspend();
  enableGui(true);
end;

Danke im Voraus

cu Patrick

Errraddicator 9. Apr 2009 11:40

Re: Statusbar/Uhrzeit einblenden
 
Ich habs jetzt btw einfach so gemacht, dass ich auch die Verarbeitung in einen Thread ausgelagert habe.

Dann funktioniert das Ganze einwandfrei.
Is zwar etwas komplizierter als geplant, weil ich jetzt viel über Prozeduren via Sychnronize und Co. machen muss, aber nun gut.
Hauptsache funzt. :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:30 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz