SENDER an andere Form übermitteln

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

OK, generell funktioniert das so.
Aber: Ich muss jedes Label namentlich benennen, bei Änderungen etwas Mehraufwand.

Code: Alles auswählen

 
  if lbl = Label1 then valIndex := 0;
  if lbl = Label4 then valIndex := 1;
  if lbl = Label7 then valIndex := 2;
 

Bei meiner Version reicht copy&paste des Labels. Und wenn ich eines wieder lösche passiert auch nix.

Trotzdem danke, mal schauen was ich noch draus machen kann! Auf die Idee der Form2 ein property zuzuweisen bin ich echt nicht gekommen.

Benutzeravatar
kupferstecher
Beiträge: 416
Registriert: Do 17. Nov 2016, 11:52

Re: SENDER an andere Form übermitteln

Beitrag von kupferstecher »

Fuer was soll der ValIndex ueberhaupt gut sein? Ich vermute das ist ein Relikt aus einer anderen Anwendung.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: SENDER an andere Form übermitteln

Beitrag von wp_xyz »

Ich glaube nicht, dass es eine gute Idee ist, einen Zahlenwert in der Caption eines Labels zu speichern. Der Wert, der in dem Eingabeformular eingegeben ist, ist ein Integer, kein String - basta. Wenn es als String übergeben ist, kommt gleich eine Maschinerie ins Laufen, die prüfen muss, ob der String wirklich eine Zahl ist!

Für die Ablage der eingegebenen Werte habe ich dem Projekt ein Array FCurrValues gegeben. valIndex ist der Index für dieses Werte-Array (aber man kann das natürlich auch anders lösen...). Mein Code war nur eine Quick&Dirty-Lösung für zwei Labels. Bei mehr Labels könntest du z.B. den Array-Index im Tag des Labels ablegen, dann sparst du dir die zugebenermaßen unschöne if-Abfrage.

ppahl, an deiner Lösung gefällt mir nicht, dass das Hauptformular mit den Digits des Eingabeformulars rumhantieren muss, um den Wert zu konstrieren. Falls dein RPi später einmal eine vernünftige Tastatur hat, musst du fehleranfällig an mehreren Stellen im Programm Änderungen vornehmen, um das Programm mit Tastatur verwenden zu können. In meiner Lösung ist die Eingabe komplett gekapselt, und das Eingabeformular übergibt eine Zahl. Wie die Zahl erzeugt wird - durch die Auf/Ab-Buttons oder durch eine vernünftige Tastatur -, ist für die aufrufende Routine egal. Im Fall einer Tastatur würdest du also nur das Eingabeformular neu schreiben.

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

Der RPi wird definitiv niemals eine Tastatur haben. Er wird als Temperatursteuerung sein Dasein fristen, mit der Aussenwelt nur über das Display kommunizierend.
Und ich brauche nicht zu prüfen ob der String wirklich eine Zahl ist - wo in meinem Beispiel sollte ein anderes Zeichen herkommen? Die Labels sind im Objectinspector vorbelegt, und danach haben nur noch die OnClick-Events der Up/Down-Grafiken Einfluss darauf. Und die sind wasserdicht.

Ich kann ja deine generellen Bedenken nachvollziehen, aber ich schreibe meine Programme sehr projektbezogen und nicht universell für alles mögliche anderes verwendbar. Das hält den Code i.A. schmaler und für mich zu späteren Zeiten dann auch schneller wieder nachvollziehbar.
Bin halt kein Profi der damit Geld verdienen muss sondern reiner Hobbyist, der gelegentlich mal ein Projekt zusammendengelt. Und da zählt dann nur das Endergebnis, auch wenn es vielleicht gelegentlich etwas rustikal ausschaut ;).

Trotzdem danke!

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: SENDER an andere Form übermitteln

Beitrag von wp_xyz »

Irgendwann kommt der Tag, da fällt dir ein, dass du ja vor langer Zeit dieses tolle Eingabeformular mit den Auf/Ab-Schaltern geschrieben hast. Bei deiner Lösung musst du dich wieder in das ganze Projekt eindenken, bei meiner kopierst du einfach die Unit. Mit Schummellösungen verschenkt man die Vorteile der objektorientierten Programmierung.

Aber jetzt sage ich nix mehr - deine Entscheidung.

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

:cry: Immerhin habe ich jetzt die Lösung gefunden wie ich sie gerne hätte.

In die Typ-Deklaration von Form1:

Code: Alles auswählen

 
  public
    ausloeser : tobject;
 


Das OnClick-Event der Labels von Form1:

Code: Alles auswählen

 
procedure TForm1.Label1Click(Sender: TObject);
begin
  ausloeser := sender;
  Unit2.Eingabe.label1000er.caption := copy((ausloeser as tlabel).Caption,1,1);
  Unit2.Eingabe.label100er.caption := copy((ausloeser as tlabel).Caption,2,1);
  Unit2.Eingabe.label10er.caption := copy((ausloeser as tlabel).Caption,3,1);
  Unit2.Eingabe.label1er.caption := copy((ausloeser as tlabel).Caption,4,1);
  Unit2.Eingabe.visible := true;
end;   
 


Und das OnClick-Event des 'Übernehmen'-Buttons von der Eingabe-Form:

Code: Alles auswählen

 
  procedure TEingabe.Button1Click(Sender: TObject);
  var rueckgabe : tobject;
  begin
   rueckgabe := form1.ausloeser;
   labeltext := label1000er.caption + label100er.caption + label10er.caption + label1er.caption;
   (rueckgabe as tlabel).caption := labeltext;
   Eingabe.visible := false;
  end;
 


Und schon kann ich auf die zusätzliche Prozedur verzichten, genau so wollte ich das haben. Und du musst zugeben, das ist ein gutes Stück einfacher als bei dir :wink: .
Ein blindes Huhn findet auch mal ein Korn... :mrgreen:



Und um soviel wie möglich in die zweite Form auszulagern:

Code: Alles auswählen

 
//Das reduzierte OnClick der Labels:
procedure TForm1.Label1Click(Sender: TObject);
begin
  ausloeser := sender;
  Unit2.Eingabe.visible := true;
end;   
 
//Im Kopf der Eingabe-Unit:
var
  Eingabe: TEingabe;
  rueckgabe : tobject;
 
//OnActivate-Event der zweiten Form:
procedure TEingabe.FormActivate(Sender: TObject);
begin
 rueckgabe := form1.ausloeser;
 label1000er.caption := copy((rueckgabe as tlabel).Caption,1,1);
 label100er.caption := copy((rueckgabe as tlabel).Caption,2,1);
 label10er.caption := copy((rueckgabe as tlabel).Caption,3,1);
 label1er.caption := copy((rueckgabe as tlabel).Caption,4,1);
end;
 
//Und das OnClick-Event des Buttons wieder wie vor:
procedure TEingabe.Button1Click(Sender: TObject);
 begin
  rueckgabe := form1.ausloeser;
  labeltext := label1000er.caption + label100er.caption + label10er.caption + label1er.caption;
  (rueckgabe as tlabel).caption := labeltext;
  Eingabe.visible := false;
 end;
 


Findet das halbwegs deine Gnade? Im OnActivate könnte man ja nun deine Zahlenmanipulation einfliessen lassen.
Dateianhänge
forum2.zip
(66.23 KiB) 56-mal heruntergeladen

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: SENDER an andere Form übermitteln

Beitrag von wp_xyz »

ppahl hat geschrieben:Findet das halbwegs deine Gnade?

Eigentlich wollte ich mich hier ab jetzt raushalten, aber nachdem du mich direkt fragst: Nein - TForm1 und TEingabe sind immer noch ineinander verwoben, das ist keine Kapselung der Eingabe und außerdem bist du nahe dran an der zirkulären Abhängigkeit von Units, die dein Projekt nicht mehr kompilierbar machen (unit1 uses unit2, und unit2 uses unit1 - geht hier noch, weil beides im Implementation-Abschnitt steht, aber wenn das Projekt größer wird, wirst du den Überblick verlieren, welche Unit wann von welcher anderen Unit gebraucht wird).

Ich kann dein Projekt leider nicht übersetzen (fehlende Dateien), aber ich denke, du kannst die Eingabe kapseln indem du den "Auslöser" zu einer Property des Eingabeformular machst (statt Form1) und in SetAusloeser den String des Labels ins Eingabeformular einliest und in GetAusloeser den eingegebenen String in den Auslöser zurückschreibst. Damit fällt auch das "unit2 uses unit1" weg.

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

Ich kann dein Projekt leider nicht übersetzen (fehlende Dateien)

Uups, da fehlten wahrscheinlich die Grafiken?
Anbei nochmals entsprechend ergänzt.

Was deine weiteren Tips angeht: Sobald ich sie verstanden (*) habe probiere ich es mal aus :mrgreen: .


(*) Ich bewege mich im Gegensatz zu dir auf LowLevel, was dir also selbstverständlich erscheint ist es für mich nicht automatisch :wink:
Dateianhänge
forum3.zip
(67.2 KiB) 57-mal heruntergeladen

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: SENDER an andere Form übermitteln

Beitrag von wp_xyz »

ppahl hat geschrieben:Ich bewege mich im Gegensatz zu dir auf LowLevel, was dir also selbstverständlich erscheint ist es für mich nicht automatisch :wink:

Naja, auf so hohem Niveau fühle ich mich auch wieder nicht. Aber wenn du deine Kenntnisse als LowLevel bezeichnest (was absolut keine Schande ist!), dann ist es um so wichtig, dass dir jemand sagt, wo Fehler liegen. Und das Kapseln von Objekten (also dass sie möglichst wenig von irgendwas anderem abhängen) ist mit ein wesentlicher Grund für den Erfolg der objektorientierten Programmierung.

In meiner beigefügten Variante deines Projekts ist TEingabe autark, es muss nicht mehr TForm1 kennen, um zu funktionieren. Den "Ausloeser" habe ich in "Control" umbenannt (ist unwichtig) und er ist von TControl abgeleitet. Alle Objekte, die von TControl abstammen, haben eine Eigenschaft Caption; daher funtioniert die Eingabe z.B. auch mit einem TEdit oder TStaticText. "Control" alias "Ausloeser" ist nun eine Eigenschaft von TEingabe, nicht mehr von TForm1. Die aufrufende Routine in LabelClick muss nur den Ausloeser auf den Sender setzen, und durch diesen Vorgang wandern wegen der Routine TEingabe.SetControl die Ziffern ins Eingabeformular. Beim Click auf "Übernehmen" wird der eingegebenen Zahlenstring in die Caption von Control zurückgeschrieben.

Was mir noch nicht gefällt, ist, dass du Zahlen eingibst, diese aber als Strings speicherst. Dann hätte sich Pascal all die verschiedenen Zahlendatentypen sparen können! Aber egal, das ist vielleicht Anschauungssache.
Dateianhänge
forum3-wp.zip
(3.9 KiB) 65-mal heruntergeladen

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

Im Ansatz habe ich es gefressen - Danke!

Allerdings hänge ich jetzt wieder an einem neuen Problemchen, wahrscheinlich wieder etwas ganz simples.
Ich prüfe ja die einzelnen Stellen ob sie wirklich eine Zahl sind (noch nicht besonders hübsch, ich weiss...war halt ein schneller Test).
Wenn es keine Zahl ist ersetzt du das Zeichen durch 0 und machst weiter, das ist mir aber zu gefährlich weil dann mit u.U. falschen Werten weitergearbeitet wird.
Ich möchte statt dessen dass ein Hinweisfenster erscheint und danach wieder nur Form1 sichtbar ist.

Code: Alles auswählen

 
 if Zahlentest(label1er.caption) = false then
  begin
   ShowMessage('Nur Zahlenwerte zulässig!');
   self.Close;      // oder auch nur Close; oder .Hide;
  end;
 

...funktioniert aber nicht, Form2 erscheint nach Bestätigung des Hinweises trotzdem.
Da stehe ich mal wieder übel auf der Leitung :oops: .

Mathias
Beiträge: 6143
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SENDER an andere Form übermitteln

Beitrag von Mathias »

Aus diesem Grund wurde dir vom String abgeraten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

(Nicht) sehr hilfreich wenn ich das mal so sagen darf...
Natürlich könnte ich die Prüfung auf einen Zahlenwert wieder in die Form1 zurückverlegen um gar nicht erst in die Bredouille zu kommen. Mich interessiert aber warum ich die Form nicht gleich wieder schliessen kann.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: SENDER an andere Form übermitteln

Beitrag von wp_xyz »

ppahl hat geschrieben:Ich möchte statt dessen dass ein Hinweisfenster erscheint und danach wieder nur Form1 sichtbar ist.

Damit stellst du dir ein Bein: Wenn du bei einer Nicht-Zahl das Eingabeformular ausblendest, hast du nie mehr die Möglichkeit, die Eingabe zu ändern! Daher habe ich die Nicht-Ziffern ignoriert, durch eine '0' ersetzt und eine Warnung ausgegeben.

Falls du meinen Code verwendest, dann kommt nach Eingabe.Control := ... gleich Eingabe.Show - unerbitterlich, ob es einen Fehler gab, oder nicht.

Wenn du beim Auftreten einer Nicht-Ziffer mit Close das Eingabeformular schließen willst (self. ist übrigens unnötig), ist das wirkungslos, weil das Formular noch gar nicht angezeigt ist.

Falls du anderswo in Code auf diese Fehlersituation reagieren willst/kannst, solltest du in TEingabe.SetControl im Fehlerfall eine Fehlervariable setzen und die in FormActivate o.ä. verwenden, um das Form gleich wieder zu schließen. Das muss aber auch das aufrufende Formular mitkriegen, denn dieses muss dann verschwinden, weil aus ihm heraus heraus keine Eingabe für das fehlerhafte Label mehr möglich ist. Ich ahne, dass das alles sehr kompliziert wird. Wenn du an TEingabe nur Integer, keine Strings, übermitteln würdest, gäbe es das Problem nicht...

ppahl
Beiträge: 56
Registriert: Fr 25. Nov 2016, 00:02

Re: SENDER an andere Form übermitteln

Beitrag von ppahl »

Wenn du an TEingabe nur Integer, keine Strings, übermitteln würdest, gäbe es das Problem nicht...

Das ist für mich ja kein Dogma, dann muss ich halt in der Mainform in einen Integerwert umwandeln und die Fehlerprüfung durchführen und das Ergebnis dann ebenda wieder in einen String umwandeln.
Ist halt irgendwie doppelt gemoppelt: Das Caption zunächst in eine Integer umwandeln, an Form2 übergeben, dort die Einzelstellen wieder in Captions zerlegen, das dann wieder in eine Integer umwandeln, die zurück an Form1, und dann wieder ein Caption draus machen.

Mathias
Beiträge: 6143
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SENDER an andere Form übermitteln

Beitrag von Mathias »

Im Prinzip müsstes du deinen Eingabeform gestalten, wie ein Dialog, zB. wie der TOpenDialog.
Da rufst du dann Execute auf und wen diese dann true zurückliefert, ist deine Eingabe mit Ok bestätigt.
http://wiki.lazarus.freepascal.org/Howt ... nDialog/de
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten