Zusätzliche Fenster aufrufen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Zusätzliche Fenster aufrufen

Beitrag von 400kmh »

Hallo,

ich möchte, dass sich durch Klick auf einen Button ein zweites Fenster öffnet. Wie lässt sich dies bewerkstelligen? Und wie lassen sich auf dem zweiten Fenster Objekte hinzufügen? Alles, was ich bis jetzt versucht habe, endete mit Fehlermeldungen.

Benutzeravatar
theo
Beiträge: 10947
Registriert: Mo 11. Sep 2006, 19:01

Re: Zusätzliche Fenster aufrufen

Beitrag von theo »

Mach mal diese Tutorials durch:
http://www.delphi-treff.de/tutorials/grundlagen/" onclick="window.open(this.href);return false;
Dann im Speziellen:
http://www.delphi-treff.de/tutorials/vc ... mm/page/8/" onclick="window.open(this.href);return false;

Teekeks
Beiträge: 359
Registriert: Mi 27. Mai 2009, 20:54
OS, Lazarus, FPC: OpenSuse11.4 x86 (Lazarus: 0.9.30 FPC 2.4.2)
CPU-Target: x86
Wohnort: Cottbus

Re: Zusätzliche Fenster aufrufen

Beitrag von Teekeks »

Erste Möglichkeit:
Wenn du das 2. Fenster genauso bearbeiten willst wie das erste:
Bei Lazarus:
Datei→Neues Formular.

Aufgerufen wird es dann über Form2.show;

Andere Möglichkeit:

Code: Alles auswählen

var f:TForm;
    button:TButton;
begin
  // Formular erzeugen:
  f:=TForm.create(nil);
// Größe ändern:
  f.Width:=200;
  f.Higth:=200;
// Titel festlegen:
  f.caption:='Dies ist meine Dynamisch erzeugte 2. Form!';
// Button erzeugen:
  button:=TButton.create(f);
// Elternteil festlegen (damit der Button auch weiß woraus er soll):
  button.parent:=f;
// jetzt kannst du wieder die Position und größe mittels Top,Left,Width und Hight festlegen...
// nun noch ein Clickevent festlegen:
  button.OnClick:=@MyButtonClick;
// MyButtonClick muss so aussehen wie andere Proceduren beim Knopfdrücken auch...
// Auch eine Beschriftung tut dem Knopf gut...
  button.caption:='Hallo Welt!'; 
// Und zum Schluss: Formular anzeigen.
  f.show;
end;
Nun müssen allerdings auch noch die Objekte wieder freigegeben werden.
Das tust du am besten OnClose deiner Hauptform:

Code: Alles auswählen

f.free;
button.free;
Gruß Teekeks

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Zusätzliche Fenster aufrufen

Beitrag von 400kmh »

theo hat geschrieben:Mach mal diese Tutorials durch:
http://www.delphi-treff.de/tutorials/grundlagen/" onclick="window.open(this.href);return false;
Dann im Speziellen:
http://www.delphi-treff.de/tutorials/vc ... mm/page/8/" onclick="window.open(this.href);return false;
Danke. Welche Unterschiede zwischen Delphi und Lazarus gilt es zu beachten?

Benutzeravatar
theo
Beiträge: 10947
Registriert: Mo 11. Sep 2006, 19:01

Re: Zusätzliche Fenster aufrufen

Beitrag von theo »

400kmh hat geschrieben:Danke. Welche Unterschiede zwischen Delphi und Lazarus gilt es zu beachten?
Es gibt bestimmt Unterschiede, aber auf diesem Level ist vieles identisch.
Wenn's um die IDE geht, wird es nicht 1:1 aber ähnlich sein. Ein bisschen mitdenken hilft da bestimmt.
Lazarus benutzt UTF-8 Strings. Bei Delphi hängt's von der Version ab.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Zusätzliche Fenster aufrufen

Beitrag von Patito »

Teekeks hat geschrieben:

Code: Alles auswählen

f:=TForm.create(nil);
button:=TButton.create(f);
button.OnClick:=@MyButtonClick;

Code: Alles auswählen

f.free;
button.free;
Aber bitte nicht den Button doppelt freigeben!
Wenn eine Komponente mit einem Owner erzeugt wurde (TButton.Create(Owner: TComponent))
gehört sie dem Owner, der dann dafür zuständig ist die Komponente freizugeben.

Also entweder:

Code: Alles auswählen

form:=TForm.create(nil);
button :=TButton.create(form);
// ...
form.Free;
oder:

Code: Alles auswählen

form:=TForm.create(nil);
button :=TButton.create(nil);
// ...
button.free;
form.Free;

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Zusätzliche Fenster aufrufen

Beitrag von 400kmh »

Teekeks hat geschrieben:Erste Möglichkeit:
Wenn du das 2. Fenster genauso bearbeiten willst wie das erste:
Bei Lazarus:
Datei→Neues Formular.

Aufgerufen wird es dann über Form2.show;

Andere Möglichkeit:

Code: Alles auswählen

var f:TForm;
    button:TButton;
begin
  // Formular erzeugen:
  f:=TForm.create(nil);
// Größe ändern:
  f.Width:=200;
  f.Higth:=200;
// Titel festlegen:
  f.caption:='Dies ist meine Dynamisch erzeugte 2. Form!';
// Button erzeugen:
  button:=TButton.create(f);
// Elternteil festlegen (damit der Button auch weiß woraus er soll):
  button.parent:=f;
// jetzt kannst du wieder die Position und größe mittels Top,Left,Width und Hight festlegen...
// nun noch ein Clickevent festlegen:
  button.OnClick:=@MyButtonClick;
// MyButtonClick muss so aussehen wie andere Proceduren beim Knopfdrücken auch...
// Auch eine Beschriftung tut dem Knopf gut...
  button.caption:='Hallo Welt!'; 
// Und zum Schluss: Formular anzeigen.
  f.show;
end;
Nun müssen allerdings auch noch die Objekte wieder freigegeben werden.
Das tust du am besten OnClose deiner Hauptform:

Code: Alles auswählen

f.free;
button.free;
Gruß Teekeks
Zur zweiten Möglichkeit:

Folgender Code funktioniert:

Code: Alles auswählen

unit Unit1; 
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 
 
var
  Form1: TForm1; 
  f:TForm;
  button:TButton;
 
implementation
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  f:=TForm.create(nil);
  f.Width:=200;
  f.Height:=200;
  f.caption:='Dies ist meine Dynamisch erzeugte 2. Form!';
  button:=TButton.create(f);
  button.parent:=f;
 
  button.caption:='Hallo Welt!';
  f.show;
end;
 
initialization
  {$I Unit1.lrs}
 
end.
Es werden zwei Fenster angezeigt. Das zweite heißt "Dies ist meine Dynamisch erzeugte 2. Form!". Auf ihm ist ein Button mit der Beschriftung "Hallo Welt!".

Wenn ich die Ausführung beende erscheint jedoch folgende Fehlermeldung: "projekt projekt1.exe raised exception class 'External: SIGSEGV'". Wenn ich dann versuche die Anwendung neu zu starten, ohne Lazarus zuvor neu zu starten erscheint direkt diese Fehlermeldung. Wie kann ich das Problem beheben?

Wenn ich versuche auch noch folgenden Befehl

"button.OnClick:=@MyButtonClick;"

und

"procedure MyButtonClick;
begin
button.caption:='funktioniert';
end;"

in die Unit einzubauen bekomme ich folgende Fehlermeldung: "unit1.pas(45,19) Error: Incompatible types: got "<address of procedure;Register>"" expected "procedure variable typ of procedure(TObjekt) of objekt;Register>".

Wie behebe ich dieses Problem?

Von "f.free;" und "button.free;" verstehe ich den Sinn nicht. Wenn ich diese Befehle in die Prozedur "TForm1.FormCreate" einbaue erscheint erneut die Fehlermeldung "projekt projekt1.exe raised exception class 'External: SIGSEGV'" noch bevor die Anwendung ausgeführt werden könnte;

Benutzeravatar
theo
Beiträge: 10947
Registriert: Mo 11. Sep 2006, 19:01

Re: Zusätzliche Fenster aufrufen

Beitrag von theo »

Warum willst du das überhaupt dynamisch erzeugen und designen?
Das ist bei Formularen eigentlich nicht üblich (Jedenfalls nicht bei deinem Kenntnisstand ;-)

zum Click:

Das muss eine Methode von TForm1 mit dem entsprechenden Parameter sein.
Also nicht:

procedure MyButtonClick;

sondern

procedure TForm1. MyButtonClick(Sender: TObject);

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Zusätzliche Fenster aufrufen

Beitrag von 400kmh »

theo hat geschrieben:Warum willst du das überhaupt dynamisch erzeugen und designen?
Das ist bei Formularen eigentlich nicht üblich (Jedenfalls nicht bei deinem Kenntnisstand ;-)
Ich habe bisher einige Male mit Lazarus die Erfahrung gemacht, dass durch irgendwelche Fehler, die ich gemacht habe, ähnlich wie oben beschrieben, Anwendungen sich nicht mehr starten liesen, selbst als ich den Fehler scheinbar wieder entfernt hatte. Je mehr dynamisch erzeugt und designt wird, desto schneller geht es, ein neues Projekt auf den Stand des alten Projektes vor dem Fehler zu bringen. Ich finde es auch irgendwie übersichtlicher, wenn alles im Code steht, anstatt manches im Code und manches im Objektinspektor.

Benutzeravatar
theo
Beiträge: 10947
Registriert: Mo 11. Sep 2006, 19:01

Re: Zusätzliche Fenster aufrufen

Beitrag von theo »

Naja, der Aufwand ist aber doch um einiges grösser.
Auch ein Lazarus Formular (*.lfm) ist eine Text Datei, die man ggf. manuell bearbeiten kann.
Das mache ich oft, zum konvertieren von Delphi Formularen.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Zusätzliche Fenster aufrufen

Beitrag von Patito »

theo hat geschrieben:Warum willst du das überhaupt dynamisch erzeugen und designen?
Das ist bei Formularen eigentlich nicht üblich (Jedenfalls nicht bei deinem Kenntnisstand ;-)
Bei Micky-Maus Anwendungen ist das sicher nicht üblich, aber bei allem was halbwegs modular aufgebaut ist, sollte sowas eigentlich Standard sein.
Wie will man denn sonst eine Library schreiben, die ein paar GUIs enthält?
Soll der Benutzer der Library etwa erst alle Formulare, die in der Library sind, von Hand in die Anwendung reinklicken?

Also für sowas wie:

Code: Alles auswählen

TMyLibrary.AskUserForSomething(const Param: TMyParams): TMyDialogResult;
Und wenn man eine DLL schreibt, in der ein paar Formulare sind, sollte man das mit dem dynamisch erzeugen - und wieder freigeben(!!!) von Formularen auf jeden Fall drauf haben.

Leider gibt es im Delphi-Umfeld oft Komponenten, die mit dem dynamisch erzeugen und freigeben nicht klarkommen (könnte da so manches prominente Beispiele nennen)...

Daher: Bei allen Formulare und Komponenten sollt man testen, ob sie sich dynamisch verwenden lassen. Wenn nicht, gehörten die so schnell wie möglich in die Tonne. Sonst ist irgendwann die Überraschung groß wenn auf einmal nichts mehr funktioniert wenn man versucht den Code in eine DLL o.ä. einzubauen...
Zuletzt geändert von Patito am Do 6. Mai 2010, 07:58, insgesamt 3-mal geändert.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Zusätzliche Fenster aufrufen

Beitrag von Patito »

400kmh hat geschrieben: Folgender Code funktioniert:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  f:=TForm.create(nil);
  f.Width:=200;
  f.Height:=200;
  f.caption:='Dies ist meine Dynamisch erzeugte 2. Form!';
  button:=TButton.create(f);
  button.parent:=f;
 
  button.caption:='Hallo Welt!';
  f.show;
end;
Ne, tut es nicht. Du leakest dein f (f wird erzeugt und nirgends mehr freigegeben)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Zusätzliche Fenster aufrufen

Beitrag von pluto »

Ne, tut es nicht. Du leakest dein f (f wird erzeugt und nirgends mehr freigegeben)
Wenn er es frei geben würde, nach dem Show, würde es eine AV geben. Am besten beim erzeugen des Fensterns nicht NIL angeben sondern From1 oder sowas. Dann wird es Automatisch frei geben.
MFG
Michael Springwald

Antworten