Probleme mit zwei Fenstern (Forms)

Für Fragen von Einsteigern und Programmieranfängern...

Probleme mit zwei Fenstern (Forms)

Beitragvon Adromir » 27. Jun 2018, 00:22 Probleme mit zwei Fenstern (Forms)

Ich bin gerade dabei mir eine GUI für eine Konsolenanwendung zu Basteln. In diesem Program möchte ich zwei Fenster haben. Das eine in dem Man mit der Anwendung "interagiert" und das andere, in dem die Ausgabe der Anwendung angezeigt wird.
Beim Start des Programms sollen beide Fenster gleichzeitig geladen werden. Das bekomme ich zwar hin, über ein OnCreate Event im Hauptfenster (geht das noch eleganter?). Wenn ich aber jetzt den Output an das zweite Fenster sende, dann kriege ich ein Access Violation. Wie kann ich eine Variable aus dem einen Fenster (Formular) an das andere übergebe, schmeisst mir das einenSIGSEV Fehler aus. Ich such mir gerade einen wolf.. Das einzige was klappt ist das fenster direkt bei der Übergabe zu erschaffen und dann wieder zu zerstören, womit aber der Output der vorherigen eingabe verloren geht :/

Weiß jemand, wie ich das Hinkriege?
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon m.fuchs » 27. Jun 2018, 07:52 Re: Probleme mit zwei Fenstern (Forms)

Magst du uns vielleicht ein kleines bisschen Quellcode zeigen?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1963
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon MacWomble » 27. Jun 2018, 11:10 Re: Probleme mit zwei Fenstern (Forms)

Für mich hört sich das nach einem Fall für den tiOPF-Mediator an, zumindest könnte man diesen hierzu elegant nutzen.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.
MacWomble
 
Beiträge: 576
Registriert: 17. Apr 2008, 00:59
Wohnort: Freiburg
OS, Lazarus, FPC: Mint 19 Cinnamon / CodeTyphon Generation V Plan 6.60 | 
CPU-Target: Intel i7 64/32 Bit
Nach oben

Beitragvon Adromir » 27. Jun 2018, 11:11 Re: Probleme mit zwei Fenstern (Forms)

Also ich versuch es mal auf das wichtigste Runterzubrechen. Ich habe 3 Units main_window (das Hauptfenster), console_window (das Konsolenfenster) und eine Unit (ADBCommands) in der ich zur besseren Übersicht häufig gebrauchte Prozeduren/Funktionen auslagere.

die Unit main_window


Code: Alles auswählen
 
uses
       [...], ADBCommand, console_window;
 
[...]
{ Tadb_gui }
 
procedure Tadb_gui.oncreate(Sender: TObject);
var
  adb_output : TStringList;
  parameter : TStringList;
  frm: Tadb_console;
begin
 
    // Konsolen Fenster wird geöffnet)
    frm := Tadb_console.Create(nil);
    frm.Show
 
    parameter := TStringList.Create;
    parameter.Add('devices');
    parameter.Add('-l');
 
    // Konsolenprogramm wird aufgerufen und der Rückgabewert (TStringList) an
    //das Konsolenfenster gesendet
 
    adb_output := adb(parameter);
    ListUSBDevices(adb_output);
    Send2Console(adb_output);
    adb_output.Free;
end;
 



Hier die Funktion zum Senden des Outputs:

Code: Alles auswählen
 
procedure Send2Console(input: TStringList);
var
  begin
   adb_gui.adb_console_output.Lines.Assign(input);
  end;
 
 


das Konsolenfenster beinhaltet im Prinzip nur ein Formular mit namen adb_gui und einem TMemo (adb_console_output) in das die Ausgabe geschrieben wird.

So Schmeißt mir das ganze einen SIGSEV Fehler entgegen. Wenn ich direkt beim Start in der Hauptunit eine Ausgabe nach dem Öffnen des Fensters schicke per
Code: Alles auswählen
 
 frm.adb_console_output.Lines.Assign(adb_output);
 


anstelle der Funktion send2Console dann wird das Konsolenfenster mit einem Korrekten Output angezeigt. Jeder weitere Aufruf der Funktion führt zu dem SIGSEV fehler.
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon shokwave » 27. Jun 2018, 12:32 Re: Probleme mit zwei Fenstern (Forms)

Hallo,

man möge mich korrigieren wenn ich falsch liege, aber assign weist ein Objekt zu, welches du eine Zeile weiter zerstörst.
Code: Alles auswählen
 
    Send2Console(adb_output); // <-- Zuweisung des Objekts adb_outut an adb_gui.adb_console_output.Lines
    adb_output.Free; //  <-- Zerstörung von adb_gui.adb_console_output.Lines

Damit scheitert jeder weitere Zugriff auf adb_gui.adb_console_output.Lines.

Meines Erachtens nach wäre es besser den Inhalt der Stringlist zu kopieren. z.B. so:
Code: Alles auswählen
procedure Send2Console(input: TStringList);
var
  begin
   adb_gui.adb_console_output.Lines.AddStrings(input);
  end;


Habe es jetzt nicht getestet. Hoffe es hilft dir dennoch weiter.
mfg Ingo
shokwave
 
Beiträge: 420
Registriert: 15. Nov 2007, 16:58
Wohnort: Rudolstadt
OS, Lazarus, FPC: Win10 (L 1.6 FPC 3.0.0) | 
CPU-Target: i386,x64
Nach oben

Beitragvon Adromir » 27. Jun 2018, 13:03 Re: Probleme mit zwei Fenstern (Forms)

Ich werde es mal heute Abend testen. Danke für deine Idee.

Ich hab mir noch einen anderen Weg überlegt, obwohl ich nicht sicher bin, wie vernünftig das ist..

Ich schreibe den Output in eine globale Variable. Im Konsolenfenster wird diese periodisch mittels einer Schleife abgefragt und der Inhalt in das Memo kopiert und der Inhalt der Variable dann gelöscht.. Würde das so sinnvoll funktionieren?
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon shokwave » 27. Jun 2018, 17:23 Re: Probleme mit zwei Fenstern (Forms)

Adromir hat geschrieben:Ich schreibe den Output in eine globale Variable. Im Konsolenfenster wird diese periodisch mittels einer Schleife abgefragt und der Inhalt in das Memo kopiert und der Inhalt der Variable dann gelöscht.. Würde das so sinnvoll funktionieren?

Ich glaube der allgemeine Konsens hier im Forum ist, dass globale Variablen keine gute Lösung sind.

Wenn es dir um die Zugriffsverletzung beim Start des Programms geht, die auftritt, weil du auf die 2. Form zugreifst, bevor sie existiert, das umgehe ich üblicherweise, indem ich Form1 eine Variable gebe(z.B. isStartup), diese im OnCreate auf True setze und den Teil, der beim Start des Programms auf die 2. Form zugreift in OnShow ausführe, jedoch nur wenn isStartup True ist.(So viele Kommas und kein Punkt. Irgendwas stimmt da nicht...)
Etwa so:
Code: Alles auswählen
uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    isStartup: Boolean;
  public
 
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  isStartup:= true;
  doPrepareStuff;
end;
 
procedure TForm1.FormShow(Sender: TObject);
begin
  if isStartup then
  begin
    doStuffWithForm2;
    Form2.Show
    isStartup:= false;
  end;
end;
end.

Das isStartup mache ich deswegen, weil OnShow nicht nur beim Start des Programms aufgerufen wird, sondern z.B. auch beim wieder anzeigen nach einem minimieren.

Ich hoffe ich habe mich halbwegs verständlich ausgedrückt.
mfg Ingo
shokwave
 
Beiträge: 420
Registriert: 15. Nov 2007, 16:58
Wohnort: Rudolstadt
OS, Lazarus, FPC: Win10 (L 1.6 FPC 3.0.0) | 
CPU-Target: i386,x64
Nach oben

Beitragvon Adromir » 28. Jun 2018, 14:28 Re: Probleme mit zwei Fenstern (Forms)

So, ich hab das das mal probiert.. Aber ich krieg immer noch den Fehler..

komischerweise, wenn ich das Form nur mit

Code: Alles auswählen
 
adb_console.Show;
 


aufrufe, kriege ich schon seinen SIGSEV fehler Der bleibt zumindest aus wenn ich das Formular Komplet mit
Code: Alles auswählen
    adb_console := Tadb_console.Create(nil);
    adb_console.Show


erzeuge. Danach aber wieder beim Senden an das Fenster den SIGSEV Fehler. Und der verweist immer auf die Funktion

Code: Alles auswählen
 
procedure Send2Console(input: TStringList);
  begin
    adb_console.adb_console_output.Lines.AddStrings(input);
  end;   
 
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon shokwave » 28. Jun 2018, 16:07 Re: Probleme mit zwei Fenstern (Forms)

Adromir hat geschrieben:Der bleibt zumindest aus wenn ich das Formular Komplet mit
Code: Alles auswählen
    adb_console := Tadb_console.Create(nil);
    adb_console.Show

erzeuge.

Wo erzeugst du "adb_console"? Im OnCreate/OnShow? Und wichtiger, wo zerstörst du es? Im OnClose der Hauptform, hoffe ich.
Diese SIGSEV-Fehler bedeuten, dass du auf ein Objekt zugreifst, welches noch nicht oder nicht mehr existiert.
mfg Ingo
shokwave
 
Beiträge: 420
Registriert: 15. Nov 2007, 16:58
Wohnort: Rudolstadt
OS, Lazarus, FPC: Win10 (L 1.6 FPC 3.0.0) | 
CPU-Target: i386,x64
Nach oben

Beitragvon Adromir » 28. Jun 2018, 17:04 Re: Probleme mit zwei Fenstern (Forms)

Also ich erzeuge das im Oncreate. Ich hab da soGar extra ein Sleep eingebaut, daß ich sicher sein kann, daß es existiert. Zerstören tue ich das momentan Gar nich
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon shokwave » 28. Jun 2018, 18:22 Re: Probleme mit zwei Fenstern (Forms)

Kann ich gerade überhaupt nicht nachvollziehen. Hab mal ein Minidemo erstellt, zum vergleichen.
Code: Alles auswählen
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, unit2,
  StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    isStartup:Boolean;
    testSL: TStringList;
  public
    procedure PrepareStuff;
    procedure Send2Console(input: TStringList);
 
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
//Beim scließen von Form1
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  TestSL.Free;
  Form2.Free; //Form2 zerstören
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  PrepareStuff;
  Send2Console(TestSL);
end;
 
//Beim erstellen von Form1
procedure TForm1.FormCreate(Sender: TObject);
begin
  testSL:= TStringlist.Create;
  Form2:= TForm2.Create(nil)//Form2 erstellen
  Randomize;
  PrepareStuff;
  isStartup:= True;
  Send2Console(TestSL); //was hinschicken
end;
 
//Beim anzeigen von Form1
procedure TForm1.FormShow(Sender: TObject);
begin
  if isStartup then
  begin
    Form2.Show//Form2 anzeigen
    Send2Console(TestSL); //nochmal das selbe hinschicken
  end;
end;
 
procedure TForm1.PrepareStuff;
begin
  testSL.Clear;
  testSL.Add('Test' + IntToStr(Random(100)));
  testSL.Add('Test' + IntToStr(Random(100)));
  testSL.Add('Test' + IntToStr(Random(100)));
end;
 
procedure TForm1.Send2Console(input: TStringList);
begin
  Form2.Memo1.Lines.AddStrings(input);
end;
 
end.

Form2 enthält nur ein TMemo. Die Projektdatei sieht so aus:
Code: Alles auswählen
program Project1;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, unit1, unit2
  { you can add units after this };
 
{$R *.res}
 
begin
  RequireDerivedFormResource:=True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
//  Application.CreateForm(TForm2, Form2); //Auskommentiert, da "von Hand" erstellt
  Application.Run;
end.
 
mfg Ingo
shokwave
 
Beiträge: 420
Registriert: 15. Nov 2007, 16:58
Wohnort: Rudolstadt
OS, Lazarus, FPC: Win10 (L 1.6 FPC 3.0.0) | 
CPU-Target: i386,x64
Nach oben

Beitragvon Adromir » 28. Jun 2018, 18:54 Re: Probleme mit zwei Fenstern (Forms)

Allerherzlichsten Dank für deine Mühen. Ich werde mal schauen, ob ich das irgendwie eingebaut bekomme. Vielleicht macht es irgendwie auch zicken, daß ich die Funktion send2console in eine weitere Unit ausgelagert habe
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon Adromir » 29. Jun 2018, 08:00 Re: Probleme mit zwei Fenstern (Forms)

Bin wohl ein Hoffnungsloser Fall lol.. Hab versucht meinen Code an dein Beispiel anzupassen, hat nicht geklappt, immer noch die Sigsev Fehler. Bin wohl zu doof dafür. Hab jetzt dein Beispiel genommen um noch mal neu Anzufangen und bis her läuft es 1a. Danke dafür
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

Beitragvon Adromir » 30. Jun 2018, 13:25 Re: Probleme mit zwei Fenstern (Forms)

Falls ich nochmal stören darf.. Ich bin jetzt auf der Basis von shockwaves Code ziemlich weit gekommen. Nun habe ich ein kleines "kosmetisches" Problem. Wenn ich die Applikation starte, erscheint das Konsolenfenster in der Tableiste vor dem Hauptfenster. Kann man das irgendwie ändern?
Adromir
 
Beiträge: 37
Registriert: 28. Apr 2018, 03:09

• Themenende •

Zurück zu Einsteigerfragen



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste

cron
porpoises-institution
accuracy-worried