Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Button in eine Gaugecomponente einfügen?
ALF - Di 19.10.10 15:47
Titel: Button in eine Gaugecomponente einfügen?
Hi,
Wie der Titel schon sagt, überlege ich gerade ob man Buttons in eine Gaugecomponente einfügen kann?
Zusätzlichen Text (nicht den StandartCaption)und dessen Positionierung habe ich ja schon geschaft. Aber 1 oder 2 Buttons, incl ihrer Propertys und Eigenschaften?
Wüsste also nicht mal ansatzweise wie, wenn es überhaupt geht?
Gruss Alf
jaenicke - Di 19.10.10 20:34
Ich weiß nicht, ob TGauge ein Handle hat, so dass du darüber den Parent des Buttons darauf setzen kannst.
Ansonsten: Schreibe doch einfach die komplette Gauge selbst. Viel ist das ja nicht, jedenfalls solange du nur einfache Formen haben möchtest (ich weiß nicht was TGauge so alles macht).
// EDIT:
Naja, also das was TGauge kann lässt sich recht schnell selber schreiben und dann kannst du einfach einen Button reintun.
ALF - Di 19.10.10 21:26
jaenicke hat folgendes geschrieben : |
......und dann kannst du einfach einen Button reintun. |
Naja ich habe ja ne externe Komponente, abgeleitet von TGauge, wie ich da aber
einfach nen Button reinbringen soll mit all seinen Möglichkeiten?
Es ist eine Unit die ich im Netz gefunden habe. Meine versuche schlagen da ja irgend wie fehl!
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:
| unit GaugeCaption;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, StdCtrls, Gauges, StrUtils;
type TTemperature= (tNormal, tDegradado, tTemperatura); TPosicion= (poIzquierda, poDerecha); TGaugeKind = (gkText, gkHorizontalBar, gkVerticalBar, gkPie, gkNeedle);
TGaugeCaption = class(TGauge) private
FMinValue: Longint; FMaxValue: Longint; FCurValue: Longint; FKind: TGaugeKind; FShowText: Boolean; FBorderStyle: TBorderStyle; FBorderWidth: TBorderWidth;
FButton1: TButton; FButton2: TButton; |
Hab noch nicht mal in irgend einer weise nen Ansatz dafür. Oder das geht vielleicht gar nicht und ich muss mir ne eigene schreiben, wo ich die beiden TGaugeCaption und TButton irgend wie zusammen bekomme!?
Gruss Alf
jaenicke - Di 19.10.10 21:56
Die Eigenschaften sind im Button ja drin. Wenn du eine property unter published erstellst, steht die auch im Objektinspektor. Im Konstruktur müsstest du dann auch die Buttons mit erzeugen und auf die Komponente setzen.
Ich habe aber mittlerweile gesehen, dass ein TGauge gar kein Handle hat. Also kannst du da AFAIK auch keine Komponenten draufsetzen.
Deshalb denke ich einmal selber gleich alles machen geht am einfachsten.
ALF - Di 19.10.10 22:08
jaenicke hat folgendes geschrieben : |
Deshalb denke ich einmal selber gleich alles machen geht am einfachsten. |
Jo hab ich befürchtet :( Nur wie bekomme ich beides zusammen?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| unit ButtonGauge;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, StdCtrls, Gauges, StrUtils;
TButtonGauge = class(??????) |
Wovon soll ich das nun ableiten? Da fehlt leider die Erfahrung :oops:
Gruss ALf
FinnO - Di 19.10.10 22:14
Moin,
TGraphicWinControl hat AFAIK ein Canvas, das könnte schonmal hilfreich sein. Ansonsten gibt es für sowas den Komponentenwizard!
ALF - Di 19.10.10 22:50
mh... ne einzelne Komponente zu erstellen trau ich mir ja noch zu, aber ne Komponente die beides beinhaltet?
Dazu mal ein Bild im Anhang, wie ich es meine.
FinnO hat folgendes geschrieben : |
Ansonsten gibt es für sowas den Komponentenwizard! |
jo, aber deswegen weiss ich nicht wie ich 2 unterschiedlich Komponenten in einer vereinen kann? Mir fehlt leider jeglicher Ansatz dafür!
Gruss Alf
FinnO - Di 19.10.10 23:07
Moin,
na ja, ich vermute mal, dass die Eigenschaften Top und Left eines Buttons sich auf sein parent beziehen. Und wenn du den Button dann als Property deiner Komponente hast und den im Constructor deiner Komponente das Handle ebendieser als Parent festlegst, könnte das etwas werden. Aber gemacht hab ich das auch noch nie, jaenicke hat da auch mit Sicherheit mehr Überblick.
LG
bummi - Di 19.10.10 23:39
Du könntest von TCustomPanel ableiten...
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| TMyGauge = class(TCustomPanel) private .... protected procedure Paint(var Message: TWMPaint); Message WM_PAINT; .... |
hier im Contructor deine Buttons erzeugen, die Getter/Setter/Events durchschleifen
und im Paint malen
ALF - Mi 20.10.10 01:31
Naja, so richtig schnall ich das nicht wie ich eine 2te Komponente einbinden soll, unabhängig davon, ob ich es versuche in meiner TGaugeCaption zumachen, geschweige, wie ich es machen soll wenn ich 2 komponenten zusammen bringen soll. Bin einfach zu blöd.
Ich hab zwar versucht zu verstehen was Ihr mir geschrieben habt, aber ....
Gruss ALf
jaenicke - Mi 20.10.10 06:09
Ich schreib dir ne kleine Demo... Aber dazu komme ich erst nach der Arbeit heute Abend. ;-)
Wegen der Elternkomponente: Da du ein Fensterhandle brauchst um andere Komponenten mit SetParent auf deine Komponente zu pflanzen bietet es sich an von TCustomControl abzuleiten.
Von Nachfahren wie TCustomPanel abzuleiten ist weniger sinnvoll, da du deren Funktionalität wahrscheinlich gar nicht brauchst. Man sollte immer die höchste Komponente in der Hierarchie wählen, die alles hat was man braucht.
Und TGraphicControl ist für eigene Komponenten, die kein eigenes Fensterhandle brauchen.
Xion - Mi 20.10.10 10:22
Ich mach sowas immer anders. In etwa so:
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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| type TOnBtnClickEvent= procedure (GaugeMax, GaugeMin, GaugePos: integer) of object;
type TGaugeButton=class private Btn: TButton; Gauge: TGauge;
VOnBtnClick: TOnBtnClickEvent; VLeft: integer;
procedure SetLeft (v: integer);
procedure InternalOnBtnClick(Sender: TObject); public constructor Create( Owner: TWinControl); property Left: integer read VLeft write SetLeft; property OnBtnClick: TOnBtnClickEvent read VOnBtnClick write VOnBtnClick; end;
...
constructor TGaugeButton.Create (Owner: TWinControl); begin Gauge:=TGauge.Create(Owner); Gauge.Parent:=Owner;
Btn:=TButton.Create(Owner; Btn.Parent:=Owner; Btn.OnClick:=InternalOnBtnClick;
end;
procedure TGaugeButton.InternalOnBtnClick(Sender: TObject); begin if Assigned(OnBtnClick) then VOnBtnClick( Gauge.Min, Gauge.Max, Gauge.Pos); end;
procedure TGaugeButton.SetLeft (v: integer); begin Gauge.Left:=v; Btn.Left:=v+5; end; |
Zum verwenden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| GBtn: TGaugeButton; begin GBtn:= TGaugeButton.Create(Form1); GBtn.Left:=100; GBtn.OnBtnClick := OnGaugeBtnClick; end;
procedure TForm1.OnGaugeBtnClick(GaugeMax, GaugeMin, GaugePos: integer); begin ShowMessage('Gauge filled at '+floattostr( (GaugeMax-GaugeMin)/(GaugePos-GaugeMin)*100 )+'%'); end; |
Bin mehr ein Fan von Delegation anstatt von Vererbung.
Wenn du jetzt den Button direkt ansprechen willst, dann würde ich ihn public machen. Wenn du ihn dann von Hand verschiebst, bist du selbst Schuld :P
jaenicke - Mi 20.10.10 11:39
Naja, aber ich denke mal die bessere Lösung ist schon eine eigene echte Komponente. Delegation ist schön und gut, aber auch nur dann, wenn es dazu passt. Aber hier...
ALF - Mi 20.10.10 16:47
Hi, es ist ja nicht so, das ich nun von euch erwarte das Ihr mir den code liefert :wink:
Bin natürlich selbst schon dabei was zu machen, geht aber halt langsam vorran. Mal sehen ob ichs packe!?
Achso, ich vergass zu erwähnen, das ich die Komponente die ich aus dem Inet habe einbinden möchte, also nicht die TGauge von Delhpi. Diese hat auch ein onClickereignis und noch ander dabei. So als Randbemerkung
Gruss ALf
Xion - Mi 20.10.10 22:02
ALF hat folgendes geschrieben : |
Hi, es ist ja nicht so, das ich nun von euch erwarte das Ihr mir den code liefert :wink: |
Das hat ja auch keiner behauptet ;) Ich hab dir nur als Konzept gezeigt, wie ich sowas machen würde. Aber ich bin mal gespannt wie
jaenicke das vor hat, vielleicht find ich Vererbung dann doch endlich mal ganz nett :mrgreen: Wie es aber ohne Delegation und ohne Mehrfachvererbung gehen soll ist mir ehrlich gesagt ein Rätsel, aber ich bin ja lernfähig :D
jaenicke - Mi 20.10.10 22:04
Xion hat folgendes geschrieben : |
Wie es aber ohne Delegation und ohne Mehrfachvererbung gehen soll ist mir ehrlich gesagt ein Rätsel |
Ich habe nicht gesagt ganz ohne Delegation. ;-)
Ja, ich mach mich gleich dran.
ALF - Mi 20.10.10 22:18
jo, ich hab nun auch schon was versucht, natürlich zwecklos. Hab zwar ne neue Komponente die keine Fehler mehr wirft, aber keine Buttons zu sehen. Klar, ohne Grundlage wie sowas funct kann es nur nach hinten losgehen :? :cry:
Edit:
Hab mal den Vorschlag von
Xion umgesetzt. Ist ja toll 8) , währe jetzt nur schön, wenn ich die neue Komponente auch so auf die Form legen könnte. Aber ich code erst mal an das weiter :wink:
Gruss Alf
jaenicke - Do 21.10.10 06:05
So, bin gestern eingeschlafen, habs aber gerade eben schnell gemacht, siehe Anhang.
bummi - Do 21.10.10 08:05
Wahrscheinlich wird die Info wie Clicks durchzuschleifen sind auch noch benötigt, einer der Wege liegt bei (davon ausgehend daß man onKlick intern auch was tun möchte):
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: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| .... property Position: Integer read FPosition write SetPosition; Property OnButtonClick:TnotifyEvent read FButtonClick write FButtonClick; end;
TForm259 = class(TForm) TrackBar1: TTrackBar; procedure TrackBar1Change(Sender: TObject); procedure FormCreate(Sender: TObject); private FMyGauge: TMyGauge; public end;
var Form259: TForm259;
implementation
{$R *.dfm}
Procedure TMyGauge.InternalClick(Sender:TObject); begin if Assigned(FButtonClick) then FButtonClick(Sender); end;
constructor TMyGauge.Create(AOwner: TComponent); begin inherited; DoubleBuffered := True; FButton := TButton.Create(Self); FButton.OnClick := InternalClick; FButton.Left := 10; .... |
Xion - Do 21.10.10 19:38
Sorry, aber das überzeugt mich nicht ;)
Das kann man weder von Hand auf der Form platzieren (ok, anderes Kapitel), noch kann ich den Button direkt ansprechen. Das einzige ist, dass du deine TGauge nochmals implementierst (im .Paint z.B.), was man ja aus OOP Sicht nun eben nicht braucht (ok, es sieht hübscher aus ;) ).
Was genau ist hier der Vorteil gegenüber meinem? Weil dass ich die Gauge nochmal programmieren muss, find ich deutlich als Nachteil. Nach diesem Schema müsste ich ja auch in allen meinen Klassen (Btn+Gauge, Edit+Gauge, Label+Gauge) immer die Gauge neu schreiben und abändern.
Was ich überhaupt *mist*e find ist, dass ich die ganzen Funktionen nach außen ziehen muss. Hmm, vielleicht wäre es am besten, die Klasse von TButton abzuleiten. Ja, ich glaub das wäre eine gute Idee bei der sogar ich Vererbung nutzen würde :mrgreen:
...außerdem flackert der Button trotz DoubleBuffered:=True...komisch.
Edit:
Vererbung von TButton
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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| type TGaugeBtn = class(TButton) private Gauge: TGauge; procedure SetPosition(V: integer); function GetPosition: integer; constructor Create( Owner: TWinControl ); destructor Destroy; public property Position: integer read GetPosition write SetPosition; end;
constructor TGaugeBtn.Create( Owner: TWinControl ); begin inherited Create(Owner);
Gauge:=TGauge.Create(Owner); Gauge.Left:=Self.Left; Gauge.Top:=Self.Top+Self.Height; Gauge.Width:=Self.Width; Gauge.Height:=Self.Height; Gauge.Parent:=Owner; end;
destructor TGaugeBtn.Destroy; begin Gauge.Free; Gauge:=nil;
inherited Destroy; end;
procedure TGaugeBtn.SetPosition(V: integer); begin Gauge.Progress:=V; end;
function TGaugeBtn.GetPosition:integer; begin Result:=Gauge.Progress; end; |
Edit:
Getestet und für gut befunden. Wie man das jetzt in den OI kriegt...vermutlich nicht so ohne weiteres (die Komponente muss sich dann irgendwo im Delphi registrieren).
Damit die Klasse gut funktioniert, muss man natürlich bei Left/Top... Veränderungen noch die entsprechenden Funktionen überschreiben um die Gauge mitzubewegen.
Xion - Do 21.10.10 20:01
Funktion zum Packen in den Objektinspektor:
ACHTUNG: Vorher informieren, was das bewirkt *keine Ahnung von hat*
//Edit: verdammter LoadBalancer...haut mich raus während ich im inline-Editor wurstel. Deswegen der Doppelpost (war wohl mein Fehler nach dem Durcheinander)
jaenicke - Do 21.10.10 20:10
Xion hat folgendes geschrieben : |
ACHTUNG: Vorher informieren, was das bewirkt *keine Ahnung von hat* |
Das gehört in die Prozedur Register. Die wird beim Laden des Packages dann ausgeführt. Und da ich die Eigenschaften published gemacht habe, sind die dann auch im OI sichtbar.
Allerdings halte ich davon nicht so viel, deshalb habe ich es nicht hinzugefügt. Ich finde es sehr viel einfacher neue Komponenten einfach manuell zu erstellen. Dann kann jeder das Projekt einfach laden und kompilieren.
Ich hasse es, wenn ich für ein Projekt erst eine halbe Stunde Komponenten installieren darf... :roll:
Jakob_Ullmann - Do 21.10.10 20:10
Xion hat folgendes geschrieben : |
ACHTUNG: Vorher informieren, was das bewirkt *keine Ahnung von hat* |
Das sollte der Komponentenwizard eig. automatisch erzeugen. Zumindest war das bei Delphi 7 so. Und das hat was mit der Palette, nicht mit dem OI zu tun. Was da rein soll, musst doch in published als property deklarieren.
Xion - Do 21.10.10 20:19
jaenicke hat folgendes geschrieben : |
Ich hasse es, wenn ich für ein Projekt erst eine halbe Stunde Komponenten installieren darf... :roll: |
Absolut auch meine Meinung...nur
ALF wollte wissen wie es geht ;)
Jakob_Ullmann hat folgendes geschrieben : |
Und das hat was mit der Palette, nicht mit dem OI zu tun. Was da rein soll, musst doch in published als property deklarieren. |
Das ist natürlich richtig, hatte mit Objekt Inspektor zusätzlich die Palette gemeint :oops:
ALF - Fr 22.10.10 19:55
Ich melde mich mal kurz, das ich noch am Ball bin. Leider bin ich beruflich stark gebunden und kann alle eure Info und Meinungen noch nicht in Ruhe abarbeiten.
Richtig ist, es geht mir nur darum ob es möglich ist, eine neue Komponente zu erstellen die zwei unterschiedliche Komponenten beeinhaltet und dabei all ihre flexibilität behalten.
Habt ihr mir ja schon aufgezeigt :wink:
Leider bin ich ein Typ, der es lieber so hat, das man die neue Komponente auf die Form packen kann, um sie sich anzuschauen, dan zu sehen was ich alles mit ihr machen kann bzw was mir der OI alles für Möglichkeiten bietet.(Also sie dynamisch zu erstellen um sie dann dynamisch einzubinden ist nicht so mein ding) Dabei geht es mir auch nicht darum eine Komponente zu regestrieren, sondern sie in die Pallete mit aufzunehmen.(Wie das funktioniert ist ja bekannt) :wink:
Habt also Nachsicht, das ich noch keine Rückmeldung, wie weit ich mit euren Hinweisen gekommen bin abgeben kann.
Fragen meinerseit, werden auf alle Fälle folgen :mrgreen:
Gruss ALf
ALF - Mo 25.10.10 15:00
So nun habe ich meine Komponenete mal erstellt.
Buttons sind drauf, lassen sich in grösse verändern, Caption kann geschrieben werden, Font kann extra eingestellt werden!(Leider wird die Font Änderung nicht automatisch aktuallisiert sondern erst beim Schreiben von Caption bzw wenn sich an der Gauge was ändert) :cry:
Was nun wichtig währe, ist das Oncklickereignis von den Buttons. Mein Versuch:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Btn1.OnClick:= SetBtnClick; Btn2.OnClick:= SetBtnClick; .... .... procedure TGaugeButton.SetBtnClick(Sender: TObject); begin FBtnClick:= TButton(Sender).Name; end; |
es in etwa so umzusetzen, .... naja nix sag dazu.
Ich gehe mal davon aus was
jaenicke gesagt hat, ohne Handle keine Antwort, trifft in diesem Fall zu und ich kann es also so nicht umsetzen :cry:
Was natürlich das einfachste währe. Es sei, es hat noch jemand eine Idee!!
Gruss ALf
Xion - Mo 25.10.10 15:29
ALF hat folgendes geschrieben : |
Leider wird die Font Änderung nicht automatisch aktuallisiert sondern erst beim Schreiben von Caption bzw wenn sich an der Gauge was ändert :cry: |
Das kannst du aber von Hand machen im SetFont().
ALF hat folgendes geschrieben : |
Ich gehe mal davon aus was jaenicke gesagt hat, ohne Handle keine Antwort, trifft in diesem Fall zu und ich kann es also so nicht umsetzen :cry:
|
Das ist deine Komponente, hier bist du Gott! "Alles" geht.
ALF hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TGaugeButton.SetBtnClick(Sender: TObject); begin FBtnClick:= TButton(Sender).Name; end; |
|
Und mit "Alles" meine ich nicht, einem Event einen String zuweisen :P
Ich versteh nicht so ganz was du willst. Ich rate mal:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TGaugeButton.SetBtnClick(Sender: TObject); begin if Assigned(FBtnClick) then FBtnClick( Sender ); end; |
So wird der Button nach außen gereicht. DORT kannst du dann TButton(Sender).Name abfragen.
Die noble Variante ist die:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TWelcherButtonWurdeGeklickt = (bcButton1WurdeGeklickt ,bcButton2WurdeGeklickt, bcBugInKomponente ); procedure TGaugeButton.SetBtnClick(Sender: TObject); begin if Assigned(FBtnClick) then begin if Btn1=Sender then FBtnClick( bcButton1WurdeGeklickt ) else if Btn2=Sender then FBtnClick( bcButton2WurdeGeklickt ) else FBtnClick( bcBugInKomponente) end; end; |
Der Übergabeparameter von FBtnClick muss natürlich dann vom Typ TWelcherButtonWurdeGeklickt sein!
jaenicke - Mo 25.10.10 15:31
Du kannst auch einfach eine Property einführen OnButton1Click oder so, deren Setter dann die Property bei Button1 setzt und deren Getter die wieder dort ausliest. ;-)
ALF - Mo 25.10.10 16:58
mh.. der erste Vorschlag will nicht funcen. Irgenwas mache ich Falsch
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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| unit GaugeButton;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, StdCtrls, StrUtils, Gauges;
type TGaugeKind = (gkHorizontalBar, gkVerticalBar); TGaugeButton = class(TCustomControl)
private FBtnClick: TObject; .... .... protected .... public .... procedure SetBtnClick(Sender: TObject); published ... end;
implementation
.... ....
constructor TGaugeButton.Create (AOwner: TComponent); begin inherited Create(AOwner); ... ... FBtnFont:= TFont.Create; Btn1:= TButton.Create(Self); Btn1.Parent:= Self; Btn1.Name:= 'Btn1'; Btn1.OnClick:= SetBtnClick; Btn1.Font:= FBtnFont; .... .... end;
procedure TGaugeButton.SetBtnClick(Sender: TObject); begin if Assigned(FBtnClick) then FBtnClick:= (Sender);
end; |
ich sehe zwar zur Laufzeit SetBtnClick aber auslesen wie oben gezeigt ????
Die anderen Vorschläge sind auch nicht ohne :wink: aber wenn ich das eine nicht mal packe, wie soll es bei den anderen gehen :gruebel:
Gruss ALf
jaenicke - Mo 25.10.10 17:21
Ich schreibe gleich zu Hause ein Beispiel dazu...
ALF - Mo 25.10.10 17:33
neeeee!!! alles zurück Ein grosser Denkfehler von mir
Die einzelnen buttons müssen zur Laufzeit so erkannt werden z.B.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| TForm1.GaugeButton1Click(Sender: TObjekt); begin If TGaugeButton(Sender).Name = 'ButtonGauge1' then begin if FBtnClick = ??? then else end else If TGaugeButton(Sender).Name = 'ButtonGauge2' then begin if FBtnClick = ??? then else end
end; |
Alles ander hätte ja keinen Sinn und müsste sehr kompliziert ausgelesenen und verglichen werden!
Da ich ja wissen muss
von welcher Gauge der zusätzlich Button geklickt wurde.
Gruss ALf
Xion - Mo 25.10.10 18:02
Du machst das irgendwie komisch...FBtnClick ist ja ein TObject :shock:
Wie genau kommst du denn in deinem Code in Form1 an FBtnClick?? Ist das ne globale Variable?
Guck dir am besten nochmal das Beispiel von Seite 1 von mir an:
Xion hat folgendes geschrieben : |
Delphi-Quelltext 1:
| type TOnBtnClickEvent= procedure (GaugeMax, GaugeMin, GaugePos: integer) of object; | |
Dort kannst du natürlich statt GaugeMax usw. auch den Button angeben (als Nummer oder Boolean oder wie oben mit TWelcherButtonWurdeGeklickt )
ALF - Mo 25.10.10 18:25
Irgendwie will das alles nicht.
Ich muss doch die zusätzlichen Button, in diesem Fall Btn1 + Btn2 ihr Oncklickergeignis neu zuweisen. Inerhalb meiner neuen Komponente. Die Komponente befindet sich in der Delphi Palette!
Mit dieser Zuweisung muss aber auch zur Laufzeit gearbeitet werden. Das heist, klick ich Btn1 an, muss ich als Rückmeldung die Info abfragen können aus welcher Gauge welcher zusätzliche Button geklickt wurde.
Ich bekomme aber nicht mal ne Info, ob der extra Button überhaupt geklickt wurde :gruebel:
FBtnClick ist ein Fehler, soll setBtnClick sein.
Edit: Habs geschafft :dance:
Ist vielleicht nicht die beste Lösung aber sie funct
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| public property BtnClick: String read FBtnClick;
procedure TGaugeButton.SetBtnClick(Sender: TObject); begin if TButton(sender).Name = 'Btn1' then FBtnClick:= 'Btn1' else FBtnClick:= 'Btn2';
onclick(self); end; |
Thx an alle für die Ausdauer mit mir
Gruss ALf
Xion - Mo 25.10.10 22:40
Xions Lösung Deluxe
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: 33: 34: 35: 36: 37:
| type TButtonClicked = (btButton1, btButton2);
type TGaugeButtonClickEvent=procedure (Sender: TObject; Clicked: TButtonClicked) of object;
type TGaugeButton=class private VOnButtonClick : TGaugeButtonClickEvent; procedure ButtonClick(Sender: TObject); public property OnButtonClick: TGaugeButtonClickEvent read VOnButtonClick write VOnButtonCLick; end;
constructor TGaugeButton.Create(...); begin Btn1.OnClick:=ButtonClick; Btn2.OnClick:=ButtonClick; end;
procedure TGaugeButton.ButtonClick (Sender: TObject); begin if Assigned( VOnButtonClick) then begin if Sender=Btn1 then VOnButtonClick( Self, btButton1 ) else if Sender=Btn2 then VOnButtonClick( Self, btButton2 ); end; end;
|
Benutzung
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:
| type TForm1=class procedure GaugeButtonClick( Sender: TObject; Clicked: TButtonClicked);
GaugeButton1.OnButtonClick:= GaugeButtonClick; GaugeButton2.OnButtonClick:= GaugeButtonClick;
procedure TForm1.GaugeButtonClick (Sender: TObject; Clicked: TButtonClicked); begin if Sender = GaugeButton1 then begin if Clicked=btButton1 then ShowMessage('Gauge1 - Button1 clicked') else if Clicked=btButton2 then ShowMessage('Gauge1 - Button2 clicked'); end else if Sender = GaugeButton2 then begin if Clicked=btButton1 then ShowMessage('Gauge2 - Button1 clicked') else if Clicked=btButton2 then ShowMessage('Gauge2 - Button2 clicked'); end; end; |
ALF - Mo 25.10.10 23:09
Jo, schau ich mir an!
Gibt aber dennoch ein Problem bei meiner Variante :autsch:
Vielleicht auch bei euren, weiss ich noch nicht!
Klicke ich nun einen extra Button, wird die Variable BtnClick gesetzt und das onclick von der Gauge wird aufgrufen.
Wenn ich nur auf die Gauge klicke, bleibt die Variable BtnClick bestehen, sie muss aber dann leer sein!!
Wie nun, daran hab ich nicht gedacht :autsch: was wie nun :cry:
EDIT:
@Xion, hab ich übernommen ist natürlich sauberer als meins, aber.... ganau das gleiche Problem, wenn ich nun nur auf die Gauge klicke, muss ich also das OnClick auch noch aufrufen!
Gruss ALf
jaenicke - Di 26.10.10 05:28
ALF hat folgendes geschrieben : |
@Xion, hab ich übernommen ist natürlich sauberer als meins, aber.... ganau das gleiche Problem, wenn ich nun nur auf die Gauge klicke, muss ich also das OnClick auch noch aufrufen |
Ja, wenn du das willst, klar. Geht ja genauso.
Xion - Di 26.10.10 08:15
ALF hat folgendes geschrieben : |
Klicke ich nun einen extra Button, wird die Variable BtnClick gesetzt und das onclick von der Gauge wird aufgrufen.
Wenn ich nur auf die Gauge klicke, bleibt die Variable BtnClick bestehen, sie muss aber dann leer sein!! |
Auch wenn mir diese Vorgehensweise seltsam vorkommt: Du könntest ja BtnClick nach dem Aufruf des Events ( onclick(self) ) wieder auf nil setzen.
ALF hat folgendes geschrieben : |
EDIT:
@Xion, hab ich übernommen ist natürlich sauberer als meins, aber.... ganau das gleiche Problem, wenn ich nun nur auf die Gauge klicke, muss ich also das OnClick auch noch aufrufen! |
Du weißt einfach Gauge.OnClick das gleiche Event zu und machst dann noch ein if, bei welchem du dann den letzten Parameter z.B. auf btGauge setzt. Alternativ kannst du auch für die Gauge auch ein ganz andres Event machen, welches andere Übergabeparameter hat.
ALF - Di 26.10.10 16:45
Ok, ich hab mir mal erlaubt meine Variante einzusetzen, sagen wir mal so, bin zufrieden :wink:
Ob mann es nun so simpel machen kann, mhhh..., oder doch lieber Profesionel entzieht sich mir, da ja beides funct.
Es sei den, bei mir befinden sich unsauberer Code, der evtl das Prog oder Systhem stört oder anderes?
Hab mal nen kleines Demo und die GaugeButton.pas zum anschauen angehängt. Sollte ich da wirklich schlecht gecodet haben(GaugeButton.pas), dann werd ich selbstverständlich das abändern :mrgreen:
Anbei: Der grösste Teil kommt von der original Gauge.pas aus Delphi
Ne Info, ob ich es so lassen kann, währe nicht schlecht.
Gruss ALf
Xion - Di 26.10.10 17:23
Also nach 15min rumwursteln läufts jetzt erstmal ;) Ich habs ja nicht installiert, musste also erst die dfm lesen und...
1. Funktioniert: ja (scheint zumindest so)
2. Wie ich schon sagte finde ich es sinnlos die Gauge (inbesondre das .Paint) neu zu programmieren...stattdessen von TGauge erben oder Gauge delegieren (d.h. als Instanz wie analog zu den Buttons).
3. Die BtnClick-property find ich immernoch...ungewöhnlich ;) Die damit verbundenen Stringvergleiche find ich aber unschön, weil die CaseSensitive sind, was heißt, du schreibst if 'btn1' ... else ... Dabei ist der ButtonName aber 'Btn1'. Passiert sehr schnell mal und man findet den Fehler nicht.
Edit:
Du hättest die "Danke" ja auch an Postings von uns machen können, die besonders konstruktiv waren :mrgreen: Besonders den Einzeiler von
jaenicke find ich da irgendwie...amüsant. :P Aber Danke fürs Danke :nut:
ALF - Di 26.10.10 22:42
Xion hat folgendes geschrieben : |
2. Wie ich schon sagte finde ich es sinnlos die Gauge (inbesondre das .Paint) neu zu programmieren...stattdessen von TGauge erben oder Gauge delegieren (d.h. als Instanz wie analog zu den Buttons). |
Ja und nein. Ich finds so schöner und, ich weiss was ich gemacht habe! (lerneffekt für mich, so selten wie ich was Code)
Xion hat folgendes geschrieben : |
3. Die BtnClick-property find ich immernoch...ungewöhnlich ;) |
Weil man es so nicht macht oder weil es zu simple ist???
Xion hat folgendes geschrieben : |
Die damit verbundenen Stringvergleiche find ich aber unschön, weil die CaseSensitive sind, was heißt, du schreibst if 'btn1' ... else ... Dabei ist der ButtonName aber 'Btn1'. Passiert sehr schnell mal und man findet den Fehler nicht. |
Worauf soll ich aber sonst vergleichen, als auf den Komponenten.Name, den der ist nun mal einmalig. Ich weiss, der vergleich auf 'Btn1' kann immer mal daneben gehn 'btn1'! Solange man btn1 nicht noch mal für was anderes definiert :wink: Aber das sollte jeder Coder wissen! Sonst wüsst ich keine Alternative dazu!
Gruss ALf
ps gab noch danke extra
jaenicke - Di 26.10.10 22:46
Du kannst einfach die Variablen vergleichen.
Delphi-Quelltext
1: 2:
| if Sender = Button1 then ... |
ALF hat folgendes geschrieben : |
Weil man es so nicht macht oder weil es zu simple ist??? |
Weil es unnötig umständlich ist. Statt dass du den Wert direkt im Event übergeben bekommst, musst du ihn extra aus der Komponente auslesen...
ALF - Mi 27.10.10 18:13
jaenicke hat folgendes geschrieben : |
Du kannst einfach die Variablen vergleichen. |
Jo, oft genug gesehen, schon gemacht, wieder vergessen :oops:
jaenicke hat folgendes geschrieben : |
ALF hat folgendes geschrieben : | Weil man es so nicht macht oder weil es zu simple ist??? | Weil es unnötig umständlich ist. Statt dass du den Wert direkt im Event übergeben bekommst, musst du ihn extra aus der Komponente auslesen... |
Zu sowas, werd ich mal einen
extra Thread aufmachen, weil nicht schlüssig die Antwort. Bleiben viele Fragen meinerseits offen!
Ansonsten hab ich
Xion delüx Vorschlag umgesetzt mit einer zusätzlichen Variablen!
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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| type TBtnClicked = (bcNoBtn, bcBtn1, bcBtn2); TGaugeButtonClickEvent = procedure (Sender: TObject; Clicked: TBtnClicked) of object; TGaugeButton = class(TCustomControl) private FBtnClick : TGaugeButtonClickEvent; .... .... Btn1: TButton; Btn2: TButton; .... procedure SetBtnClick(Sender: TObject); ....
protected ..... public .... ....
published .... .... property OnBtnClick: TGaugeButtonClickEvent read FBtnClick write FBtnCLick;
end;
implementation
..... .....
constructor TGaugeButton.Create (AOwner: TComponent); begin inherited Create(AOwner); OnClick:= SetBtnClick; .... .... Btn1:= TButton.Create(Self); Btn1.OnClick:= SetBtnClick; .... ....
Btn2:= TButton.Create(Self); Btn2.OnClick:= SetBtnClick; .... .... end;
procedure TGaugeButton.SetBtnClick (Sender: TObject); begin if Assigned(FBtnClick) then begin if Sender = Btn1 then FBtnClick(Self, bcBtn1) else if Sender = Btn2 then FBtnClick(Self, bcBtn2) else FBtnClick(Self, bcNoBtn); end; end; |
Nun geh ich davon aus, das es so richtig umgesetzt ist :wink:
Gruss Alf
ALF - So 31.10.10 15:30
Hilfe meine Routine funct nicht mehr
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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47:
| type TBtnClicked = (bcNoBtn, bcBtn1, bcBtn2, bcPlay, bcStop); TGaugeButtonClickEvent = procedure (Sender: TObject; Clicked: TBtnClicked) of object;
private FBtnClick: TGaugeButtonClickEvent; ..... procedure SetBtnClick(Sender: TObject); published
property OnBtnClick: TGaugeButtonClickEvent read FBtnClick write FBtnCLick;
..... .....
procedure TGaugeButton.SetBtnClick(Sender: TObject); begin if not Assigned(FBtnClick) then begin if Sender = Btn1 then FBtnClick(Self, bcBtn1) else if Sender = Btn2 then FBtnClick(Self, bcBtn2) else if TSpeedButton(Sender).Name = 'BtnPLay1' then begin BtnPlay.Glyph.LoadFromResourceName(hInstance, 'Bild4'); BtnStop.Enabled:= True; FBtnClick(Self, bcPlay);
end else if TSpeedButton(Sender).Name = 'BtnStop1' then begin BtnStop.Enabled:= True; BtnPlay.Glyph.LoadFromResourceName(hInstance, 'Bild3'); FBtnClick(Self, bcStop); end else begin FBtnClick(Self, bcNoBtn); TGaugeButton(Sender).SetFocus; end; end; end; |
Ändere ich es so, bekomme ich Fehlermeldung an allen stellen wo FBtnClick(Self, ...) steht
Zugriffsverletztung bei Adresse 00000000
Ich habe doch nur was hinzugefügt, zusätzlich 2 Buttons! Selbst wenn ich die wieder rausnehme, bleibt der Fehler!
Gruss ALf
bummi - So 31.10.10 15:54
Delphi-Quelltext
1: 2: 3: 4: 5:
| if not Assigned(FBtnClick) then begin if Sender = Btn1 then FBtnClick(Self, bcBtn1) else |
wenn FBtnClick nicht Assigned ist rufst Du es auf??????????
muß heißen if Assigned(FBtnClick)
Du muß die Clickroutine zuweisen, dann passiert auch etwas
ALF - So 31.10.10 16:09
bummi hat folgendes geschrieben : |
wenn FBtnClick nicht Assigned ist rufst Du es auf??????????
muß heißen if Assigned(FBtnClick) |
War ja auch so, nur da überspringt er komischerweise die Abfrage und geht gleich zum ende der Procedure???
bummi hat folgendes geschrieben : |
Du muß die Clickroutine zuweisen, dann passiert auch etwas |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| OnClick:= SetBtnClick; .... .... Btn1.OnClick:= SetBtnClick; Btn2.OnClick:= SetBtnClick; BtnPlay.OnClick:= SetBtnClick; BtnStop.OnClick:= SetBtnClick; |
sind sie!
Hat ja ach alles funktioniert, nur jetzt nicht mehr!? :cry:
Gruss ALf
jaenicke - So 31.10.10 16:18
ALF hat folgendes geschrieben : |
War ja auch so, nur da überspringt er komischerweise die Abfrage und geht gleich zum ende der Procedure??? |
Dann ist FBtnClick eben gerade
nicht zugewiesen. Das ist ja genau das Problem.
Das ist wie wenn du zum Fahrer sagst:
"Wenn Reifen am Wagen sind, dann fahre los."
Der fährt aber nicht los. Also sagst du einfach:
"Wenn keine Reifen am Wagen sind, dann fahre los."
Und wunderst dich, dass das Auto komische Geräusche macht. (Zugriffsverletzung) :mrgreen:
ALF - So 31.10.10 16:26
Das war ja auch nur zum Test! :wink:
Nur erklärt es mir nicht warum plötzlich nix mehr passiert??? ergo FBtnclick bleibt nil!
Gruss Alf
jaenicke - So 31.10.10 16:26
Du weist OnBtnClick nicht zu. :nixweiss:
ALF - So 31.10.10 17:05
So noch mal neu überarbeitet, alla
Xion delüx Vorschlag! anstatt V steht bei mir F . Trotzdem, nix passiert!?
Was vorher klappte, will jetzt nicht mehr. Ich finde und seh nichts wo es klemmpt :autsch:
:cry: :cry: :cry:
Gruss ALf
bummi - So 31.10.10 17:25
ist 1.) OnBtnClick ein Event im Objektinspektor zugewiesen?
2.) verwendest Du in Deinem Code nur noch VOnButtonClick und nicht noch irgendwo als Leiche FOnButtonClick
wenn ja, wirst Du Komponentensource und Testprogramm als Code hinterlegen müssen damit Dir geholfen werden kann.
ALF - So 31.10.10 17:39
1. ist sichtbar.
2. anstatt V habe ich F genommen!
3. ich hänge mal den Code dran.
und bin gespannt wo ich Dussel nen Fehler nicht mehr sehe!
bummi - So 31.10.10 17:53
Ich musste zum testen die Resoureladerreien rausnehmen und TRoundbutton durch Button ersetzen.
Getestet mit
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Button2Click(Sender: TObject); begin With TGaugeButton.Create(self) do begin Parent := Self; OnBtnClick := ButtonClick; end; end; |
läuft ....
ich bin fast sicher daß Du im Objektinspektor OnBtnClick nicht zugewiesen hast
ALF - So 31.10.10 19:04
Mhh... peinlich!
Mir war so, wenn ich die pas meinem Project hinzufüge und ich sie dann mit Haltpunkte versehe, genau in der OnBtnClick routine, das ich dann zugreifen kan auf den Sender um zu sehen ob alles richtig ausgeführt wird. Das muss dann wohl ein Irrtum von mir gewesen sein!
Alles ander funct. Also im OI doppelclick auf OnBtnClick usw.
Danke noch mal
Gruss ALf
jaenicke - So 31.10.10 19:06
Aller guten Dinge sind drei (also was den Hinweis darauf angeht). :D
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!