Entwickler-Ecke
Sonstiges (Delphi) - Label wird zu groß gezeichnet
hui1991 - So 10.08.08 15:18
Titel: Label wird zu groß gezeichnet
Hallo,
ich codiere mit meinem Programm Daten in ein anderes Format. Dies mache ich mit Threads. Der Hauptthread ist dazu da das Fenster neuzuzeichnen. Der andere Thread berechnet die Daten.
Bei den Informationen ist aber hin und wieder ein Fehler beim Zeichnen.
Manchmal wird die Schrift zu groß gezeichnet.
Kann es daran liegen, genau in dem moment der andere Thread die Anzeige aktualisiert und der Hauptthread das Label neuzeichnet.
Im Anhang wird gezeigt wie es groß und wie es normal aussieht.
Meine Frage ist nun: Wie kann ich es beseitigen?
Edit: Gerade bekam ich eine Fehlermeldung die unten als Screen ist und da steht:
Quelltext
1:
| Im Projekt ist eine Exeception der Klasse EInvalidOperation mit der Meldung 'Leinwand/Bild erlaubt kein Zeichnen' aufgetreten. |
Wie bekommt man den Fehler weg so das sich die 2 Threads nicht im Weg stehen?
MfG
hui1991
Hidden - So 10.08.08 16:06
Hi,
Mal so ven dem her, was ich bisher von Threads gehört habe: Lass doch den Hauptthreat die Daten
SYNCHRONISIERT aus deinem Threat auslesen und die Form auch ausschließlich von der Hauptanwendung bearbeiten.
mfG,
Sinspin - So 10.08.08 16:39
Ein Thread darf
niemals einfach so auf ein Fenster zugreifen und irgendwelche Eigenschaften von Komponenten ändern.
Wenn du über Delphi : Datei / Neu / Thread-Object einen Neuen Thread erstellst, dann steht das ganz deutlich als Kommentar in der neuen Unit.
Allgemein:
Eine Möglichkeit ist es, unter Verwendung von Syncronize aus deinem Thread heraus zu aktualisieren. Die bessere Lösung.
Die andere Möglichkeit ist, die Aktualisierung über deine Fenster zu realisieren. Unter Verwendung eines Timers oder OnIdle. Da kann es aber immer mal passieren das du einen Thread zu einem ungünstigen Zeitpunkt erwischst. Also, die schlechtere Lösung.
hui1991 - So 10.08.08 16:59
Ich hab den Thread als Code erstellt. Ich hab gerade die Werte mit:
InterlockedExchange
geändert.
Das hab ich aus dem Thema:
http://www.delphi-library.de/viewtopic.php?t=16627&highlight=thread%20%20%20synchronisieren
Stand in der PDF drin, scheint auch zu funktionieren.
Ich schreibe es auf Synchronize um.
Problem ist nur wie bekomme ich die Werte von meiner Thread-Funktion in die Procedure?
Edit:
Ich werde einfach einen Record erstellen und dort alle Daten eingeben. Wenn ich den Synchronize-Befehl aufrufe, dann werden die Daten gelesen und eingetragen.
Hoffe das geht so.
Sinspin - So 10.08.08 17:18
Ich verwende dafür immer zwei Prozeduren.
Eine, und zwar die, die im Thread aufgerufen wird, hat Parameter. Die speichert die bekommenen Werte in, unter private im Thread liegenden Variablen.
Und ruft im Anschluss die Andere, Parameterlose via Synchronize auf.
Die Parameterlose holt sich dann die Variablen und aktualisiert die Ansicht.
Das ist zwar nicht unbedingt schön, ist aber die einzige Lösung die mir dazu einfällt.
// Edit: bist ja schon selber drauf gekommen :wink:
hui1991 - So 10.08.08 17:40
Ich kann Synchronize nicht aufrufen.
Meine Threadfunktion sieht so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure UpdateComponents; begin Form1.ProgressBar1.Max := Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Fensterinfo.ProgressBar1Positon; Form1.Label5.Caption := Fensterinfo.Label5Caption; Form1.Panel2.Caption := Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Fensterinfo.Panel3Caption; end;
function ThreadFunc(tp: PThreadParams): Integer; var Open : string; Save: string; begin Open := PThreadParams(tp)^.Open; Save := PThreadParams(tp)^.Save;
Synchronize(UpdateComponents); Dispose(tp); end; |
in der Delphi-Hilfe steht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TMyThread.PushTheButton; begin Button1.Click; end; ... procedure TMyThread.Execute; begin ... Synchronize(PushTheButton); ... end; |
Irgendwie funktioniert Synchronize nicht mit einer funktion.
Ich rufe die Funktion so auf:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var Thread : THandle; ThreadID : Cardinal; begin Thread := BeginThread(nil, 0, @ThreadFunc, nil, 0, ThreadID); end; |
Ich muss wohl den Thread anders erstellen. :(
Oder gibt es eine andere Möglichkeit.
Probiere schon 4 Stunden an den Threads rum. In der Zeit wäre das Programm schon fertig gewesen ^^
Boldar - So 10.08.08 17:53
hui1991 hat folgendes geschrieben: |
An der Stelle kommt ein [Pascal Fehler] Unit1.pas(589): E2066 Operator oder Semikolon fehlt |
Dann fehlt wohl ein Semikolon!!!
Poste doch mal den ganzen Code
hui1991 - So 10.08.08 18:03
Semikolon ist hinten dran. Irgendwas ist da noch falsch.
Welcher von den 3 Proceduren wird eigentlich verwendet für sowas:
Quelltext
1: 2: 3: 4: 5:
| [Delphi] procedure Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean); overload;
[Delphi] procedure Synchronize(AMethod: TThreadMethod); overload;
[Delphi] procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload; |
Boldar - So 10.08.08 18:23
hui1991 hat folgendes geschrieben: |
Semikolon ist hinten dran. Irgendwas ist da noch falsch.
Welcher von den 3 Proceduren wird eigentlich verwendet für sowas:
Quelltext 1: 2: 3: 4: 5:
| [Delphi] procedure Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean); overload;
[Delphi] procedure Synchronize(AMethod: TThreadMethod); overload; //--------------------> Die
[Delphi] procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload; | |
Poste doch mal den Code vor der Stelle oder den Gesamten code!!!!!!!!
hui1991 - So 10.08.08 18:32
Ich hab mal einen Thread umgeschrieben auf:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| procedure UpdateComponents; begin Form1.ProgressBar1.Max := Unit1.Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Unit1.Fensterinfo.ProgressBar1Positon; Form1.ProgressBar2.Max := Unit1.Fensterinfo.ProgressBar2Max; Form1.ProgressBar2.Position := Unit1.Fensterinfo.ProgressBar2Positon; Form1.Label5.Caption := Unit1.Fensterinfo.Label5Caption; Form1.Panel2.Caption := Unit1.Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Unit1.Fensterinfo.Panel3Caption; end;
procedure Threadladen.Execute; var s : string; x,y: Integer; begin Unit1.Fensterinfo.Panel2Caption := 'Status: Anwendung laden...'; Unit1.Fensterinfo.ProgressBar2Max:=100; Unit1.hin_daten := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=2; Unit1.hin_leistung := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=4; Unit1.hin_daten.LoadFromFile('2.joined'); Unit1.Fensterinfo.ProgressBar2Positon:=74; Unit1.hin_leistung.LoadFromFile('1.joined'); Synchronize(UpdateComponents); end; |
Dieses Synchronize hat bei mir bis jetzt nie funktioniert. :(
Edit: Hab einen neuen beitrag erstellt, weil delphi-tag sonst nicht funktioniert.
Sinspin - So 10.08.08 18:36
Warum blos immer alle so giergig auf den Quelltext anderer Leute sind!?
Ich vermute mal das es daran liegt das die Prozedur aus der du den Aufruf machst nicht zu Thread gehört und damit Synchronize unbekannt ist. Denn Synchonize ist eine Prozedur des Threads!
hui1991 - So 10.08.08 18:46
Ich hab den Fehler gefunden.
Das muss so heißen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| class procedure Threadladen.UpdateComponents; begin Form1.ProgressBar1.Max := Unit1.Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Unit1.Fensterinfo.ProgressBar1Positon; Form1.ProgressBar2.Max := Unit1.Fensterinfo.ProgressBar2Max; Form1.ProgressBar2.Position := Unit1.Fensterinfo.ProgressBar2Positon; Form1.Label5.Caption := Unit1.Fensterinfo.Label5Caption; Form1.Panel2.Caption := Unit1.Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Unit1.Fensterinfo.Panel3Caption; end;
procedure Threadladen.Execute; var s : string; x,y: Integer; begin Unit1.Fensterinfo.Panel2Caption := 'Status: Anwendung laden...'; Unit1.Fensterinfo.ProgressBar2Max:=100; Unit1.hin_daten := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=2; Unit1.hin_leistung := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=4; Unit1.hin_daten.LoadFromFile('2.joined'); Unit1.Fensterinfo.ProgressBar2Positon:=74; Unit1.hin_leistung.LoadFromFile('1.joined'); Synchronize(UpdateComponents); end; |
1. Es muss in ein Thread-Objekt
2. Es muss eine
Class Procedure sein.
dann geht es.
Die Lösung habe ich hier gefunden:
http://www.delphipraxis.net/topic91117.html
Eigentlich sollte als Fehlermeldung:
[Pascal Fehler] Unit1.pas(440): E2076 Diese Form des Methodenaufrufs ist nur für Klassenmethoden erlaubt
kommen, aber es kommt nur mit TThread.Synchronize
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!