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 Neuzeichnen von TStatusbar (https://www.delphipraxis.net/35080-neuzeichnen-von-tstatusbar.html)

Neelix 2. Dez 2004 11:05


Neuzeichnen von TStatusbar
 
Hallo,

in einem Programm werden nacheinander mehrere Query's
Delphi-Quellcode:
      StatusBar1.SimpleText := 'Erstelle tmp_blabla_1';
      StatusBar1.Repaint;
      dmCopyVertrag.qu_CreateDropTable.SQL.Clear;
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('CREATE TEMP TABLE tmp_blabla1 (');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_1 CHAR(20) NOT NULL,');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_2 INTEGER NOT NULL)');
      dmCopyVertrag.qu_CreateDropTable.ExecSQL;
      dmCopyVertrag.qu_tmp_blabla_1.ExecSQL;

      StatusBar1.SimpleText := 'Erstelle tmp_blabla_11';
      StatusBar1.Repaint;
      dmCopyVertrag.qu_CreateDropTable.SQL.Clear;
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('CREATE TEMP TABLE tmp_blabla_11 (');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_11 INTEGER NOT NULL,');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_12 CHAR(21) NOT NULL)');
      dmCopyVertrag.qu_CreateDropTable.ExecSQL;
      dmCopyVertrag.qu_tmp_blabla_11.ExecSQL;
Der text in der Statusbar ändert sich aber erst, wenn alle Querys abgearbeitet sind und dann sthet dort "Fertig". Es ist aber nicht im Sinne des Erfinders, wenn nur der erste und der letzte Text angezeigt werden. Eigentlich soll man sehen können, an welcher Stelle im Programm man sich gerade befindet.
System: Windows XP, P4 2,4 GHz
Unter NT und einem P3 800 MHz hat's aber schon funktioniert und sogar ohne das Repaint. :wall:

Luckie 2. Dez 2004 11:06

Re: Neuzeichnen von TStatusbar
 
Delphi-Quellcode:
Statusbar1.Refresh/Repaint;
Sollte dein Problem lösen.

Oh hast du ja schon. Sind die Querys eventuell zu schnell?

Neelix 2. Dez 2004 11:10

Re: Neuzeichnen von TStatusbar
 
Die dauern eigentlich 'ne ganze Weile. Deswegen will ich das ja anzeigen.

Luckie 2. Dez 2004 11:12

Re: Neuzeichnen von TStatusbar
 
War nur eine Vermutung, da sie ja auf dem langsamen System angezeigt wurden. Mach doch mal ein Sleep(2000) nach dem Repaint der Statusbar.

Neelix 2. Dez 2004 11:14

Re: Neuzeichnen von TStatusbar
 
Werde ich vor dem nächsten Programmstart mal einbauen. ;-) Zur Zeit arbeitet das Programm gerade wieder (ca. eine halbe Stunde)

Igotcha 2. Dez 2004 11:21

Re: Neuzeichnen von TStatusbar
 
Zitat:

Zitat von Neelix
Die dauern eigentlich 'ne ganze Weile. Deswegen will ich das ja anzeigen.

Nur mal so ne Frage... was dauert denn beim Erstellen von 2 Tabellen mit je 2 Feldern "ne ganze Weile"?

Echtet 2. Dez 2004 11:25

Re: Neuzeichnen von TStatusbar
 
Hallo,

das Problem der mangelnden Aktualisierung hatte ich auch in einem ähnlichen Fall.

Bei mir konnte ich das Neuzeichnen durch den Aufruf von 'application.processmessages' (jeweils vor dem Ändern des Textes der Statusleiste) lösen.

Gruß,
Thimo

Neelix 2. Dez 2004 11:33

Re: Neuzeichnen von TStatusbar
 
Das:
Delphi-Quellcode:
dmCopyVertrag.qu_tmp_blabla_11.ExecSQL;
Dahinter verbirgt sich u.a. so etwas
SQL-Code:
INSERT INTO tmp_blabla_1
SELECT distinct b2.bla_2, b3.bla_3 
FROM blabla_21 b2, tmp_blabal_31 b3
WHERE b2.bla_22 = b3.bla_32
AND b2.bla_23 = b3.bla_33
Und davon gibt es mehrere. Eingefügt werden 1000 und mehr Datensätze und selectiert wird über Tabellen mit mehreren Tausend Datensätzen.

Und um gleich der Frage vorzubeugen, warum ich nicht erst mal mit wenigen Datensätze teste: Ich nutze das Programm zur Zeit im "scharfen Betrieb" und versuche nur nebenbei die Anzeige in der Statuszeile wieder hinzubekommen.

Jasocul 2. Dez 2004 11:34

Re: Neuzeichnen von TStatusbar
 
[quote="Igotcha"]
Zitat:

Zitat von Neelix
Nur mal so ne Frage... was dauert denn beim Erstellen von 2 Tabellen mit je 2 Feldern "ne ganze Weile"?

Ich vermute, dass Neelix ein implizites Drop der Tabellen macht. Deutet der Bezeichner der Komponente zumindest an.
Aber dann ist der Server/die Datenbank grottenlangsam oder die Tabellen sind mehrere zig GB groß.

Neelix 2. Dez 2004 11:41

Re: Neuzeichnen von TStatusbar
 
Zitat:

Zitat von Jasocul
Aber dann ist der Server/die Datenbank grottenlangsam oder die Tabellen sind mehrere zig GB groß.

Letzteres. Und hinzu kommt, das tausende von Datensätzen (meherere voneinander abhängige Tabellen mit RI) von Datenbank A nach Datenbank B kopiert werden, wobei die Datenbanken (zumindest zur Zeit) auf zwei unterschiedlichen Maschinen liegen. Ich habe ja in meinem Beispiel nur einen kleinen Ausschnitt gezeigt.

Sourcemaker 2. Dez 2004 11:49

Re: Neuzeichnen von TStatusbar
 
Hi,

Ich würde empfehlen die Methode Update aufzurufen Application ProcessMessages geht auch ist aber unter Umständen mit Nebenwirkungen behaftet.

Zitat:

Die Methode Update bearbeitet alle anstehenden Zeichenbotschaften.

Delphi-Syntax:

procedure Update; virtual;

C++ Syntax:

virtual void __fastcall Update(void);

Beschreibung

Mit Update können Sie das sofortige Neuzeichnen des Steuerelements veranlassen, bevor weitere, möglicherweise zeitaufwendige Bearbeitungen durchgeführt werden. Mit Hilfe dieser Methode können Sie dem Benutzer eine sofortige Rückmeldung zukommen lassen.

Update ruft nicht die Methode Invalidate des Steuerelements auf, sondern veranlasst nur das Neuzeichnen von Bildschirmbereichen, die bereits aktualisiert wurden. Wenn auch das Steuerelement erneut gezeichnet werden soll, rufen Sie stattdessen Repaint auf.
Grüße

Frank

Neelix 2. Dez 2004 12:27

Re: Neuzeichnen von TStatusbar
 
Die Methode Update hat auch nichts gebracht. Teste gerade den Vorschlag von Luckie mit dem sleep. Welche Nebenwirkungen hat den Application.ProcessMesages?

Sourcemaker 2. Dez 2004 12:54

Re: Neuzeichnen von TStatusbar
 
Beispiel für Nebenwirkung:

Wenn Du eine Form erzeugts und sie in einer SetUp-Routine mit Daten füllst die dann zügig angezeigt werden sollen während weitere Initialisierung ablaufen führt ein Application Processmessage zwar zur direkten Anzeige der Form sorgt aber auch dafür das Events ablaufen bzw. auf Events reagiert wird die erst nach vollständigen SetUp behandelt werden können und das führt zu schönen Knalleffekten. Update hingegen zeichnet hingegen nur die bereits gefüllten Controls neu.

Grüße

Frank

Neelix 2. Dez 2004 13:01

Re: Neuzeichnen von TStatusbar
 
Sleep (2000) hat leider auch nichts gebracht. :wall:

Muetze1 2. Dez 2004 13:17

Re: Neuzeichnen von TStatusbar
 
Moin!

Noch 2 Vorschlägen:

1. Vor dem Update noch ein Invalidate aufrufen
2. per Hand:
Delphi-Quellcode:
Var
  lRect : TRect;
Begin
  ...

  lRect := StatusBar.ClientRect;
  InvalidateRect(Handle, @lRect, False);
  UpdateWindow(Handle);

  ...
End;
MfG
Muetze1

bigg 2. Dez 2004 13:17

Re: Neuzeichnen von TStatusbar
 
Code:
Application.ProcessMessages
:)

franktron 2. Dez 2004 13:19

Re: Neuzeichnen von TStatusbar
 
Machs mal so

Zitat:

Zitat von Neelix
Hallo,

in einem Programm werden nacheinander mehrere Query's
Delphi-Quellcode:
     
      StatusBar1.SimpleText := 'Erstelle tmp_blabla_1';
      Application.ProcessMessages;
      dmCopyVertrag.qu_CreateDropTable.SQL.Clear;
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('CREATE TEMP TABLE tmp_blabla1 (');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_1 CHAR(20) NOT NULL,');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_2 INTEGER NOT NULL)');
      dmCopyVertrag.qu_CreateDropTable.ExecSQL;
      dmCopyVertrag.qu_tmp_blabla_1.ExecSQL;

      StatusBar1.SimpleText := 'Erstelle tmp_blabla_11';
      Application.ProcessMessages;
      dmCopyVertrag.qu_CreateDropTable.SQL.Clear;
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('CREATE TEMP TABLE tmp_blabla_11 (');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_11 INTEGER NOT NULL,');
      dmCopyVertrag.qu_CreateDropTable.SQL.Add('bla_12 CHAR(21) NOT NULL)');
      dmCopyVertrag.qu_CreateDropTable.ExecSQL;
      dmCopyVertrag.qu_tmp_blabla_11.ExecSQL;


Muetze1 2. Dez 2004 13:21

Re: Neuzeichnen von TStatusbar
 
Moin!

Und für die letzten beiden nochmals dieses hier. Application.ProcessMessages ist an dieser Stelle wirklich kein guter Weg und wirkt eh wie eine Holzhammermethode.

MfG
Muetze1

Neelix 2. Dez 2004 13:31

Re: Neuzeichnen von TStatusbar
 
Hallo Muetze1,

Test läuft.

Neelix 2. Dez 2004 13:51

Re: Neuzeichnen von TStatusbar
 
Hat auch nichts gebracht. In meiner Verzweiflung versuche ich nun doch Application.ProcessMessages. :x

Luckie 2. Dez 2004 13:55

Re: Neuzeichnen von TStatusbar
 
Wie wäre es mit einem separaten Thread? Nach jedem Schritt schickt der dem Hauptthread eine Nachricht mit einer Statusmeldung.

Neelix 2. Dez 2004 14:01

Re: Neuzeichnen von TStatusbar
 
Habe noch nie Threads programmiert. :wall:

Luckie 2. Dez 2004 14:11

Re: Neuzeichnen von TStatusbar
 
Ein Tutorial gibt es hier: http://tutorials.luckie-online.de

Neelix 2. Dez 2004 17:43

Re: Neuzeichnen von TStatusbar
 
Danke Luckie. Ich schaue mir das mal an. Und wenn ich nicht weiterkomme, dann kann ich dich ja auch fragen.
Was empfiehlst Du in parallelen Threads laufen zu lassen. Die DB-Zugriffe?
BTW: Die einzelnen Queries stehen in einem DataWindow (VCL-Programmierung), und werden beim Programmstart schon erzeugt. Das geht bei Threads wohl eher nicht, oder?

Luckie 2. Dez 2004 17:45

Re: Neuzeichnen von TStatusbar
 
Keine Ahnung, ich habe von DB Programmierung keinen Plan. Aber ich würde nur die Queries in den Thread auslagern, glaube ich.

Neelix 3. Dez 2004 09:27

Re: Neuzeichnen von TStatusbar
 
So, ich habe jetzt mal einen Test gemacht. Verwende das VCL Thread-Objekt. Dann einen (!) Query-Aufruf in die Execute Methode gepackt und voila nach Abarbeitung dieses einen Threads werden alle nachfolgenden Einträge in die TStatusBar angezeigt, obwohl dies nicht mehr in einem separaten Thread abläuft. Is this a feature? :gruebel: :cyclops:

Luckie 3. Dez 2004 17:44

Re: Neuzeichnen von TStatusbar
 
So würde ich es machen, ohne TThread sondern mit der API:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure WndProc(var Msg: TMessage); override;
  end;

type
  TThreadParams = packed record
    FhWnd: THandle;
  end;
  PThreadParams = ^TThreadParams;

const
  MTM_STATUS = WM_USER + 1; // lParam -> Status-String

var
  Form1: TForm1;

implementation

{$R *.dfm}

function ThreadFctn(p: Pointer): Integer;
var
  i: Integer;
  s: String;
  hWnd: THandle;
begin
  hWnd := PThreadParams(p)^.FhWnd;
  for i := 0 to 4 do
  begin
    s := 'Durchlauf: '+IntToStr(i);
    SendMessage(hWnd, MTM_STATUS, 0, Integer(PChar(s)));
    sleep(500);
  end;
  s := 'fertig';
  SendMessage(hWnd, MTM_STATUS, 0, Integer(PChar(s)));
  FreeMem(p, sizeof(TThreadParams));
  result := 0;
end;

procedure TForm1.WndProc(var msg: TMessage);
begin
  inherited;
  case msg.Msg of
    MTM_STATUS:
    begin
      Caption := PChar(msg.LParam);
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ThreadParams: PThreadParams;
  ThreadID: Cardinal;
begin
  GetMem(ThreadParams, sizeof(TThreadParams));
  ThreadParams.FhWnd := Handle;
  CloseHandle(BeginThread(nil, 0, @ThreadFctn, ThreadParams, 0, ThreadID));
end;

Neelix 4. Dez 2004 12:03

Re: Neuzeichnen von TStatusbar
 
Zitat:

Zitat von Luckie
So würde ich es machen, ohne TThread sondern mit der API:

Danke Luckie, aber ich meide die API-Programmierung, wenn ich kann. Werde Dein Beispiel aber am Montag mal ausprobieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 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