Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Prüfen ob Button geklickt
Dude566 - Sa 01.05.10 15:51
Titel: Prüfen ob Button geklickt
Hallo,
also ich bin momentan dabei ein kleines Zeichenprogramm zu entwickeln.
Ich habe ähnlich wie Paint eine Toolbar in der ich Buttons für die jeweiligen Zeichenoperationen habe.
(siehe Anhang)
Nun habe ich für jede Zeichenoperation eine eigene Klasse geschrieben, wenn der Button geklickt wird und im folgenden dann der erste Klick auf der Paintbox getätigt wird, soll überprüft werden welche Zeichenoperation gewählt wurde.
Bisher habe ich es so gelöst:
Wenn der jeweilige Button gewählt wird, wird ein String mit dem Namen des Typen in eine globale Variable "typ" geschrieben.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.btnLineClick(Sender: TObject); begin typ := 'Line'; end;
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if typ = 'Line' then begin MyLine := TLine.Create; MyLine.SetColor(ColorDialog1.Color); MyLine.SetPointP1(x,y); end; end; |
Ich finde das sehr unpraktisch, habt ihr einen Vorschlag für eine bessere Möglichkeit zu überprüfen welche Zeichenoperation gewählt wurde?
Gruß Dude566
Gausi - Sa 01.05.10 16:07
Eine Möglichkeit wäre, bei Klick auf btnLine das OnMouseDown von Paintbox1 zu ändern. Ob das sinnvoller ist, weiß ich aber auch nicht. ;-)
Dude566 - Sa 01.05.10 16:10
Wie meinst du das Verändern? Nenne doch bitte mal ein Beispiel. ;)
elundril - Sa 01.05.10 16:12
Naja, dem MouseDown einfach eine neue Procedure zuweisen.
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.btnLineClick(Sender: TObject); begin PaintBox1.OnMouseDown := LineMouseDown; end; |
lg elundril
Gausi - Sa 01.05.10 16:12
Anhand des Bildes habe ich das Programm mal erweitert, damit klarer wird, was ich meine:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TForm1.btnLineClick(Sender: TObject); begin PaintBox1.OnMouseDown := PaintBox1MouseDownLine; end;
procedure TForm1.btnSquareClick(Sender: TObject); begin PaintBox1.OnMouseDown := PaintBox1MouseDownSquare; end;
procedure TForm1.PaintBox1MouseDownLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MyLine := TLine.Create; MyLine.SetColor(ColorDialog1.Color); MyLine.SetPointP1(x,y); end; procedure TForm1.PaintBox1MouseDownSquare(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MySquare := TSquare.Create; MySquare.SetColor(ColorDialog1.Color); MySquare.SetPointP1(x,y); end; |
Dude566 - Sa 01.05.10 16:16
Habt vielen Dank, werde ich gleich mal ausprobieren. :)
Edit: Ich bekomme eine ungenügende External Forward Deklaration angezeigt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PaintBox1MouseDownLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PaintBox1MouseUpLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure TForm1.btnLineClick(Sender: TObject); begin PaintBox1.OnMouseDown := PaintBox1MouseDownLine; end;
procedure TForm1.PaintBox1MouseDownLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MyLine := TLine.Create; MyLine.SetColor(ColorDialog1.Color); MyLine.SetPointP1(x,y); end;
procedure TForm1.PaintBox1MouseUpLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MyLine.SetPointP2(x,y); try MyLine.Draw(PaintBox1.Canvas); finally MyLine.Free; end; end; |
Liegt ja wohl daran, dass ich keine Implementation für PaintBox1MouseDownLine und PaintBox1MouseUpLine habe, was soll ich tun?
Denn wenn ich eine Leere Implementation der beiden Methoden mache funktioniert es auch nicht, also was sollte darin stehen?
elundril - Sa 01.05.10 17:45
wo hast du die proceduren denn definiert?
lg elundril
Dude566 - So 02.05.10 19:59
Im Implementation Teil. Wo denn auch sonst, deklariert sind sie unter private der Form-Klasse.
MaPsTaR - So 02.05.10 20:22
Bei mir kommt dieser Fehler, wenn ich eine Prozedur zwar im Interface-Teil, aber nicht im Implementation-Teil stehen hab.
-> Fehlerzeile im Compilerfenster anklicken und "F1".
Ich würde vorschlagen, du schaust dir mal die Compiler-Fehlermeldung an, um herauszufinden, welche Prozedure gemeint ist.
Nach dem Code, den du geschickt hast, könnten es
Delphi-Quelltext
1: 2: 3: 4:
| procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); |
sein.
Dude566 - Mo 03.05.10 15:06
Ja es betrifft diese 2 Methoden, und selbst wenn ich beide in den Implementation Teil schreibe tritt der Fehler auf.
Normal sollte diese Meldung ja auftreten wenn ich sie nicht implementiert hätte, was ich aber getan habe, wenn auch ohne Inhalt.
Gausi - Mo 03.05.10 15:16
Und bei der Implementation hast du bei den "leeren" Methoden auch ein TForm1 davor stehen?
Und leere Formular-Methoden werden auch schonmal gerne von der IDE beim compilieren gelöscht. Ein kleiner Kommentar oder ein einzelnes Exit; in der Methode verhindern das. ;-)
Dude566 - Mo 03.05.10 15:23
Also in den letzten Tagen bin ich doch sehr durcheinander, habe tatsächlich den Objektnamen (TForm1) vergessen. :oops:
Problem gelöst!
Martok - Mo 03.05.10 16:54
Problem gelöst, aber nicht unbedingt nach Lehrbuch...
Für die Werkzeugauswahl hat man doch normalerweise eine Menge SpeedButtons, die man zu einer Gruppe zusammenfasst. Dann kann immer nur einer Down sein...
Im Zeichen-Event muss man dann nur noch prüfen, bei welchem denn nun Down gesetzt ist.
Also im Prinzip das Selbe, wie du auch schon gemacht hattest, nur mit "Bordmitteln". Außerdem hat der User so direktes Feedback, was er denn eigentlich für ein Werkzeug nutzt gerade.
Dude566 - Di 04.05.10 17:58
Wie kann ich denn Speedbuttons zu einer Gruppe auf meiner Toolbar einrichten? Ich habe gerade mal zum Test einfach 2 auf die Toolbar gezogen, aber wenn ich einen anklicke wird er nicht "eingedrückt".
Wie stelle ich das an? Das wäre natürlich eine bessere Lösung denn so sieht der Benutzer auch gleich welche Zeichenoperation aktiviert ist.
SvenAbeln - Di 04.05.10 18:41
Schau dir mal die Property GroupIndex an.
Dude566 - Di 04.05.10 18:50
Okay das klappt, allerdings können auch mehrere ausgewählt werden (gedrückt).
SvenAbeln - Di 04.05.10 18:58
Wenn Buttons den selben GroupIndex haben, kann immer nur einer davon ausgewählt sein.
jaenicke - Mi 05.05.10 12:36
Wie wäre es denn mit OOP zu arbeiten für den Zweck?
Einfach eine Elternklasse und für jede Zeichenoperation eine abgeleitete Klasse. Dann muss beim Umschalten der Zeichenoperation nur (z.B. über eine Factory-Klasse) die passende Zeichenklasse erzeugt werden.
Dude566 - Mi 05.05.10 15:32
Was du jetzt im genauen mit "über eine Factory-Klasse" meinst ist mir nicht klar, ich habe doch für jede Zeichenoperation eine Klasse.
Alle diese Klassen sind von einer Klasse TGrafix abgeleitet, in der die Punkte etc enthalten sind.
Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| type TJNGrafix = class(TObject) private FColor : TColor; FPen : byte; p1, p2 : TPoint; public procedure SetColor (AFarbe : TColor); procedure SetPointP1 (x, y : integer); procedure SetPointP2 (x, y : integer); procedure SetPen (AWidth : byte); end;
type TLine = class(TJNGrafix) private public procedure Draw (ACanvas : TCanvas); end; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| procedure TLine.Draw(ACanvas: TCanvas); begin ACanvas.Pen.Color := FColor; ACanvas.Pen.Width := FPen; ACanvas.MoveTo(p1.X, p1.Y); ACanvas.LineTo(p2.X, p2.Y); end;
procedure TForm1.PaintBox1MouseDownLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MyLine := TLine.Create; MyLine.SetColor(ColorDialog1.Color); MyLine.SetPen(12); MyLine.SetPointP1(X,Y); end;
procedure TForm1.PaintBox1MouseUpLine(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MyLine.SetPointP2(X,Y); try MyLine.Draw(PaintBox1.Canvas); finally MyLine.Free; end; end; |
Bin noch nicht so ganz fit in Sachen OOP.
jaenicke - Mi 05.05.10 20:06
Dann ist es doch sehr sehr einfach: ;-)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| TForm1 = class(TForm) private FPaintOperation: TJNGrafix; end;
FPaintOperation := TLinePainter.Create; FPaintOperation := TRectPainter.Create;
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FPaintOperation.SetColor(ColorDialog1.Color); FPaintOperation.SetPen(12); FPaintOperation.SetPointP1(X,Y); end;
procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FPaintOperation.SetPointP2(X,Y); FPaintOperation.Draw(PaintBox1.Canvas); end; |
So musst du das Objekt nicht ständig neu erzeugen (sondern nur bei Auswahl einer anderen Form).
Und so nebenbei: Benenne deine Komponenten ordentlich... ;-)
Dude566 - Do 06.05.10 18:03
Also einfach je nach Wahl der Form meiner Instanz der Hauptklasse eine der Unterklassen zuweisen.
Was meinst du mit ordentlich benennen? Ich dachte ich hätte sie schon ordentlich benannt.
jaenicke - Fr 07.05.10 04:44
Dude566 hat folgendes geschrieben : |
Also einfach je nach Wahl der Form meiner Instanz der Hauptklasse eine der Unterklassen zuweisen. |
Richtig, das spart dir viel Aufwand und redundanten Code.
Dude566 hat folgendes geschrieben : |
Was meinst du mit ordentlich benennen? Ich dachte ich hätte sie schon ordentlich benannt. |
Ja, ich sehe schon, dass du die Buttons benannt hast. Mir waren jetzt Form1 und PaintBox1 aufgefallen. ;-)
Dude566 - Fr 07.05.10 18:04
Ja da mache ich mir nicht die Arbeit die umzubenennen wenn die nur einmal vorkommen und es zu keiner Verwechslung kommen kann.
Dude566 - Fr 07.05.10 18:48
Nein, das kannte ich bisher nicht.
Das nenne ich mal ein nützliches Tool, danke
jaenicke! :zustimm:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!