Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Form aufrufen und anpassen (https://www.delphipraxis.net/154856-form-aufrufen-und-anpassen.html)

Remedy7 28. Sep 2010 10:50

Delphi-Version: 2006

Form aufrufen und anpassen
 
Hallo Forum,

hatte vor kurzen die beliebte Frage danach eine Form mehrfach zu öffnen.
Die sah in meinem Programm nach tatkräftiger Unterstützung der User dann so aus:

Delphi-Quellcode:
 MyForm:Array of TForm2
      setlength(MyForm,11)

      for t := 0 to 10 do begin
        MyForm[t] := Form5.Create(Application);
        MyForm[t].show;
      end;
   begin
      for i:=1 to Eingabe do

      begin
        MyFrm := TForm5.Create(Application.MainForm);
        MyFrm.Left := Random(Screen.Width - Form5.Width) +1;
        MyFrm.Top := Random(Screen.Height - Form5.Height) +1;
        MyFrm.Show;
      end;
Leider war das nicht sehr zufriedenstellend da die Formen keine Bezug zur eigentlichen Form hatten.

Dann habe ich es über Buttons realisiert:
Delphi-Quellcode:
procedure TForm2.Button10Click(Sender: TObject);
var
  i: Integer;
begin
with TForm5.Create(Application.MainForm) do;      //self

begin
  for i := 1 to 1  do


  Form5.left:= Random(Screen.Width - Form5.Width);
  Form5.Top:= Random(Screen.Height - Form5.Height);
  Form5.caption:= Form2.Label22.caption;
  Form5.Name := Form2.Label22.caption;
  Form5.Show;

end;
end;
Anhand von "Form5.caption:= Form2.Label22.caption" sollte man auch sehen was ich mit Bezug meine.

Auch das funktioniert nur leider ist es so das mir Form 5 zwar neu geöffnet wird aber dafür die vorher geöffnete Form5 geschlossen wird.

Wie kann ich das lösen das die "alte" Form5 geöffnet bleibt obwohl ich mit einem anderen Button die Form nochmal öffne?


BEste Grüße

DeddyH 28. Sep 2010 10:57

AW: Form aufrufen und anpassen
 
Wenn Du die Variable Form5 ansprichst, ist damit auch eine ganz bestimmte Instanz gemeint. Wie ist es so?
Delphi-Quellcode:
procedure TForm2.Button10Click(Sender: TObject);
var
  i: Integer;
begin
with TForm5.Create(Application.MainForm) do //self

begin
  for i := 1 to 1 do


  {Form5.}left:= Random(Screen.Width - Form5.Width);
  {Form5.}Top:= Random(Screen.Height - Form5.Height);
  {Form5.}caption:= Form2.Label22.caption;
  {Form5.}Name := Form2.Label22.caption;
  {Form5.}Show;

end;
end;
Oder besser unter Verzicht auf "With":
Delphi-Quellcode:
procedure TForm2.Button10Click(Sender: TObject);
var
  Frm: TForm5;
begin
  Frm := TForm5.Create(Application.MainForm);
  Frm.left:= Random(Screen.Width - Frm.Width);
  Frm.Top:= Random(Screen.Height - Frm.Height);
  Frm.caption:= Form2.Label22.caption;
  Frm.Name := Form2.Label22.caption;
  Frm.Show;
end;

GHorn 28. Sep 2010 11:11

AW: Form aufrufen und anpassen
 
Der Frm.Name muss aber eindeutig sein. Und nur so kannst Du die
diversen Forms auch kontrolliert wieder schließen.

xZise 28. Sep 2010 11:14

AW: Form aufrufen und anpassen
 
Ach dieses With, das macht doch alles unübersichtlich. Ich übersetze mal deinen Code in "ohne-with-Code":
Delphi-Quellcode:
var
  x : TForm5; // Variable von with
begin
  x := TForm5.Create(Application.MainForm);
  for i := 1 to 1 do
    Form5.left:= Random(Screen.Width - Form5.Width);
  Form5.Top:= Random(Screen.Height - Form5.Height);
  Form5.caption:= Form2.Label22.caption;
  Form5.Name := Form2.Label22.caption;
  Form5.Show;
Und jetzt solltest du dich fragen, was du genau gemacht hast: Ich weiß es nicht :stupid: aber das with hat keine Auswirkungen, weil es kein Attribut oder Methode gibt in der Klasse TForm5 die Form5 heißt.

Was du eher machen willst, hat dir DeddyH schon gezeigt. Wobei die For-schleife einerseits begin und end haben sollte und andererseits außerhalb des withs sein sollte. Warum? Naja du erstellst einmal das Formular, aber du setzt die Eigenschaften (aktuell) einmal. Würde die Schleife zweimal laufen würde, alles zweimal gesetzt werden, aber keine neue Form erstellt.

Und zu einem anderen Punkt: Wo ist Form5 definiert? Vermutlich in der Unit5 in so einem var Abschnitt:
Delphi-Quellcode:
var
  Form5 : TForm5;
Dann gebe ich dir einen Tipp: Benutze nie nie nie nie nie diese Variable ;) Es gibt Ausnahmen, aber in der Regel wirst du sie nicht brauchen und Probleme schaffen.

Stattdessen nutze entweder die interne Variable von with, oder (mein Vorschlag) verzichte auf das with und lege eine lokale Variable an (siehe DeddyH).

MfG
Fabian

PS: @GHorn: Bedingt: Da er einen Owner angibt, werden sie automatisch geschlossen bzw. freigegeben.

shmia 28. Sep 2010 12:15

AW: Form aufrufen und anpassen
 
@xZise: du hast aber selbst oben die Variable "Form5" benützt obwohl wie die Instanz in Variable "x" erzeugt hast.
Sicher nur im Eifer des Gefechts; kannst ja noch korrigieren.

xZise 28. Sep 2010 14:05

AW: Form aufrufen und anpassen
 
Naja ganz 100% muss das nicht stimmen. Und zwar dann, wenn die Klasse TForm5 ein öffentliches Attribut oder Methode hat die auch Form5 heißt. Dann weiß ich nicht, was with da bevorzugt. Ich meine es ist ja quasi
Delphi-Quellcode:
x.[...]
innerhalb von with. Das ist nur nicht der Fall, wenn
Delphi-Quellcode:
x.[...]
in den Moment nicht gültig wäre. Zum Beispiel:
Delphi-Quellcode:
with TButton.Create(nil) do
begin
  Caption := 'Foo';
  Text := 'Text';
end;
Die erste Zeile funktioniert und der Button ist vermutlich mit Foo beschriftet, bei der zweiten Zeile funktioniert es allerdings nicht, da TButton keine Eigenschaft Text hat. Das heißt, wenn das z.B. ein TEdit wäre (oder davon abgeleitet), dann würde in diesem Fall da stehen:
Delphi-Quellcode:
x : TButton;

x := TButton.Create(nil);
x.Caption := 'Foo';
Self.Text := 'Text';
Es kann natürlich sein, dass ich tatsächlich was übersehen habe, aber ich bin mir sicher, dass es tatsächlich so "übersetzt" würde. Und mein Code soll natürlich keine Korrektur sein sondern eine Übersetzung.

MfG
Fabian

DeddyH 28. Sep 2010 14:20

AW: Form aufrufen und anpassen
 
Zum Sinn und Unsinn von with gibt es hier schon einige Threads. Ich kann nur raten, auf dessen Gebrauch zu verzichten, da dieser u.U. zu unvorhergesehenen Effekten führen kann. Wenn es so implementiert worden wäre wie in (Visual) Basic, dann sähe das vielleicht anders aus (dass ausgerechnet ich mal VB lobe hätte ich mir auch nie träumen lassen :lol:).

Remedy7 29. Sep 2010 18:22

AW: Form aufrufen und anpassen
 
Hallo,

entschuldigt die verspätete Antwort.

Also Fprm5 ist aus Unit5 ja.

Ich habe dann mal die beiden Beispiele ausprobiert aber leider besteht weiter das Problem das Form5 nicht neu geöffnet wird sondern quasi die alte einfach überschrieben wird.
Sie soll aber immer wieder neu erstellt werden...


Schonmal dank für die aufschlussreichen Beiträge und die Hilfe.
Ich kann leider immer nur Abends mal ein bis 2 Stündchen an Delphi arbeiten und werde deshalb nur langsam schlauer:thumb:

Gruß

xZise 29. Sep 2010 22:29

AW: Form aufrufen und anpassen
 
Du kannst den zweiten Code aus den zweiten Beitrag nehmen (den ohne with). Da sollte sich bei jedem klick auf den Button ein neues Fenster öffnen. Und wenn du mehrere Fenster brauchst, dann kannst du das in einer Schleife ausführen. Ich wollte die nur zeigen, was man immer verhindern sollte: Die Variablen wie Form5 zu nehmen. Dadurch handelst du dir nur Fehler ein. Aktuell kann ich nicht so viel und schnell tippen, aber wenn du willst kann ich es weiter ausführen.

Fabian

Remedy7 5. Okt 2010 17:45

AW: Form aufrufen und anpassen
 
Guten Abend und Hallo xZise,

danke für die Hilfe, werde mal versuchen das ganze in eine Schleife zu packen.

Natürlich kannst du mir gern etwas erklären ich bin über jede Info dankbar...

MfG Remedy7

xZise 6. Okt 2010 12:31

AW: Form aufrufen und anpassen
 
Moin,
also das wichtige ist erst mal zu verstehen was man möchte: Du möchtest eine bestimmte Anzahl Formulare. Zum Beispiel 42 :stupid: dann musst du auch 42x ein Formular erstellen. Wie erstellt man ein Formular? Indem man TForm.Create aufruft. Oder in deinen Fall TForm5, dabei ist TForm5 quasi TForm: Nämlich kann TForm5 alles das was auch TForm kann. Also ein (leeres) Fenster anzeigen. TForm5 ist nur eine Erweiterung von TForm und bietet zum Beispiel einige platzierte Komponenten an.

Das heißt, wenn du 42 Formulare haben willst, musst du 42x TForm5.Create aufrufen. Nun bei dir ist die Schleife anfangs falsch angesetzt:
Du erstellst ein Forumlar (du rufst 1. TForm5.Create auf) und setzt dann in einer Schleife den linken Abstand der Variable Form5. Nun hat allerdings Form5 gar nichts mit mit deinen neuen Fenster zu tun. Das ist nämlich eine globale Variable die irgendwo definiert ist, und beschrieben wird, wenn man das Fenster von Delphi automatisiert öffnen lassen will.

Man kann aber auch so etwas machen:
Delphi-Quellcode:
var
  foobar : TForm5;

procedure foo;
var
  form : TForm5;
begin
  form := TForm5.Create(nil);
  try
    foobar.ShowModal();
  finally
    form.Free;
  end;
end;
Jetzt benutze ich foobar, was genauso wie Form5 definiert ist, obwohl nirgendswo es erstellt wurde. Eventuell wurde irgendwo ein Wert drin gespeichert, aber das wissen wir hier nicht. Deshalb sollte man globale Variablen immer vermeiden (zu nutzen).

Außerdem das with-Konstrukt: Es gibt das Lager, welches es hasst und das Lager welches es gerne nutzt. Du selber musst entscheiden, wie häufig und wo du with benutzt, aber dann sollte es übrigens richtig geschehen:
Delphi-Quellcode:
with x do
begin
  // Hier kann man das x. jetzt sparen
end;
Du hast da jetzt für das x einfach TForm5.Create(...) geschrieben, alles soweit wunderbar, aber dann benutzt du da drin die Variable form5. Erstens steht die neue Form nicht da drin (wo sollte das denn gesehen) und zweitens könnte man sich das with sparen, wenn man sowieso nicht die Features nutzt.

Ein letztes Wort zur Form5: Es gibt zwei Stellen, wo gerne darauf zurückgegriffen wird:
Delphi-Quellcode:
procedure TForm5.DoFoo;
begin
  Form5.Caption := 'Fooooooooo bar :D';
end;
In diesem Fall, setzt du die Caption von Form5, aber das kann alles sein. Ein Beispiel:
Delphi-Quellcode:
procedure TWoanders.FooWindow;
var
  frm : TForm5;
begin
  frm := TForm5.Create(nil);
  try
    frm.DoFoo;
  finally
    frm.Free;
  end;
end;
Jetzt wird von dem Objekt frm die Methode DoFoo aufgerufen. Allerdings steht in frm ein ganz anderes Fenster, wie in in Form5. Das ist entweder leer (= nil) oder mit einem anderen Fenster gefüllt. Wie setzt man dann die Caption? Einfach weglassen:
Delphi-Quellcode:
procedure TForm5.DoFoo;
begin
  Caption := 'Fooooooooo bar :D';
end;
Das ist die kurze Schreibweise für:
Delphi-Quellcode:
Self.Caption := 'Fooooooooo bar :D';
Dabei sagt das Self. aus: Ich bin gemeint.

Mal ein Beispiel aus den Leben gegriffen: Fritz möchte eine Spritztour machen. Natürlich kann mehrere Fritze geben, und jetzt kann Fritz sagen:
Zitat:

Hej Fritz (er meint sich selber) will ne Spritztour machen.
Jetzt musst du hoffen, dass "Fritz" mit diesem speziellen Fritz assoziiert wird, ansonsten wird irgendein anderer Fritz eine Spritztour machen. Stattdessen kannst du aber sagen:
Code:
Hej! Ich will ne Spritztour machen.
Die andere Möglichkeit Form5 zu verwenden wäre, so ähnlich wie du das gemacht hast:
Delphi-Quellcode:
Form5 := TForm5.Create();
...
Da kann man aber wunderbar lokale Variablen verwenden (siehe über mir). Außerdem was passiert, wenn in Form5 was wichtiges drin Stand? Das ist dann auf jeden Fall weg.

Es gibt einen Grund, warum man dennoch die globale Variable nutzen kann: Wenn das Formular bereits erstellt ist (so ist das automatisch bei Delphi der Fall) kann man direkt darauf zugreifen. Aber so kann man auch maximal ein Fenster speichern.

Man könnte das umgehen, indem man eine private/öffentliche (!= globale) Variable erstellt und dann beim Erstellen des Formulars die nötigen Unterformulare auch zu erstellen. So kann man mehrere Fenster speichern, und ist die globale Variable los geworden.

MfG
Fabian

PS: Ich hoffe das stimmt soweit alles!

Remedy7 12. Okt 2010 14:29

AW: Form aufrufen und anpassen
 
Hallo,

okay Danke. Ich denke das verstehe ich soweit. Es fällt mir gerade nur schwer das in meinen Code zu basteln.

Nochmal schnell zur Erklärung.

Unit2, von der ich Unit5 aufrufe, sieht so aus:

Label1 Button1
Label2 Button2
Label3 Button3
. .
. .
. .

Durch eine Doppelklick auf Label öffnet sich eine Maske wo ich den Namen des Labels eintragen muss.
Mit einem Klick auf den nebenstehenden Button öffnet sich dann Unit5 (Form5) deren Name dann praktisch der Inhalt von Label sein soll damit das gnaze später einen Bezug hat. Das ist das warum ich Unit5 mehrer male öffnen können muss.

In meinem Code ist das nun also "procedure button1.click....."
Du hast jetzt hier "procedure foo" verwendet. Was genau bewirkt das? Kann ich das uaf den Button übernehmen?

Ich weiß es ist kompliziert aber ich hab schon gefühlte 100 mal alle Tutorials im Inet gelesen und fühl mich trotzdem nicht schlauer was die programmiererei angeht!

Grüße Sascha

xZise 13. Okt 2010 09:46

AW: Form aufrufen und anpassen
 
Moin Sascha

Zitat:

Zitat von Remedy7 (Beitrag 1055356)
[...]Durch eine Doppelklick auf Label öffnet sich eine Maske wo ich den Namen des Labels eintragen muss.
Mit einem Klick auf den nebenstehenden Button öffnet sich dann Unit5 (Form5) deren Name dann praktisch der Inhalt von Label sein soll damit das gnaze später einen Bezug hat. Das ist das warum ich Unit5 mehrer male öffnen können muss.

Warum du die mehrmals öffnest interessiert mich hier gerade nicht ;) Aber wo du es gerade erwähnst, könntest du natürlich speichern, welches Edit "Schuld" dafür war, dass sich das Fenster öffnete.

Zitat:

Zitat von Remedy7 (Beitrag 1055356)
[...]In meinem Code ist das nun also "procedure button1.click....."
Du hast jetzt hier "procedure foo" verwendet. Was genau bewirkt das? Kann ich das uaf den Button übernehmen?

Ereignisse sind wie normale Prozeduren, nur war ich etwas Tippfaul. Du kannst normalerweise den Inhalt immer übernehmen.

MfG
Fabian

Remedy7 13. Okt 2010 11:52

AW: Form aufrufen und anpassen
 
wie meinst du "speichern"???

stahli 13. Okt 2010 12:55

AW: Form aufrufen und anpassen
 
Sicher in einer Eigenschaft, die in der Form deklariert wird...
So etwa:

TheForm.CallComponent := MyControl;
TheForm.Show;

xZise 14. Okt 2010 19:08

AW: Form aufrufen und anpassen
 
Genau so. Du legst eine Variable für das Formular an, und speicherst da drin zu welchen Edit es gehört.

MfG
Fabian


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