Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Listbox, Einträge nur teilweise anders einfärben
Friedhelm - Mo 25.11.02 19:21
Titel: Listbox, Einträge nur teilweise anders einfärben
Hallo zusammen,
ich möchte die Einträge einer LIstbox in derselben Zeile nur teilweise, in Abhängigkeit vom angezeigten Wert, z.B. 100 anders einfärben.
d.h. Wert ist 100 am Ende der Zeile habe ich einen Strich mit 100 Einheiten.
ist der Wert 50, dann soll der Strich um die Hälfte kürzer sein.
Hat dazu jemand eine Idee?
Danke für den Tip
Gruß
Friedhelm
Keldorn - Mo 25.11.02 21:14
Hallo,
wenn ich dich richtig versatnden habe, geht das, indem Du die einzelnen Items und den Hintergrund selber zeichnest.
die eigenschaft Style der listbox mußt du auf lbOwnerDrawFixed stellen
Anm: 100 ist der maximalwert, die werte der Listbox dürfen nur Zahlen sein, sonst schepperts...
ansonsten sollte der ansatz da sein.
Mfg Frank
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:
| procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); Var x1:integer; arect:Trect; begin with (Control as Tlistbox) do begin //anteil bestimmen x1:=round(strtoint(items[index])*rect.right/100); //Balken zeichnen - wenn Item selektiert, dann andere Farbe wählen arect:=rect; arect.Right:=x1; if odSelected in State then canvas.brush.color:=clgray else canvas.brush.color:=clltgray; Canvas.fillrect(arect); //RestBalken weiß zeichnen arect:=rect; arect.left:=x1; if odSelected in State then canvas.brush.color:=clblue else canvas.brush.color:=clwhite; Canvas.fillrect(arect); //Textausgeben Canvas.brush.style:=bsclear; canvas.textout(rect.left+2,rect.top+2,items[index]); end; end; |
Tino - Di 26.11.02 10:08
Keldorn hat folgendes geschrieben: |
Anm: 100 ist der maximalwert, die werte der Listbox dürfen nur Zahlen sein, sonst schepperts... |
Dazu brauch man eigentlich nur noch das
OnMeasureItem-Event benutzen.
Gruß
TINO
Keldorn - Di 26.11.02 10:42
Tino hat folgendes geschrieben: |
Dazu brauch man eigentlich nur noch das OnMeasureItem-Event benutzen.
|
wie meinst du das ?
von unterschiedlichen Höhen der Items war ja noch nicht die Rede :?
mit dem maximal-wert 100 meinte ich die x-Position, da ja sonst die Umrechnung nicht mehr richtig funzt.
mit den werten und scheppern: meinte ich das STRtoint
Mfg Frank
Tino - Di 26.11.02 10:45
Hallo,
ich habe das so verstanden das so eine Art Balken in jeweils verschiedenen Höhen angezeigt wird. Wenn das nicht der Fall sein sollte dann ist natürlich der Hinweis von mir an dieser Stelle nicht richtig!
Gruß
TINO
Friedhelm - Mi 27.11.02 16:23
Hallo zusammen,
im Prinzip hat es funktioniert. Nur muss ich den Anfangspunkt des Balkens in der Listbox hinter den gesamten String legen.
d.h.: 020102-A354-P035 !---------------hier soll der Balken hin, in
Abhängigkeit des Wertes "035" nämlich in diesem Falle 35%.
Oder kann man es verbessern?
Gruss
Friedhelm
Keldorn - Mi 27.11.02 16:33
Zitat: |
Oder kann man es verbessern?
|
ja.
haben die Einträge alle die gleiche Länge bzw. sollen die Balken den gleichen Anfang haben?
Du mußt 3x Fillrect aufrufen und die 3 Teilbereiche zeichnen (Schrift, Balken, Balkenrest)
x1:=round(strtoint(items[index])*rect.right/100);
das rect.right/100 muß dann auch entsprechend und das arect muß jeweils angepaßt werden.
Sollte aber alles kein großes Problem sein, probiers erstmal und wenn du noch Probs hast, meldsete dich wieder
Mfg Frank
Friedhelm - Mo 02.12.02 10:35
Hallo FRank,
ich habe es probiert. Die Länge von dem String macht Ärger. Der Balken soll ab dem Audrufungszeichen bis rechts Anschlag Listbox gehen. Die 035 ist der Wert, den ich jeweils als Balken zeichnen möchte.
Gruss
Friedhelm
Keldorn - Mo 02.12.02 10:40
hallo
poste mal deinen Code von ondraw, mit der beschreibung kann ich nicht unbedingt viel anfangen und nur vermuten.
Frank
Friedhelm - Mo 02.12.02 14:36
Hallo Frank,
Also, die Länge der Balken soll von der 035 abhängen. (Das nächsten Projekt ist vielleicht 50% fertig)
Die Strings, die aufgelistet sind shen so aus: 020102-A-110345-P035
Hinter der 035 bis Ende Listbox = 100 Einheiten(0,25,50,75,100) möchte ich den Balken platzieren. Sop kann ich den Fortschritt jedes Projektes sehen.
Hier der Code:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| x1:=round(strtoint(items[index])*rect.right/100); arect:=rect; arect.Right:=x1;
if odSelected in State then canvas.brush.color:=clgray else canvas.brush.color:=clltgray; Canvas.fillrect(arect); arect:=rect; arect.left:=x1;
if odSelected in State then canvas.brush.color:=clblue else canvas.brush.color:=clwhite;
Canvas.fillrect(arect); Canvas.brush.style:=bsclear; canvas.textout(rect.left+2,rect.top+2,items[index]); |
Gruss
Friedhelm
(02.12. 13:53 Tino) Code-Tags hinzugefügt.
Keldorn - Mo 02.12.02 15:28
Hallo
meinen Code kannte ich :lol: :lol: ich wollte deinen sehen, du hast ja gar keinen Versuch unternommen, den Balken woanders zu zeichnen :twisted:
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:
| procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
const startposx = 100; //Anfangsposition des Balkens (mußt du anpassen)
Var arect : Trect;
begin with (Control as tlistbox) do begin //Hintergrund komplett löschen if odSelected in State then canvas.brush.color:=clblue else canvas.brush.color:=clwhite; Canvas.fillrect(rect);
//den Balken zeichnen arect:=rect; arect.Left:=Startposx; arect.right:=round(strtoint(items[index])* // 1) (rect.right-startposx)/100)+startposx; if odSelected in State then canvas.brush.color:=clgray else canvas.brush.color:=clltgray; Canvas.fillrect(arect);
//text ausgeben Canvas.brush.style:=bsclear; canvas.textout(rect.left+2,rect.top+2,items[index]); end; end; |
1) wie du diesen Wert ermittelst, ist ne andere Sache -> hier muß der Prozenzsatz stehen
die Endposition des Balkens ist das Verhältnis des Wertes zur maximal möglichen Gesamtlänge des Balkens
Mfg Frank
Friedhelm - Mo 02.12.02 19:41
Hallo Frank,
Danke für die Hilfe. Da wäre ich nicht draufgekommen. Ich habe es anders versucht. Ging nicht.Jetzt versuche ich noch herausfinden, wie der Rest von dem jeweiligen Item ignoriert werden kann.
Danke nochmals.
Gruss
Friedhelm
Friedhelm - Di 03.12.02 19:03
Hallo Frank,
ich kopiere die Prozentziffer aus dem gesamten String heraus.
Quelltext
1: 2: 3:
| for yy := 0 to Listbox1.Items.Count - 1 do Listbox1.Items.Add ( copy (Listbox1.Items [yy], 39, 3)); //Prozent |
das wäre denn an der Stelle: 39 drei Ziffern. In welcher Form kann man ihn den einfügen?
Quelltext
1: 2: 3: 4:
| arect.Left:=Startposx; arect.right:=round(strtoint(items[index])* YY ?? // 1)
(rect.right-startposx)/100)+startposx; |
Gruss
Friedhelm
(04.12. 08:39 Tino) Code-Tags hinzugefügt.
Keldorn - Di 03.12.02 19:34
Hallo
Zitat: |
arect.right:=round(strtoint(items[index])* YY ?? // 1) |
was soll das *YY denn bewirken ? :roll:
Zitat: |
In welcher Form kann man ihn den einfügen? |
diese Frage hast du dir doch schon selber beantwortet.
mit
Quelltext
1:
| Listbox1.Items.Add( copy (Listbox1.Items [yy], 39, 3)); //Prozent |
fügst Du die Prozentwerte in die Listbox ein um sie hier
strtoint(items[index])
wieder in eine Zahl zu wandeln um damit zu rechnen und die Balkenlänge zu ermitteln.
abgesehen davon macht
Quelltext
1: 2: 3:
| for yy := 0 to Listbox1.Items.Count - 1 do Listbox1.Items.Add ( copy (Listbox1.Items [yy], 39, 3)); //Prozent |
keinen Sinn, da du die werte ja wieder in die gleiche Listbox hinzufügst :P
Mfg Frank
Friedhelm - Di 03.12.02 19:54
Hallo Frank,
ja,das war nicht gut. Aber
Quelltext
1:
| ( copy (Listbox1.Items [yy], 39, 3)); |
kann ich doch einer Variablen zuordnen. z.B. "P" und diese dann
hier einsetzen.
Quelltext
1:
| arect.right:=round(strtoint(items[index])* P ?? // |
Das müsste doch laufen. Oder?
Danke für den Tip
Gruss Friedhelm
(04.12. 08:40 Tino) Code-Tags hinzugefügt.
Keldorn - Di 03.12.02 22:21
Hallo
Zitat: |
Das müsste doch laufen. Oder? |
nö. Allerdings sehe ich jetzt auch keinen Sinn, dir direkt zu sagen wie es richtig wäre, zumal die antwort in meinem letztem Posting steht. Außerdem soll es ja dein Programm werden und nicht meins.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| //den Balken zeichnen arect:=rect; arect.Left:=Startposx; arect.right:=round(strtoint(items[index])* // 1) (rect.right-startposx)/100)+startposx; if odSelected in State then canvas.brush.color:=clgray else canvas.brush.color:=clltgray; Canvas.fillrect(arect); |
Beschreib mir mal, wie das mit dem Balken zeichnen genau funktioniert und dann sehen wir weiter
Mfg Frank
Friedhelm - Mi 04.12.02 10:28
Hallo Frank
klar, ich muss selbst überlegen. Aber es liegt , denke ich , ein MIssverständnis vor. Denn meine Items sind fortlaufend so:
021231-A345-P035
021223-A543-P075
usw
viele Items und immer soll die Prozentziffer angezeigt werden. Darum verstehe ich nicht warum
Quelltext
1: 2: 3:
| for yy := 0 to Listbox1.Items.Count - 1 do Listbox1.Items.Add ( copy (Listbox1.Items [yy], 14, 3)); //Prozent |
keinen Sinn machen soll? Ich nehme doch die Stelle 14,3 und kopiere die Ziffer, berechne sie und gehe zum nächsten Eintrag. Müssen denn nicht alle Items nacheinander angesprochen werden?
Gruss
FRiedhelm
(04.12. 10:33 Tino) Code-Tags hinzugefügt.
Keldorn - Mi 04.12.02 10:55
Hallo Friedhelm,
das macht keinen Sinn, weil Du die Items zur gleichen Listbox hinzufügst.
also steht dann in der Listbox
Zitat: |
021231-A345-P035
021223-A543-P075
035
075
|
das Drawitem-Ereignis wird ausgelöst, wenn
ein Eintrag neugezeichnet werden muß. das wird unweigerlich zu einer Exception führen, da strtoint('021231-A345-P035 ') nicht geht.
Da ich ja vorher nicht wußte, was für Einträge deine Listbox enthält bin ich nur von Zahlen (als String) ausgegangen. Dieser String wird mit strtoint(items[index]) wieder zu ner Zahl gewandelt mit der dann die Balkenlänge errechnet wird.
und jetzt frage ich dich, wenn in meinem Code beim OnDrawitem items[index] die Zahl (also die Prozentzahl) darstellt, wie es in deinem Code aussehen soll.
Meine Frage haste mir auch noch nich beantwortet :?
Mfg Frank
Friedhelm - Mi 04.12.02 11:10
Hallo FRank,
mit dem Kopieren ist mir jetzt klar. War Blödsinn. Will ja nicht die kopierten Teile wieder in die Listbox einsetzen.
NUn zu deiner Frage, das meisnt du doch?
"Beschreib mir mal, wie das mit dem Balken zeichnen genau funktioniert und dann sehen wir weiter "
meinst du damit, wie es funktionieren soll - , oder was der Code
Quelltext
1: 2: 3: 4: 5:
| //den Balken zeichnen arect:=rect; arect.Left:=Startposx; arect.right:=round(strtoint(items[index])* (rect.right-startposx)/100)+startposx; |
aussagt?
Gruss
Friedhelm
(04.12. 10:34 Tino) Code-Tags hinzugefügt.
Keldorn - Mi 04.12.02 11:18
Hallo,
Zitat: |
meinst du damit, wie es funktionieren soll
|
genau, weil ich den Eindruck habe, das Du nicht richtig verstanden hast, was dort genau passiert - sonst hättest Du nicht *P und die Probleme mit dem rauskopieren etc. geschrieben.
Frank
Friedhelm - Mi 04.12.02 12:06
Hallo Frank,
1. Startposx wird festgelegt wo der Balken anfangen soll (x-Achse)
2. arect.right:=round(strtoint(items[index])* rechteck zeichnen,
3. (rect.right-startposx)/100)+startposx;
Item/Index die zahl, die in der Listbox steht.
4. damit habe ich aber nicht - wie in meinem Falle - den Teilstring verarbeitet?
Ich rechne doch einzig und allein mit den Werten, die in der Listbox stehen(wenn es nur ZAHLEN sind) UNd dass´ist in meiner ListBox ja nicht der Fall.
Mit nur Zahlen funzt es.
Eigentlich geht es mir jetzt darum, den Teilstring(Item), nämlich die 035, 075 usw als Balken hinter dem jeweiligen Eintrag zu stellen, wobei alle Einträge der LB in voler Länge bestehenbleiben.
Sehe ich die LÖsung nicht, oder ist sie so simpel??? :oops:
Gruss
Friedhelm
Keldorn - Mi 04.12.02 12:44
*aufgeb*
das arect ist das "Rechteck" des Balkens
arect.left die linke anfangsposition
arect.right dir rechte. die setzt sich zusammen aus:
rect.right-startposx ist die maximal mögliche Länge des Balkens in Pixel (also für den angenommenen max Wert 100)
rect.right ist die Breite des zu zeichnenden Items und damit auch der Listbox. Dadurch ist der Code flexibel und Größenänderungen der Listbox führen immer zum gleichen relativen Ergebnis
der Rest ist ein simpler Dreisatz:
maximale Balkenlännge = 100
meine Balkenlänge = mein Wert
daraus ergibt sich
mein wert * maximale Balkenlänge
meine Balkenlänge = ---------------------------------
100
mein Wert ist der Prozentsatz oder was auch immer. In meinem Beispiel strtoint(items[index])
und für den deinen Code : strtoint(copy (Items [index], 14, 3)).
du mußt den Prozentsatz dort rauskopieren .... so schwer?
um sicher zu sein,
Quelltext
1: 2: 3: 4: 5: 6: 7:
| s:=copy (Items [index], 14, 3); try wert:=strtoint(s) except wert:=0; end; arect.right:=round(Wert*(rect.right-startposx)/100)+startposx; |
is jetz nur so hier reingeklimpert, geht bestimmt noch eleganter. Sinn ist, das copy(...) trotzdem noch einen String enthaltenn könnte,
der nicht in eine Zahl gewandelt wrden kann. Damit kommst du evtl in eine Endloschleife, da erst eine Exception ausgelöste wird, evtl der Listboxeintrag neu gezeichnet wird und damit wieder eine Exception ausgelöst usw.
jetzt klar ?
Mfg Frank
Friedhelm - Mi 04.12.02 14:21
Hallo Frank,
danke für deine Mühe. Wenn ich das so lese habe ich es verstanden.
Bei mir hat z.B. beim Kopieren immer ein Komma gefehlt. :oops:
So kam ich nicht weiter.
Danke nochmal. :beer:
Gruss
Friedhelm
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!