TMultiButton, ein Button mit einem integrierten Button

Zur Vorstellung von Komponenten und Units für Lazarus
wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo Winni,
da hast du natürlich mit allem Recht. Aber einfach mal nur schnell strg+c ist ja auch doof. Ich werd auf jeden Fall in meine unit diesen Satz aufnehmen:
for some improvements see viewtopic.php?f=29&t=13252
Es sind nun ja bereits etliche Verbesserungen aus dem Forum eingeflossen!

Viele Grüße
Bernd

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
ich hab nun noch einige Anregungen eingebaut.

Siro schrieb:
Du scheinst einen "virtuellen" Rahmen um deine Schaltfläche zu haben.
Das verwirrte mich etwas bei den Einstellungen "Width" und Height"
Weil der eigentlich sichtbare Bereich kleiner nach innen versetzt ist.
Dort hast Du eine "feste" Größe von 5 Pixel vorgesehen.
Der eigentliche "Hotspot" ist also an allen 4 Kanten um 5 Pixel kleiner.
Im Prinzip scheinen die 5 Pixel der "Hover" Rahmen (Focus Rahmen) zu sein.
sollte evtl. einstellbar sein ?
Es lässt sich nun mit der Eigenschaft HoverFrameWidth die Breite frei einstellen. Allerdings sieht man dann bei einer Rechteckform bzw. RoundRect und einer Breite von 0 keinen Hover und Focus mehr.
Zusätzlich hab ich eine Beschreibung bei width und height im OI hinterlegt.
OI.jpg
OI.jpg (13.8 KiB) 3230 mal betrachtet
Ich hoffe damit wird das für einen Anwender etwas plausibler.
Wenn BorderWidth sichtbar ist, wäre noch eine Positionsanpassung des Textes sinnvoll:
bei taLeftJustify BorderWidth dazu addieren
bei taRightJustify entsprechend abziehen
Die Textausgabe mit TextRect ist auf der einen Seite sehr angenehm aber leider funktioniert nicht immer alles so wie man es erwartet. Verrechnungen zum Beispiel funktionieren nur mit taLeftJustify und tlTop. Ich habe deshalb das Textrechteck um BorderWidth verkleinert und FTextStyle.Clipping auf true eingestellt. Damit sollte der Text im Rechteck bleiben und nicht von der Border verdeckt werden (zumindest solange das Rechteck nicht zu klein wird).
Ein Datum oder Version in jeder Datei oben rein
Ja das muss ich mir unbedingt angewöhnen!

Die verschiedenen Verbesserungen für die Unit PtIn habe ich soweit eingebaut!

Vielen Dank an Alle und viele Grüße!
Bernd
Dateianhänge
Release02.zip
(18.11 KiB) 137-mal heruntergeladen

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Winni »

Hi!


Hover für Faule. Hat aber auch nen guten Effekt:

a) Schriftgrößer änden. Ausrichtung muss taCenter sein.
b) Font-Farbe ändern. Von Gelb auf schwarz ist reichlich Kontrast.Und freut die BVB-Fans.
c) Font-Style ändern. Von normal [ ] auf bold , italic oder Beides.

Das kann man alles kombinieren oder für sich benutzen.

Winni

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

wennerer hat geschrieben:
Mo 23. Nov 2020, 17:33
Die Textausgabe mit TextRect ist auf der einen Seite sehr angenehm aber leider funktioniert nicht immer alles so wie man es erwartet. Verrechnungen zum Beispiel funktionieren nur mit taLeftJustify und tlTop.
Wenn man es einmal verstanden hat, ist es ganz einfach: TextRect schreibt in das vorgegebene Rechteck, je nachdem wie die TextStyle-Elemente Alignment und Layout gesetzt sind, wobei aber die angegebenen X und Y-Koordinaten nicht immer verwendet werden:

Ist Alignment = taRightJustify wird der Text rechtsbündig an den rechten Rechteck-Rand gesetzt, bei Alignment taCenter horizontal im Rechteck zentriert, egal welchen Wert die X-Koordinate hat. Nur wenn Alignment = taLeftJustify ist, wird der Text linksbündig am Ort der Koordinate X begonnen.

Genauso mit der vertikalen Positionierung: Layout = tlBottom mal den Text an den unteren Rand des Rechtecks, tlCenter vertikal zentriert im Rechteck. Auch hier wird die Koordinate (nun Y) ignoriert. Nur wenn Layout = tlTop ist, wird der Text am Ort der Koordinate gezeichnet, und zwar so, dass die Text-Oberkante bei Y liegt.

Überzeuge dich mit dem folgenden Code. Setze eine Paintbox aufs Formular und weise ihr folgenden OnPaint-Handler zu.

Code: Alles auswählen

procedure TForm1.PaintBox1Paint(Sender: TObject);
const
  s = 'Text';
  ignored = MaxInt;
var
  ts: TTextStyle;
  R: TRect;
begin
  with PaintBox1.Canvas do begin
    Brush.Color := clWhite;
    R := Rect(0, 0, Paintbox1.Width, Paintbox1.Height);
    FillRect(R);

    ts := TextStyle;
    ts.Alignment := taLeftJustify;
    ts.Layout := tlTop;
    TextRect(R, R.Left, R.Top, s, ts);

    ts.Alignment := taCenter;
    TextRect(R, ignored, 0, s, ts);

    ts.Alignment := taRightJustify;
    TextRect(R, ignored, 0, s, ts);

    ts.Layout := tlCenter;
    ts.Alignment := taLeftJustify;
    TextRect(R, 0, ignored, s, ts);

    ts.Alignment := taCenter;
    TextRect(R, ignored, ignored, s, ts);

    ts.Alignment := taRightJustify;
    TextRect(R, ignored, ignored, s, ts);

    ts.Layout := tlBottom;
    ts.Alignment := taLeftJustify;
    Textrect(R, 0, ignored, s, ts);

    ts.Alignment := taCenter;
    TextRect(R, ignored, ignored, s, ts);

    ts.Alignment := taRightJustify;
    Textrect(R, ignored, ignored, s, ts);
  end;
end; 

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo wp_xyz,
nach anfänglichen Schwierigkeiten hab ich das Verhalten von TextRect schon verstanden.
siehe: viewtopic.php?f=55&t=13225

Ich hab mich da aber vielleicht etwas missverständlich ausgedrückt. Ich verwende TextRect für die Ausgabe der Caption. Dies ist einerseits wegen der bereitgestellten Eigenschaften sehr angenehm. Auf der anderen Seite hab ich dann aber im OI die Properties CaptionLeft und CaptionTop die halt eventuell nicht reagieren.
Konkretes Beispiel: Bei taRightJustify und etwas dickem Rand wird der Text rechts etwas verdeckt. Mit CaptionLeft lässt sich leider nichts korrigieren. Wenn man weiß das TextRect verwendet wurde ist das natürlich klar. Meine Lösung ist jetzt das ich das TextRect um die Breite des Randes verkleinere.
Richtig cool wäre es wenn CaptionLeft und CaptionTop nur sichtbar wären wenn sie auch benutzt werden können, oder sie wären ausgegraut. Hab so was aber noch nie gesehen. Kann man so was machen?

Viele Grüße
Bernd

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Sieben »

Das habe ich beides auch noch nicht gesehen und wüsste auf Anhieb auch keinen Ansatz. Du kannst aber einen entsprechenden Setter schreiben, der Werte bei unpassenden Randbedingungen wieder zurücksetzt und/oder (am besten nur zur Designzeit) auch Meldungen ausgibt.

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wp_xyz »

wennerer hat geschrieben:
Mo 23. Nov 2020, 19:17
Richtig cool wäre es wenn CaptionLeft und CaptionTop nur sichtbar wären wenn sie auch benutzt werden können, oder sie wären ausgegraut. Hab so was aber noch nie gesehen. Kann man so was machen?
Das geht nicht, gelegentlich findet man auch in der LCL Beispiele, dass Properties mitgeschleppt werden, die nur in einem bestimmten Zusammenhang angewendet werden.

Was du machen kannst, ist, den beiden Properties einen unverfänglicheren, allgemeiner gültigen Namen zu geben. Ich würde die beiden statt CaptionLeft/CaptionTop HorMargin/VertMargin nennen. Das wäre dann der Abstand der Caption zum Rand des Buttons, was sowohl bei links-/rechtsbündiger und oberer/unterer Ausrichtung einen Sinn gäbe. Und dass sie bei zentrierter Ausgabe unnötig sind, ist unmittelbar klar.

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
ich habe erst nochmal über alle Antworten etwas nachdenken müssen :wink:

Winni schrieb:
Hover für Faule. Hat aber auch nen guten Effekt:

a) Schriftgrößer änden. Ausrichtung muss taCenter sein.
b) Font-Farbe ändern. Von Gelb auf schwarz ist reichlich Kontrast.Und freut die BVB-Fans.
c) Font-Style ändern. Von normal [ ] auf bold , italic oder Beides.

Ja, habe nun eine Property HoverFontColor hinzugefügt. Damit hat man noch eine weitere Möglichkeit den Hover/Fokus darzustellen.

Sieben schrieb:
Du kannst aber einen entsprechenden Setter schreiben, der Werte bei unpassenden Randbedingungen wieder zurücksetzt und/oder (am besten nur zur Designzeit) auch Meldungen ausgibt.
Find ich auch gut. Hab ich so eingebaut. Es sollte jetzt eine ShowMessage ausgelöst werden.

wp_xyz schrieb:
Was du machen kannst, ist, den beiden Properties einen unverfänglicheren, allgemeiner gültigen Namen zu geben. Ich würde die beiden statt CaptionLeft/CaptionTop HorMargin/VertMargin nennen.......
Ich weiß nicht ob das sehr viel verbessert. Aber es klingt viel professioneller! Hab ich deshalb auch so umgesetzt (CaptionHorMargin, CaptionVerMargin).

Vielen Dank an euch für die Antworten. Mir ist schon klar das ich der einzige sein werde der die Komponente in einem kleinen Programm verwenden wird. Ich finde es aber dennoch schön wenn ich durch die Tipps hier im Forum die Komponente ein bisschen verbessern kann.

Viele Grüße
Bernd
Dateianhänge
Release03.zip
(246.87 KiB) 141-mal heruntergeladen

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

PtInPoly hat sich ja nun verändert und ich habe mal einen Test gemacht:
In Windows kann man sehr schön Zeiten messen und es zeigt sich, dass die neue PtInPoly rund 4 mal schneller ist als die ehemalige (alte) Version.
600ns zu 2,2µs
Poly_Time.jpg
Poly_Time.jpg (13.56 KiB) 3114 mal betrachtet
Ich weis nicht ob man sowas auch unter Linux testen kann.

Code: Alles auswählen


var freq,tStart,tStop:Int64;
var t:Single;  

 ...... 
 if Form = Poly then
  begin
   p.X:=x;p.Y:=y;
   QueryPerformanceFrequency(freq);

   QueryPerformanceCounter(tStart);
   if PtInPoly(aPolygon,p)    then aColor := cllime else aColor:=clyellow;
   QueryPerformanceCounter(tStop);
   t:=(tStop-tStart) / freq; { in Sekunden umrechnen }
   Label1.caption:=FloatToStr(t);

   QueryPerformanceCounter(tStart);
   if PtInPolyOld(aPolygon,p) then aColor := cllime else aColor:=clyellow;
   QueryPerformanceCounter(tStop);
   t:=(tStop-tStart) / freq; { in Sekunden umrechnen }
   Label2.caption:=FloatToStr(t);
  end;                                 
                                                 
Textausrichtung auch nochmal geprüft:
Der Zusätzliche Abstand geht auch.
Jo, sieht gut aus.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Winni »

Hi!

Ich kannte "QueryPerformanceCounter" bis eben nicht .

Aber was auf *allen* Plattformen funktioniert, ist

getTickCount64
aus der unit lazsysutils.pas.

Das gibt dir Millisekunden zurück, und zwar seit dem der Rechner gestartet wurde.

Damit kannst du also genauso rechnen:

Code: Alles auswählen

Procedure Irgendwas;
var  startTime = Qword;
begin
StartTime := getTickCount64;
...
showMessage ('Das hat gedauert: '+IntTor(GetTickCount - startTime)+' Millisekunden');
end;
Für die geschichtlich Interesserten. Und für den Humor:

Die frühen Versionen von Windows NT (Anfang der 90iger) waren der hoffnungsvolle Lichtblick in der Geschichte
der Windows-Rechner: Als Server einsetzbar und halbwegs stabil. Kein Wunder: Codiert von dem ehemaligen VMS-Team - abgeworben von DEC. Eine Macke hatten die Rechner: alle ??? Tage krachte das OS ohne ersichtlichen Grund. Da dieser Zyklus anscheinend > 40 Tage war, ging man dazu über, die NT-Rechner am Monats-Ersten zu booten.
An dieser Stelle zeigte es sich, wie hilfreich die 4 Grundrechen-Arten seien können. Wenn das wühlen in zig Seiten von C-Code nicht geholfen hat:

Damals war getTickCount64 noch nicht erfunden und alles wurde mit 32 Bit erledigt - das war gerade das Modernste im Schrank. Nun geht das große Rechnen los:

MaxDWord / 1000 MillSec = 49.xxxx Tage.

Es war ein simpler 32-Bit-Overflow, den NT nicht verkraftete.
Großes Gelächter allerseits.
Und die Geburt von GetTickCount64

Bei großen Dimensionsdifferenzen sollte man also mal X * PI * Daumen gucken,
ob das dann alles noch in einen Int64 (oder Double) passt.

Winni

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Hallo Bernd,

Ich habe soeben ein kleines Problem noch festgestellt bei deinem MultiButton.
Ich habe die Release3 installiert, sollte also auf den aktuellen Stand sein.

Beim experimentieren ist mir dann Lazarus komplett abgestürzt.
aber ich glaube ich habe das Problem einkreisen können.

Wenn Du auf dem Formular im Erstellungsmodus den Button in der Größe veränderst
und die untere Kante über die obere ziehst, dann gibt es wohl eine negative Höhe,
was Lazarus bei mir mit einem Totalabsturz ahndete.

Den Button könnte ich momentan sogar gut verwenden, mir gefällt die Optik.
Er lässt sich optisch recht gut so einstellen wie ich das grad haben möchte.

Das passiert dann auch, wenn ich die rechte Ecke über die Linke ziehe... :wink: grad probiert.
---
Neuer Versuch:

wenn ich im Objektinspektor width setze, dann gibt es ebenfalls ein Problem.
Werte kleiner 10 verusachen einen Fehler.
MultiButton_Width.jpg
MultiButton_Width.jpg (15.14 KiB) 2827 mal betrachtet
Hier muss noch ein bischen RangeChek rein...

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Grüß dich Siro,
freut mich das du den MultiButton brauchen kannst. Das ein Fehler kommt natürlich weniger. Ich habe das wohl tatsächlich nie probiert.
Ich habe in der neuen Version (Release4) die Werte von width und height so begrenzt das sie größer bleiben als 2xHoverFrame. Beim MessageButton ist nun eine Eingabe von negativen Werten nicht mehr möglich.
Gib mir bitte Bescheid falls dir noch was auffällt.
Ich hänge die neueste Version mal an den ersten Beitrag. Dann braucht man nicht immer alles nach der letzten Version durchsuchen.

Eine Gute Zeit und viele Grüße
Bernd

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Jo, funktioniert.

Ich danke Dir und noch ein schönen Sonntag.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo,
angeregt durch den Beitrag von nimral viewtopic.php?f=18&t=13674 habe ich mich an ein paar Änderungen versucht.
Als erstes habe ich den Rahmen in Fokusrahmen umbenannt und er reagiert auch nur noch auf den Fokus und nicht mehr auf den Hover (das war wirklich etwas verwirrend). Den Fokus kann man mit FocusedOn ein- und abschalten. Der Hover kann mit HoverStartColor, HoverEndColor und HoverOn beeinflusst werden.
An die beim SpeedButton vorhandene Eigenschaft GroupIndex dachte ich bis jetzt nicht, gefällt mir aber sehr gut.
Ich habe deshalb eine Eigenschaft Down und AllowsUp eingefügt. Stellt man Down auf true und AllowsUp auf true ist der Button gedrückt und lässt sich durch anklicken "entdrücken".
Auch gibt es jetzt die Property GroupIndex bleibt man bei 0 (=default) schaltet jeder Button für sich allein. Stellt man mehrere Buttons auf einen anderen GroupIndex kann nur immer einer dieser Buttons gedrückt sein. Stellt man noch die neue Eigenschaft ShowMsgButtonInGroup auf true hat der gedrückte Buton einen sichtbaren Messagebutton.
Ich stelle die neuste Version vorne in den ersten Beitrag. Es befindet sich auch ein kleines Testprogramm im Anhang wo das Beschriebene gut zu erkennen ist.



Viele Grüße
Bernd
Dateianhänge
MultiButton.png
MultiButton.png (20.16 KiB) 2629 mal betrachtet

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Hallo Bernd,
habe mir grade deinen neuesten Code rutergeladen und angeschaut.

Erstaunlich wie sich manch Code ähnelt.
Ich habe bei meinen Tasten auch eine fast identische Funktionsweise mit dem GruppenIndex,
mit einem Unterschied: GroupIndex -1 bedeutet bei mir "Eigenständige Taste mit Festhaltefunktion".
Was Du, wenn ich das richtig verstanden habe, über das zusätzliche Flag "AllowsUp" gelöst hast.

Mich hatte der Code der GruppenTasten auch interessiert und der sieht recht ähnlich aus wie meiner,
wobei Du eine recht elegante Methode der Schleife benutzt hast, die ich so noch garnicht kannte.
for comp in self.Parent do
Da klappert er also alle Komponenten des Besitzerfensters ab.

das habe ich bisher so gemacht:
for i:=0 to Owner.ComponentCount-1 do

Deine Methodik gefällt mir aber besser.

Ich bin immer wieder erstaunt wie man über 2000 Zeilen Code schreiben kann für eine Taste.
Das sind doch nur 2 Drähte.... :mrgreen:
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Antworten