TMultiButton, ein Button mit einem integrierten Button

Zur Vorstellung von Komponenten und Units für Lazarus
wennerer
Beiträge: 218
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 19.3 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo zusammen,
ich hab mir einen MultiButton gebastelt. Würde mich sehr freuen wenn Jemand Lust hat ihn bei Gelegenheit mal auszuprobieren. Kritik ist sehr erwünscht!!!

Hier ein Screenshot vom Demo Programm:
TestTheMultiButton.png
TestTheMultiButton.png (53.91 KiB) 1252 mal betrachtet
Viele Grüße
Bernd

Edit: Die neuste Version (Release2) befindet sich weiter hinten in diesem Beitrag.
Dateianhänge
Release01.zip
(306.96 KiB) 19-mal heruntergeladen
Zuletzt geändert von wennerer am Mo 23. Nov 2020, 17:35, insgesamt 1-mal geändert.

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Hallo Bernd,

ich wollte mir grad deine Komponente anschauen bzw. installieren.
Ich bekomme eine Fehlermeldung beim Compilieren.

Er findet DrawForControl nicht
Zeile 2070: FImageList.DrawForControl(canvas,FImageLeft+FBLeft,FImageTop+FBTop,FImageIndex,FImageWidth,aImage,gdeNormal);

hast Du, oder jemand, eine Idee woran das liegen könnte ?

Ich habe die Lazarus Version 1.8.4
Windows 10 64 Bit

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

Benutzeravatar
theo
Beiträge: 8508
Registriert: Mo 11. Sep 2006, 19:01

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von theo »

siro hat geschrieben:
Sa 21. Nov 2020, 10:52
hast Du, oder jemand, eine Idee woran das liegen könnte ?

Ich habe die Lazarus Version 1.8.4
Es könnte daran liegen, dass deine Version vom Mai 2018 ist.
Wir sind bei Lazarus 2.0.10

https://www.lazarus-ide.org/index.php?page=downloads

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Genau das war es gewesen. Lazarus Version zu alt,
auf dem anderen Rechner hab ich Lazarus 2.0.8 und dort konnte ich es ohne Probleme installieren.

Ich danke Dir Theo.

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

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Hallo Bernd,

ich habe eben ein bischen mit deiner Komponente herumgespielt
und möchte auf jeden Fall ein "positives" Feedback geben.
Gefällt mir wirklich gut.

Zunächst war mir nicht ganz klar warum man einen Button in einem Button braucht.
Aber das kann tatsächlich nützlich sein, sihe Demo von Dir.

Die OnClick Funktionen habe ich mal probiert, sie landen separat und richtig zugehörig bei den verschachtelten Buttons.

Anregungen:
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 ?
z.B. "HotSpotFrame" 0..x oder ähnlich..

Zuerst dachte ich, dass BorderColor und BorderWith garnicht verwendet werden,
aber dazu muss lediglich weiter unten im Eigenschafteditor "ShowBorder" auf True gesetzt werden.
evtl. BorderVisible nennen ?? dann hat man im Objectinspektor gleich die Zugehörigkeit,
da dort anscheinend immer Alphabetisch sortiert wird (ist das immer so ??)

Bei Hint heisst es ja auch "ShowHint" und ist damit örtlich getrennt von "Hint" im Eigenschaftseditor...

Bleibt also fraglich ob das wirklich sinnvoll ist.


Für CaptionLayout könnte man noch tlUser einbauen.
ist dies angewählt, werden automatisch die Werte von CaptionLeft und CaptionTop verwendet.
Nur durch deinen Hinweis im Objektinspektor habe ich nämlich die Wirkunsweise verstanden.
Somit also nicht wirklich nötig sondern als Idee gedacht.

Textposition:
Test_01.jpg
Test_01.jpg (12.12 KiB) 339 mal betrachtet
Wenn BorderWidth sichtbar ist, wäre noch eine Positionsanpassung des Textes sinnvoll:
bei taLeftJustify BorderWidth dazu addieren
bei taRightJustify entsprechend abziehen

Bei CaptionLayout auch bei Top und Bottom noch Textposition y anpassen an BorderWidth.
sonst landet der Text im Rahmen

Insgesamt eine sehr schöne Komponente.
Auch die Images im Demo gefallen mir sehr gut.

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

wennerer
Beiträge: 218
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 19.3 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo Siro,
freut mich sehr das du den MultiButton mal getestet hast und vielen Dank für deine umfangreiche Rückmeldung!!!
Wie du bestimmt gesehen hast konnte ich viele Sachen die du mir gezeigt hast wieder mit einbauen.
Im Prinzip scheinen die 5 Pixel der "Hover" Rahmen (Focus Rahmen) zu sein.
sollte evtl. einstellbar sein ?
z.B. "HotSpotFrame" 0..x oder ähnlich..
Ja das verwirrt etwas (sogar mich selber). Ursprünglich wollte ich es so machen das width und height im OI die Größe des Multibuttons sind. Das hat aber aus verschiedenen Gründen überhaupt nicht funktioniert. Ich glaube das mit dem einstellbaren HoverRahmen ist eine gute Idee. Dann wird das etwas plausibler.
Wenn BorderWidth sichtbar ist, wäre noch eine Positionsanpassung des Textes sinnvoll:
bei taLeftJustify BorderWidth dazu addieren
bei taRightJustify entsprechend abziehen
Danke für den Hinweis. Ist mir nicht aufgefallen obwohl ich mit dem TextRect und TextStyle länger herum probiert hab.
siehe auch;
viewtopic.php?f=55&t=13225
Das muss ich wohl über die Größe des TextRechteckes anpassen.
Er findet DrawForControl nicht
Zeile 2070: FImageList.DrawForControl(canvas,FImageLeft+FBLeft,FImageTop+FBTop,FImageIndex,FImageWidth,aImage,gdeNormal);
Gut das Theo geantwortet hat. Ich wusste gar nicht das ich so moderne Sachen verwende :D

Nochmal herzlichen Dank und viele Grüße
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Guten Morgen Bernd,

ich habe eben mal die Funktionsweise deiner Unit PtIn genauer probiert,
also ob die Mausklicks auch wirklich innerhalb des Buttons richtig erkannt werden und muss sagen
"jo, das funktioniert ausgezeichnet". Egal ob Circle, Ellipse, RoundRect usw. die Bereiche werden rechts,links, oben unten
innerhalb, ausserhalb super erkannt.

Sehr schön, dass Du es in einer eigenen Unit untergebracht hast. Somit kann man diese auch für andere Zwecke direkt benutzen.
So etwas hatte ich schon mal gesucht. Poly habe ich aber noch nicht getestet.

Gestolpert bin ich über die Procedure Check, die sich innerhalb der Funktion PointInRoundRect befindet.
Ich hoffe, dass hier der Stack richtig verarbeitet wird....
Ein Call in die Procedure Check, dann ein Exit.
Dieses Exit soll dann die innere Procedure Check verlassen und die Funktion PointInRoundRect.

Die Idee finde ich interessant, wäre mir da aber unsicher gewesen und hätte es sicher anders gelöst:

Code: Alles auswählen

begin
 result:=TRUE;    // vermutlich liegt der Punkt innerhalb

 checkP.X:=x;checkP.Y:=y;
 checkRect := rect(aRect.Left+(rx div 2),aRect.Top,aRect.Right-(rx div 2),aRect.Bottom);
 if PtInRect(checkRect,checkP) then EXIT;    // Jo, ist innerhalb ende mit TRUE
 // ansonsten weiter prüfen...
 checkRect := rect(aRect.Left,aRect.Top+(ry div 2),aRect.Right,aRect.Bottom-(ry div 2));
 if PtInRect(checkRect,checkP) then EXIT;        // ist innerhalb, Ende mit TRUE
 ...
 ...
 result:=FALSE; // wenn er hier ankommt, war der Punkt ausserhalb, Ende mit FALSE
end;
ich hoffe, ich habe es überhaupt so richtig verstanden und liege nicht falsch...

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

wennerer
Beiträge: 218
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 19.3 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Guten Morgen Siro,
ich hoffe, ich habe es überhaupt so richtig verstanden und liege nicht falsch...
Hast du vollkommen richtig verstanden und auch vollkommen recht. Das exit ist wirkungslos. Ich habe es nun genauso umgeschrieben wie du es machst. Ich hab mir da wohl von hinten ins Knie geschossen.
Ich hänge nochmal meinen Test zu der unit an. Da kann man dann auch ein Polygon testen.
Vielen Dank für deinen Hinweis, wäre mir nie aufgefallen! Aber ein Profi sieht's halt dann doch. :D

Viele Grüße
Bernd
Dateianhänge
PtIn_Test.zip
(74.14 KiB) 8-mal heruntergeladen

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von siro »

Ja supi Bernd,
Demoprogramm funktioniert perfect.

Ich habe das Polygon abgeändert und siehe da, auch das funktioniert einwandfrei.
InPoly.jpg
InPoly.jpg (11.17 KiB) 232 mal betrachtet

Ich habe zu danken für die Unit :wink:

Siro

eine Kleinigkeit noch: Ein Datum oder Version in jeder Datei oben rein.
Ich war mir eben nicht sicher welches die neue und welches die alte Unit war...
und wünsche noch einen schönen Sonntag.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

sstvmaster
Beiträge: 366
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: Windows 10 | Lazarus: 2.0.10 und Trunk 32bit
CPU-Target: 32Bit
Wohnort: Dresden

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von sstvmaster »

Hallo Bernd,

Danke für deine Unit.

In der Funktion PointInCircle berechnenest du die Hypotenuse selbst, es gibt eine passende Funktion HyPot in der math unit.

Code: Alles auswählen

function PointInCircle(aRect: TRect; x, y: Integer): Boolean;
var radius : integer;
    a,b    : integer;
begin
 radius := (aRect.Right - aRect.Left) div 2;
 a := aRect.CenterPoint.X - x;
 b := aRect.CenterPoint.Y - y;
 if Round(HyPot(a,b)) <= radius then result:= true else result := false;
end; 
LG Maik

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Sieben »

Code: Alles auswählen

result := (Round(HyPot(a,b)) <= radius);
:wink:

wennerer
Beiträge: 218
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 19.3 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hallo zusammen,
vielen Dank für eure Antworten.
In der Funktion PointInCircle berechnenest du die Hypotenuse selbst, es gibt eine passende Funktion HyPot in der math unit.
Hab ich gleich verbessert. Mit der unit math sollte ich mich wohl auch mal genauer befassen, mach da einiges zu Fuß was es schon viel besser gibt.
Unbedingt möchte ich noch erwähnen das ich die ursprüngliche PtnInPoly in irgend einem Delphi Forumsbeitrag sah. Ist schon ziemlich lange her und ich habe denke ich ein paar Kleinigkeiten anpassen müssen das es lief. Finde die Quelle aber leider nicht mehr. Deshalb hier danke an den unbekannten Schöpfer für den tollen Algorithmus.

Viele Grüße
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Winni »

Hallo!

In der unit PtIn.pas ist auch eine Function PointInPoly.
Die ist korrekt, aber rechnet vielzuvielzuviel.

Vor ca 15 Jahren war im (leider verstorbenen) brasilianischen Forum
eine "PointInPoly Battle".

Den Geschwindigkeits Rekord hatte diese Version, die nur die 4 Grundrechenarten,
Vergleiche und etwas Boolsche Algebra benutzt:

Code: Alles auswählen

function PointInPoly(p : TPoint; const poly :  array of TPoint) : Boolean; 
var i,k : integer;
Begin
 result := false;
 k := High(poly);
 For i := 0 to high(poly) do begin
  if (
     ( ((poly[i].y <= p.y) and (p.y < poly[k].y)) or ((poly[k].y <= p.y) and (p.y < poly[i].y)) ) and
        (p.x < ((poly[k].x - poly[i].x) * (p.y - poly[i].y) / (poly[k].y - poly[i].y) + poly[i].x) )
     ) then result := not result;
  k := i
 end;
end;      

Das kann mit minimaler Änderung für Fließkomma Werte umgewandet werden:

Code: Alles auswählen

function PointInPoly(p : TPointF; const poly :  array of TPointF) : Boolean; 
var i,k : integer;

Begin
 result := false;
 k := High(poly);
 For i := 0 to high(poly) do begin
  if (
     ( ((poly[i].y <= p.y) and (p.y < poly[k].y)) or ((poly[k].y <= p.y) and (p.y < poly[i].y)) ) and
        (p.x < ((poly[k].x - poly[i].x) * (p.y - poly[i].y) / (poly[k].y - poly[i].y) + poly[i].x) )
     ) then result := not result;
  k := i
 end;
end;    

Falls jemand einen schwachbrüstigen Rechner besitzt oder das in einem Loop benutzt.
ist die obige Function von Vorteil.

Wenn man versucht, die function per inline noch einmal zu beschleunigen:
Vergiss es:
Functionen mit Arrays of irgendwas können nicht inlined werden.
Vielleicht komt das zum Sommer 2024: Da wird Blaise Pascal 400.

Winni

wennerer
Beiträge: 218
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 19.3 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von wennerer »

Hi Winni,
danke für die function. Darf ich die dann so benutzen?

Gruß
Bernd

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

Re: TMultiButton, ein Button mit einem integrierten Button

Beitrag von Winni »

Hi!

1. Natürlich
2. Ist doch sowieso alles OpenSource hier
3. Ich hab's doch auch nur aus dem brasilianischen Forum
4. Ist doch nur die nackte Implementierung des Jordan Algorithmus
"Wie oft kreuzt ein gedachter Strahl die Kanten eines Polygons?"
Ungerade: innerhalb des Polygons.
Gerade : außerhalb
Algorithmen unterliegen keinem Copyright.
Auch wenn manche Konzerne das möchten.

Winni

PS.: Ich beantrage jetzt das Copyright auf "Eins und Eins ist Zwei".
So werde ich doch noch mal reich .......

Antworten