![]() |
Probleme mit Frames und deren Aktualisierung in Formularen
Moin Moin,
ich habe folgendes Problem: Ich habe eine ganze normale Form mit eine paar TabSheets. Je nachdem, welcher TabSheet betätigt wurde, soll ein anderes Frame auf ein Panel gezeigt werden. Soweit so gut... Wenn ich jetzt angenommen in dem Frame den Name von einer GroupBox ändere und das Formular, wo das Frame eingebettet ist nicht offen habe im Designer, und ich compiliere das Projekt, dann geht das auch aber wehe ich starte das Projekt.... Jede Menge Exceptions weil er in dem Formular wo das Frame eingebettet ist, noch den Name der "alten" GroupBox hat. Gibt es eine Möglichkeit wie man alles aktualisieren kann, was auf dieses Frame zugreift? Ich hoffe ihr versteht was ich meine und könnt mir helfen...?! MFG Alex |
Re: Probleme mit Frames und deren Aktualisierung in Formular
*staubwegwisch* *hust*
Ich habe ein ähnliches Problem: ich hab ein TFrame welches zur Laufzeit erzeugt wird (können auch mehrere sein, soll so ähnlich werden wie das Download-Fenster von Firefox) mit einer Progressbar drauf, die sich aber nicht bewegt. Wenn ich das ganze direkt auf das Formular mache, läufts aber. Application.ProcessMessages hab ich schon probiert, geht aber auch nicht. Zitat:
|
Re: Probleme mit Frames und deren Aktualisierung in Formular
Also, so sieht mein Code für die Erstellung des Frames aus:
Delphi-Quellcode:
So funktioniert es aber nicht.
...
inc(FrameID); DateiFrame := TFDatei.Create(PDateien); DateiFrame.Parent := PDateien; DateiFrame.LName.Caption := FileName; if DateiGroesse < 1048576 then DateiFrame.LGroesse.Caption := RealToStr(DateiGroesse/1024) + ' KB'; if DateiGroesse > 1048576 then DateiFrame.LGroesse.Caption := RealToStr(DateiGroesse/1024/1024) + ' MB'; if DateiGroesse > 1073741824 then DateiFrame.LGroesse.Caption := RealToStr(DateiGroesse/1024/1024/1024) + ' GB'; DateiFrame.Name := 'Frame' + IntToStr(FrameID); FrameNr := FrameID; if FListe.Count <> 0 then DateiFrame.Top := (FListe.Count) * 65; FListe.Add(DateiFrame); DateiFrame.Show; PDateien.Repaint; DateiFrame.FStream := TFileStream.Create(target, fmCreate); DateiFrame.TDatei.Enabled := true; //TDatei ist der Timer der für die Progressbar zuständig ist Application.ProcessMessages; try IDS := TidStreamVCL.Create(DateiFrame.FStream); try with AContext.connection do begin try SizeOfIncomingStream := Socket.ReadInteger; Socket.ReadStream(IDS, SizeOfIncomingStream); finally Disconnect; end; end; IDS.VCLStream.Position := 0; finally FreeAndNil(IDS); end; finally for i := 0 to FListe.Count - 1 do begin DateiFrame := FListe[i]; if DateiFrame.Name = 'Frame' + IntToStr(FrameNr) then begin FreeAndNil(DateiFrame.FStream); DateiFrame.TDatei.Enabled := false; DateiFrame.Free; Fliste.Delete(i); end; end; ... Wenn ich aber statt
Delphi-Quellcode:
DateiFrame := TFDatei.Create(PDateien);
DateiFrame.Parent := PDateien;
Delphi-Quellcode:
schreibe und den Frame schon zur Designzeit aufs Formular ziehe, dann gehts.
DateiFrame := TFDatei1;
Die Datei wird auch ordnungsgemäß gespeichert und alles, nur bei der Progressbar tut sich nix. Wo liegt denn hier der Fehler? Ich hoffe ihr könnt mir helfen, langsam weis ich nicht mehr weiter. :wall: |
Re: Probleme mit Frames und deren Aktualisierung in Formular
***push***
:duck: |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hallo Sko,
wieso muss das unbedingt mit einem Frame realisiert werden? Nimm doch einfach eine Form und erzeuge sie dir dynamisch. Das sollte doch völlig ausreichend sein. Frames sind doch nur interessant, wenn du sehr viele Komponenten und logische Bereiche auf einer Form hast, dann kannst du das weiter aufteilen. Hier macht ein Frame doch nicht wirklich sinn - oder doch? Gruss Thorsten |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Thorsten,
Das ganze soll so ähnlich werden wie das Download-Fenster vom Firefox (siehe Anhang), daher der Plan mit den Frames. |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hallo!
Delphi-Quellcode:
Da es sich hier nicht um einen asynchronen Befehl handelt, wird doch gewartet, bis der komplette Stream eingelesen wurde. In dieser Zeit ist der VCL-Hauptthread natürlich blockiert, es werden keine Botschaften oder sonstiges verarbeitet. Da hilft dir auch ein irgendwie gearteter Timer nicht, denn der wartet auch darauf, daß der VCL-Hauptthread wieder auftaucht von der Prozedur...
SizeOfIncomingStream := Socket.ReadInteger;
Socket.ReadStream(IDS, SizeOfIncomingStream); Du musst dafür sorgen, daß der Download in separaten Threads erfolgt. Im Delphiforum habe ich da ein paar TCP-Komponenten gepostet, die dir asynchrones Lesen erlauben und dir synchronisierte Ereignisse wie OnRead und OnProgress liefern, kannst sie dir ja mal anschauen. Stichwort SimpleTCP. Cu, Udontknow |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hmm, wenn ichs ohne Frames und so mache (wie zur Zeit noch) dann hab ich damit kein Problem, die Progressbar läuft und der Rest vom Programm geht auch. Erzeugt der Indy-TCP-Server nicht automatisch nen Thread wenn er was zu tun bekommt :gruebel:
|
Re: Probleme mit Frames und deren Aktualisierung in Formular
:coder2:
Hat nich wer ne Idee? |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hallo,
kennst du schon die Komponente TIdAntiFreeze? Grüße vom marabu |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Ja, hab ich schon ausprobiert, hilft nicht. Das Problem ist ja nicht das sich die Progressbar nie bewegt, sie bewegt sich nur nicht wenn ich das ganze mit dynamisch erzeugten Frames mache, bei nicht-dynamischen Frames geht es.
|
Re: Probleme mit Frames und deren Aktualisierung in Formular
nochmal
*push* sry :duck: |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Sko,
ich habe mal ein Beispiel gemacht. Was du da allerdings für einen Stream hast und wie das gehen soll, blicke ich noch nicht so. Da reicht dein Codeschnipsel nicht aus. Gruss Thorsten |
Re: Probleme mit Frames und deren Aktualisierung in Formular
vielen Dank! ich sehs mir gleich mal an :coder:
|
Re: Probleme mit Frames und deren Aktualisierung in Formular
Wie sieht denn die Aktualisierungsrate des Timers aus?
Ich persönlich würde einen Thread nehmen, da die Timer sich gegenseitig behaken könnten(glaub ich) d.h. während der eine Timer in seinem OnTimer-Event ist, springt ein zweiter in seine bevor der erste sein Event fertig ausgeführt hat. Bei Threads hättest du das Problem denk ich nicht. |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Ich habs jetzt so gebaut wie in omata´s Beispiel, das ist genau das was ich wollte, vielen Dank nochmal dafür :thumb: . Aber ich glaub ich hab da irgendwas bei der Anpassung falsch gemacht: wenn das Fenster, in das die Frames kommen, schon vor der Erstellung des Frames angezeigt wird, friert das Programm ab dem Zeitpunkt der Erstellung des Frames für die Dauer der Datenübertragung ein und beim Beenden des Programms kommt "Ungültiges Fensterhandle", außerdem wird der Frame sofort nach der Übertragung vom Formular entfernt, das hab ich - jedenfalls bewusst - garnicht eingebaut. Wenn das Fenster geschlossen ist, und ich es nach dem Zeitpunkt der Erstellung des Frames erst öffne, geht alles, nichts ist eingefroren, alles läuft wie´s soll und der Frame bleibt auch nach dem Ende der Übertragung da :gruebel: . Hier mal die entsprechenden Code-Schnipsel, ich hoffe ihr könnt mir helfen:
Hier wird das erstellen ausgelöst:
Delphi-Quellcode:
So sieht das der Code für´s Downloadfenster aus:
procedure TMainForm.TCPReceiverExecute(AContext: TIdContext);
var SizeOfIncomingStream: Integer; IDS: TidStreamVCL; DateiFrame: TFDatei; Target, DGroesse: string; DStream: TFileStream; begin if DateiGroesse < 1048576 then DGroesse := RealToStr(DateiGroesse/1024) + ' KB'; //Dateigröße ist eine globale int64 Variable if DateiGroesse > 1048576 then DGroesse := RealToStr(DateiGroesse/1024/1024) + ' MB'; if DateiGroesse > 1073741824 then DGroesse := RealToStr(DateiGroesse/1024/1024/1024) + ' GB'; DateiFrame := FDownLoad.add(Target, DGroesse); //<-hier wird der Frame erstellt DStream := DateiFrame.FStream; Application.ProcessMessages; try IDS := TidStreamVCL.Create(DStream); try with AContext.connection do begin try SizeOfIncomingStream := Socket.ReadInteger; Socket.ReadStream(IDS, SizeOfIncomingStream); finally Disconnect; end; end; IDS.VCLStream.Position := 0; finally FreeAndNil(IDS); end; finally with DateiFrame do begin Bar.Position := 100; Fertig := true; FStream.Free; end; end; end;
Delphi-Quellcode:
und so der Code vom Frame:
unit DownLoadForm;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Math, EmpfDatei, StdCtrls; type TLoadForm = class(TForm) SBDateien: TScrollBox; BAuf: TButton; procedure BAufClick(Sender: TObject); private { Private-Deklarationen } DownloadListe: TList; LTimer: TTimer; public { Public-Deklarationen } constructor create(AOwner:TComponent); reintroduce; destructor destroy; override; procedure TimerUpdate(Sender:TObject); function add(Dateiname, Dateigroesse: string): TFDatei; procedure del(Index:integer); function count:integer; end; var LoadForm: TLoadForm; implementation {$R *.dfm} function TLoadForm.count: integer; begin Result := DownloadListe.Count; end; constructor TLoadForm.create(AOwner: TComponent); begin inherited create(AOwner); DownloadListe:=TList.Create; LTimer := TTimer.Create(Self); LTimer.Interval := 500; LTimer.Enabled := false; LTimer.OnTimer := TimerUpdate; end; destructor TLoadForm.destroy; var i: integer; begin for i := 1 to DownloadListe.Count do TFDatei(DownloadListe[i-1]).free; DownloadListe.free; LTimer.free; inherited; end; procedure TLoadForm.TimerUpdate(Sender: TObject); var i:integer; begin for i:=1 to DownloadListe.Count do TFDatei(DownloadListe[i-1]).Refresh; Application.ProcessMessages; end; function TLoadForm.add(Dateiname, Dateigroesse: string): TFDatei; var FrameDownload: TFDatei; ID, i: integer; begin i := 0; ID := 0; while (i < DownloadListe.Count) do begin ID := Max(ID, TFDatei(DownloadListe[i]).ID); inc(i); end; inc(ID); FrameDownload:=TFDatei.create(Self, ID, Dateiname, Dateigroesse); FrameDownload.Parent:=SBDateien; FrameDownload.Align:=alTop; LTimer.Enabled := true; DownloadListe.Add(FrameDownload); for i := 1 to DownloadListe.Count do TFDatei(DownloadListe[i-1]).Align:=alBottom; for i := 1 to DownloadListe.Count do TFDatei(DownloadListe[i-1]).Align:=alTop; result := FrameDownload; BAuf.Enabled:=(DownloadListe.Count > 0); end; procedure TLoadForm.del(Index: integer); begin if (Index >= 0) and (Index < DownloadListe.Count) then begin TFDatei(DownloadListe[Index]).free; DownloadListe.Delete(Index); LTimer.Enabled := (DownloadListe.Count > 0); BAuf.Enabled := (DownloadListe.Count > 0); end; end; procedure TLoadForm.BAufClick(Sender: TObject); var i: integer; begin i := 0; while (i < DownloadListe.Count) do begin if TFDatei(DownloadListe[i]).Fertig then begin del(i); end else inc(i); end; end; end.
Delphi-Quellcode:
unit EmpfDatei;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ComCtrls, StdCtrls, ShellAPI; type TFDatei = class(TFrame) Label1: TLabel; Label2: TLabel; LName: TLabel; LGroesse: TLabel; Bar: TProgressBar; Label3: TLabel; IIcon: TImage; LTyp: TLabel; Bevel1: TBevel; private { Private-Deklarationen } DID: integer; public FileName: String; DateiGroesse: Int64; FStream: TFileStream; DFertig: boolean; constructor create(AOwner:TComponent; ID:integer; Dateiname, Dateigroesse: string); reintroduce; destructor destroy; override; procedure Refresh; property Fertig: boolean read DFertig write DFertig; property ID: integer read DID; end; implementation uses ErwEinstellungen, Main; {$R *.dfm} function FileIcon(FileName: String): TIcon; var FileInfo: TSHFileInfo; AIcon: TIcon; begin FillChar(FileInfo,SizeOf(FileInfo),#0); SHGetFileInfo(PChar(FileName),0,FileInfo,SizeOf(FileInfo),SHGFI_ICON or SHGFI_LARGEICON); AIcon:=TIcon.Create; Try AIcon.Handle:=FileInfo.HIcon; AIcon.Transparent:=True; Except end; Result:=AIcon; end; function FileType(FileName: String): string; var FileInfo: TSHFileInfo; begin FillChar(FileInfo,SizeOf(FileInfo),#0); SHGetFileInfo(PChar(FileName),0,FileInfo,SizeOf(FileInfo),SHGFI_TYPENAME); Result := FileInfo.szTypeName; end; constructor TFDatei.create(AOwner: TComponent; ID:integer; Dateiname, Dateigroesse:string); begin inherited create(AOwner); Self.Name := 'FrameDownload' + IntToStr(ID); LName.Caption := ExtractFileName(Dateiname); LTyp.Caption := FileType(Dateiname); LGroesse.Caption := Dateigroesse; IIcon.Picture.Icon := FileIcon(DateiName); FStream := TFileStream.Create(Dateiname, fmCreate); DFertig:=false; DID := ID; end; destructor TFDatei.destroy; begin inherited; end; procedure TFDatei.Refresh; begin if not DFertig then begin if (FStream <> nil) and (FStream.Position <> 0) then Bar.Position := round((FStream.Position * 100) / FStream.Size); end; Bar.Update; end; end. |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hi Sko,
Du machst das ja von hinten mit der Faust durchs Auge ;-) Frage 1: Warum Frames ? Du könntest eine Download-Form erstellen wo nichts drin ist ausser einer Scrollbox oder einem Panel je nach dem was Dir lieber ist. Für jeden Download erstellst Du dynamisch ein Panel als Parent für das dynamisch erzeugte Panel nimmst Du das Panel oder die Scrollbox die schon auf der Form ist. Absolut gleiches aussehen wie in Firefox, habe das selber schon mit Indy so in einem Projekt gemacht. Frage 2: Warum Timer ? Vergiss den Timer das kann nur schief gehen. Du solltest für jeden Download einen Thread erstellen oder noch eleganter Du schreibst Dir eine eigene Download-Klasse die von TThread erbt und das dynamische erzeugen und zerstören der Panels übernimmt. Im Thread selber musst Du den Download Fortschritt SYNCRONISIERT anzeigen. *** EDIT *** Schau Dir mal die Sourcen meiner Demo an : ![]() Ganz besonders solltest Du Dir die Klasse FileReceiver.pas anschauen im Server-Teil, ist eigentlich genau das was Du suchst ;-) *** EDIT *** Hoffe Du kannst mit meiner Erklärung was anfragen, Gruß Data |
Re: Probleme mit Frames und deren Aktualisierung in Formular
Hmm, na gut, ich werds mir mal ansehen, ich dachte ich komm um die Threads herum, ich war froh als der eine in dem Programm lief :lol: (für´s Senden von Dateien). Nur wundert mich das trotzdem etwas, denn eigentlich hab ich omatas Beispiel nur angepasst und das Beispiel funktioniert ja. Na dann werd ich mich nochmal mit Threads auseinandersetzen :coder:
|
Re: Probleme mit Frames und deren Aktualisierung in Formular
So, jetz gehts: ich habe eine neue Klasse von TThread abgeleitet die sich mit Synchronize um die Erstellung und Aktualisierung der Frames kümmert. Vielen Dank nochmal an omata für das Beispiel und an Angel4585 und DataCool für den Tipp mit dem Thread :thumb: .
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:29 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