JavaFX ListCell höhe verändert sich beim ändern der Text-Farbe

sascha-sphw

Top Contributor
Ich habe gerade eine Entdeckung gemacht und kann mir das Verhalten leider überhaupt nicht erklären.

Ich habe eine Liste mit eigenem ListCell, der Text wird mit CSS rot eingefärbt wenn man in der Combobox "Colored" auswählt.
1595953013261.png
Wenn man genau aufpasst, sieht man wie sich die Zeilenhöhe auf einmal verringert.
1595953022266.png
Wenn man nun "Not Colored" auswählt wird der Text Style gelöscht, aber die Zeilenhöhe bleibt unverändert.
1595953036124.png
Wenn man nun wieder auf "Colored" schaltet und anschließend die Combobox mit ctrl click deselectiert, wird die Zeilenhöhe wieder vergrößert, obwohl doch genau der gleiche Code zum löschen des Styles ausgeführt wird.
1595953043561.png

Würde mich freuen wenn der eine oder andere mal drüber schauen kann und mit mir diskutiert, wie diese Verhalten zu erklären ist.

Hier gehts zum Source.
 

mihe7

Top Contributor
Ich würde mal vermuten (kenne mich mit FX nicht aus), dass setStyle(null) die Standardeinstellungen wiederherstellt. Was passiert denn, wenn Du z. B. node.setStyle("-fx-fill: black; -fx-text-fill: black;") verwendest?
 

sascha-sphw

Top Contributor
Ich würde mal vermuten (kenne mich mit FX nicht aus), dass setStyle(null) die Standardeinstellungen wiederherstellt.

Jap, aber wo ist der Unterschied zwischen dem setStyle(null); wenn ich auf "Not Colored" stelle und dem setStyle(null); wenn ich "Colored" deselektiere. Und wo kommt der Höhenunterschied her, font size bleibt ja unverändert.

Was passiert denn, wenn Du z. B. node.setStyle("-fx-fill: black; -fx-text-fill: black;") verwendest?
Interessanterweise, das gleiche wie bei setStyle(null); also die Zeile verändert die Höhe.
 

mihe7

Top Contributor
Das wird ja immer besser. Könnte mit der Font-Engine zusammenhängen. Ich weiß nicht, was da aktuell ist, vor ein paar Jahren habe ich mal was bauen müssen, wo die Metrics eine entscheidende Rolle spielten. Da gab es dann derart massive Unterschiede zwischen Windows und Linux, dass das in der Form nicht brauchbar war.
 

sascha-sphw

Top Contributor
Ich habe jetzt mal ein ContextMenu eingebaut, das mir die Größen der einzelnen Nodes ausgibt. Folgendes konnte ich beobachten.

Deselektiert:
Code:
message childs:
child 'Text[text="This it the line number 0", x=0.0, y=0.0, alignment=LEFT, origin=BASELINE, boundsType=LOGICAL, font=Font[name=Consolas, family=Consolas, style=Regular, size=13.0], fontSmoothingType=GRAY, fill=0x000000ff]' -> pref w/h: 178,69/13,00
message -> w/h: 455,00/17,00, pref w/h: 179,00/13,00
rootNode -> w/h: 455,00/17,00, pref w/h: 179,00/13,00

Colored:
Code:
message childs:
child 'Text[text="This it the line number 0", x=0.0, y=0.0, alignment=LEFT, origin=BASELINE, boundsType=LOGICAL, font=Font[name=Consolas, family=Consolas, style=Regular, size=13.0], fontSmoothingType=GRAY, fill=0xff0000ff]' -> pref w/h: 178,69/13,00
message -> w/h: 455,00/16,00, pref w/h: 179,00/13,00
rootNode -> w/h: 455,00/16,00, pref w/h: 179,00/13,00

Es schein für mich so, als dass der Text seine Höhe nicht verändert, aber der Container (HBox) dennoch meint er müsse seine Höhe anpassen.
 

dzim

Top Contributor
War in den Ferien... Sorry. :)

Also Style ist schon etwas speziell und ich versuche die Verwendung davon so oft wie möglich zu vermeiden. Allein weil es auch schlecht zu warten ist.
Meine Alternative ist, wenn möglich, das Verwenden von Pseudo-Klassen (würde in dem konkreten Use-Case auch mehr Sinn ergebe aus meiner Sicht).

Aber zum Problem. Den Style auf Null setzen ist eine schlechte Idee. Ich glaube ich bin vor langer Zeit auch mal drüber gestolpert. Entweder ein leerer String, oder explizit die alternativen Werte verwenden. Null macht irgendetwas komisches, was vermutlich so nicht gewollt ist und was auch dem "default"-Wert entspricht - dieser ist IMHO "" (also ein leerer String).
Warum es sich genau so verhält... Keine Ahnung, aber CSS in JavaFX ist schon etwas... speziell. Sagen wir's mal so.
Ich denke auch, es wäre einen Bug-Report wert, aber solange würde ich einfach auf etwas "saubere" Methoden, wie Pseudo-Klassen oder immer explizites setzen aller gewünschten Styles (in allen Fällen, also Default, Deselektiert und Colored), setzen.

Und wenn du noch etwas mehr Untersuchen möchtest sind zwei Projekte empfehlenswert: CSSFX (https://github.com/McFoggy/cssfx) und Scenic View (https://github.com/JonathanGiles/scenic-view). Letzteres vor allem, weil du damit deine CSS-Klassen, -Pseudo-Klassen und -Styles live untersuchen kannst. Und eigentlich auch alle anderen Properties, wie Pref/Min/Max-Height aber auch reale Höhe, etc. Sehr nützliches Tool, hat mir schon sehr oft geholfen, wenn ich knifflige Style-Anpassungen gemacht habe (hallo Table- und ListView! Argh! 💩).
 

sascha-sphw

Top Contributor
War in den Ferien... Sorry. :)
Kein Thema. Antworten ist ja keine Pflicht. :)

Aber zum Problem. Den Style auf Null setzen ist eine schlechte Idee. Ich glaube ich bin vor langer Zeit auch mal drüber gestolpert. Entweder ein leerer String, oder explizit die alternativen Werte verwenden. Null macht irgendetwas komisches, was vermutlich so nicht gewollt ist und was auch dem "default"-Wert entspricht - dieser ist IMHO "" (also ein leerer String).
Habe ich auch versucht. Egal ob setStyle(null), setStyle("") oder setStyle("-fx-fill: black; -fx-text-fill: black;"), das Ergebnis war, zumindest bei mir, exakt das Gleiche. Aber der Punkt ist ja der, wenn Du auf "Not Colored" stellst, läuft ja der selbe code der auch beim Deselektieren durchlaufen wird, dennoch ist das Ergebnis eine Veränderung der Höhe.
Es scheint (für mich) auch weniger mit dem Styling an sich zu tun zu haben, da sich die Höhe der Text Node ja nicht verändert.

Meine Alternative ist, wenn möglich, das Verwenden von Pseudo-Klassen (würde in dem konkreten Use-Case auch mehr Sinn ergebe aus meiner Sicht).
Ich verstehe nicht ganz wie Du das meinst, hast Du ein Beispiel hierfür? Wir reden schon über das gleiche (https://developer.mozilla.org/de/docs/Web/CSS/Pseudo-classes), oder?

Das Projekt ist auch nur ein minimal Beispiel um das Problem zu fokussieren. Im echten Projekt (https://www.softpagehomeware.de/products/logviewer), kann der User die Farben (Text/Background) selbst über die UI festlegen.

Ich habe dann auch noch ein wenig weiter rum probiert um zu sehen ob das Verhalten ohne ListCell (also nur HBox -> Text), auch zu beobachten ist. Ist es aber nicht, hier funktioniert alles wie erwartet.

Mein aktueller Workaround ist, die prefHeight der ListCell auf die eingestellte Schriftgröße + Padding zu setzen, funktioniert erst mal.

Einen Bug Eintrag werde ich demnächst noch machen, aber ich denke das es was mit einer fehlerhaften Berechnung der ListCell Size zu tun hat, dafür habe ich so einiges gefunden, unter anderem auch Bug Einträge.

Und wenn du noch etwas mehr Untersuchen möchtest sind zwei Projekte empfehlenswert: CSSFX (https://github.com/McFoggy/cssfx) und Scenic View (https://github.com/JonathanGiles/scenic-view). Letzteres vor allem, weil du damit deine CSS-Klassen, -Pseudo-Klassen und -Styles live untersuchen kannst. Und eigentlich auch alle anderen Properties, wie Pref/Min/Max-Height aber auch reale Höhe, etc. Sehr nützliches Tool, hat mir schon sehr oft geholfen, wenn ich knifflige Style-Anpassungen gemacht habe (hallo Table- und ListView! Argh! 💩).
Werde ich mal ausprobieren. Danke für die Links!
 

dzim

Top Contributor
Habe ich auch versucht. Egal ob setStyle(null), setStyle("") oder setStyle("-fx-fill: black; -fx-text-fill: black;"), das Ergebnis war, zumindest bei mir, exakt das Gleiche. Aber der Punkt ist ja der, wenn Du auf "Not Colored" stellst, läuft ja der selbe code der auch beim Deselektieren durchlaufen wird, dennoch ist das Ergebnis eine Veränderung der Höhe.
Es scheint (für mich) auch weniger mit dem Styling an sich zu tun zu haben, da sich die Höhe der Text Node ja nicht verändert.
Doch doch, das ist schon vom Styling abhängig! Das null setzen, bzw. das allgmeine Manipulieren des Styles hat Auswirkungen und du triggerst deine applyStyle Methode ja auf öfter.

Aber mal kurz zu deinem Code:
Java:
    @Override
    protected void updateItem(ListItemModel item, boolean empty) {
        super.updateItem(item, empty);
        setText(null); // use ""
        message.getChildren().clear();
        // this::applyStyle creates a new lambda each time
        // create a variable like so: private InvalidationListener listener = this::applyStyle;
        // add and remove this listener instead of this:applyStyle
        selectedGroup.removeListener(this::applyStyle);
        if (empty || item == null) {
            // clean up here instead of always? at least reset the style here as well!
            return;
        }
        selectedGroup.addListener(this::applyStyle);
        message.getChildren().add(new Text(item.text));
        applyStyle(null);
    }
Auch wenn der Code nur eine Demo ist (finde aber gut, dass du das gemacht hast!), ist hier noch Verbessungspotential vorhanden. ;)

Ich verstehe nicht ganz wie Du das meinst, hast Du ein Beispiel hierfür? Wir reden schon über das gleiche (https://developer.mozilla.org/de/docs/Web/CSS/Pseudo-classes), oder?
Ja genau.

Veraltet: Siehe z.B. hier https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/apply-css.htm und hier https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html.

JavaFX 14:
Im Prinzip ist es dann so, dass du dann so eine Pseudo-Klasse wie in den Beispielen "anlegst" und dann auf den Controls immer nur "true" oder "false" für aktiv/inaktiv setzen musst. Ist, wenn man es einmal verwendet hat, recht einfach.

Mein aktueller Workaround ist, die prefHeight der ListCell auf die eingestellte Schriftgröße + Padding zu setzen, funktioniert erst mal.
Ich bin mir nicht mehr ganz sicher, aber ich glaube bei mir waren solche Workarounds auch ab und an nötig...
 

sascha-sphw

Top Contributor
Auch wenn der Code nur eine Demo ist (finde aber gut, dass du das gemacht hast!), ist hier noch Verbessungspotential vorhanden.
Make It Work Make It Right Make It Fast. 😉

Ja genau.

Veraltet: Siehe z.B. hier https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/apply-css.htm und hier https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html.

JavaFX 14:
Im Prinzip ist es dann so, dass du dann so eine Pseudo-Klasse wie in den Beispielen "anlegst" und dann auf den Controls immer nur "true" oder "false" für aktiv/inaktiv setzen musst. Ist, wenn man es einmal verwendet hat, recht einfach.
Werde ich mir mal genauer anschauen. Danke nochmal an dieser Stelle!
 

sascha-sphw

Top Contributor
Nachdem ich ein neues Feature (Word Wrap) in meinen LogViewer eingebaut habe, musste ich mich nochmal etwas intensiver mit diesem Thema beschäftigen und konnte es lösen, indem ich die Höhe einfach selbst berechne, dazu habe ich einfach die folgenden beiden Methoden überschrieben.
Java:
@Override
protected double computeMinWidth(double height) {
    return message.minWidth(height) + message.getInsets().getTop() + message.getInsets().getBottom();
}

@Override
protected double computePrefHeight(double width) {
    return message.prefHeight(width) + message.getInsets().getTop() + message.getInsets().getBottom();
}

Falls es jemand brauchen kann. Der Source liegt jetzt auf Bitbucket.
 

sascha-sphw

Top Contributor
Nachdem ich ein neues Feature (Word Wrap) in meinen LogViewer eingebaut habe, musste ich mich nochmal etwas intensiver mit diesem Thema beschäftigen und konnte es lösen, indem ich die Höhe einfach selbst berechne, dazu habe ich einfach die folgenden beiden Methoden überschrieben.
Java:
@Override
protected double computeMinWidth(double height) {
    return message.minWidth(height) + message.getInsets().getTop() + message.getInsets().getBottom();
}

@Override
protected double computePrefHeight(double width) {
    return message.prefHeight(width) + message.getInsets().getTop() + message.getInsets().getBottom();
}

Falls es jemand brauchen kann. Der Source liegt jetzt auf Bitbucket.
Es sollte computeMinHeight sein nicht computeMinWidth... :eek:
Java:
@Override
protected double computeMinHeight(double width) {
    return message.minHeight(width) + message.getInsets().getTop() + message.getInsets().getBottom();
}

@Override
protected double computePrefHeight(double width) {
    return message.prefHeight(width) + message.getInsets().getTop() + message.getInsets().getBottom();
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
@SupressWarnings() JavaFX Auf den Controller einer ListCell zugreifen AWT, Swing, JavaFX & SWT 4
L JavaFX ListCell Performance AWT, Swing, JavaFX & SWT 10
J JavaFX Eigene ListCell Problem(Objekte werden doppelt angezeigt) AWT, Swing, JavaFX & SWT 1
L Swing TextPanel Schrift untereinander und auf einer Höhe AWT, Swing, JavaFX & SWT 3
Jose05 Javafx Label Höhe=Breite AWT, Swing, JavaFX & SWT 1
X JavaFX AreaChart area höhe wird nicht richtig dargestellt AWT, Swing, JavaFX & SWT 2
R Java FX - Fxml - relative Größenangaben für Breite und Höhe einer TextArea AWT, Swing, JavaFX & SWT 8
J JavaFX TableView - Höhe der Zeilen AWT, Swing, JavaFX & SWT 3
B JFreeChart Gantt Höhe Tasks AWT, Swing, JavaFX & SWT 1
Z Java Draw -JFrame finde nicht die Mitte & höhe, breite AWT, Swing, JavaFX & SWT 7
S SWT TableCell mit Composite als Inhalt / Höhe der Cell/Row AWT, Swing, JavaFX & SWT 5
T Swing JScrollPane in JPanel - Breite dynamisch, Höhe fix - wie? AWT, Swing, JavaFX & SWT 2
A LayoutManager Höhe von NORTH beim BorderLayout ändern AWT, Swing, JavaFX & SWT 4
M Wie ermittele ich die Breite und Höhe meines Displays in Pixel AWT, Swing, JavaFX & SWT 3
T LayoutManager GridBagLayout - zwei jTable mit unterschiedlicher Höhe AWT, Swing, JavaFX & SWT 2
N Swing Optimale Höhe eine JTextPanes bei festgelegter Breite bestimmen AWT, Swing, JavaFX & SWT 23
P Höhe der TitleBar vom JFrame AWT, Swing, JavaFX & SWT 2
Landei Swing JToolbar: Textfelder mit normaler Höhe? AWT, Swing, JavaFX & SWT 2
T jpanel höhe netbeans.... AWT, Swing, JavaFX & SWT 5
J Problem mit der Höhe eines Panels AWT, Swing, JavaFX & SWT 11
G Swing Höhe des View eines JScrollPane fest auf Höhe des JScrollPane setzen! AWT, Swing, JavaFX & SWT 4
H LayoutManager Auf gleicher Höhe anordnen AWT, Swing, JavaFX & SWT 4
_dp jTextArea/jTextPanel Auto Höhe AWT, Swing, JavaFX & SWT 5
D JPanel höhe setzen AWT, Swing, JavaFX & SWT 2
H variable Höhe einer JTextArea (als Renderer/Editor) als Zelle einer JTable AWT, Swing, JavaFX & SWT 9
F Swing Höhe eines Headers einer JTable anpassen AWT, Swing, JavaFX & SWT 4
N Höhe einstellen JScrollPane AWT, Swing, JavaFX & SWT 3
F 2D-Grafik Problem mit höhe||breite eines JFrames AWT, Swing, JavaFX & SWT 4
G JTable Multiple Row Header Example - Probleme mit der Höhe der Zellen AWT, Swing, JavaFX & SWT 4
E Wie Breite und Höhe eines Panels festlegen? AWT, Swing, JavaFX & SWT 5
S Für Breite und Höhe werden 0.0 angezeigt AWT, Swing, JavaFX & SWT 2
C Swing JTextArea mit fester Breite und angepasster Höhe??? AWT, Swing, JavaFX & SWT 8
B Höhe eines Buttons festlegen AWT, Swing, JavaFX & SWT 7
G JList Höhe? AWT, Swing, JavaFX & SWT 2
P Breite und Höhe des contentPane abfragen AWT, Swing, JavaFX & SWT 3
Y Einzigartigkeit des GridBagLayout - individuelle Höhe/Breite AWT, Swing, JavaFX & SWT 4
S Tabelle soll sich auch in der Höhe resizen? AWT, Swing, JavaFX & SWT 4
T Breite des Containers ist gegeben - wie die Höhe berechnen? AWT, Swing, JavaFX & SWT 3
H JTabbedPane Höhe-Problem AWT, Swing, JavaFX & SWT 3
S [BorderLayout]WEST/EAST sollen über ganze Höhe gehen; AWT, Swing, JavaFX & SWT 3
G Linie nach Höhe einer Zahl zeichnen? AWT, Swing, JavaFX & SWT 3
A JTextFiled-Breite und Höhe ändern AWT, Swing, JavaFX & SWT 3
S Feste Breite und Höhe für einen formatierten Text. AWT, Swing, JavaFX & SWT 5
G Höhe eines JPanels ermittlen AWT, Swing, JavaFX & SWT 3
S JFrame Fenster höhe der Titelzeile? AWT, Swing, JavaFX & SWT 13
G Klasse Image - Höhe und Breite ermitteln AWT, Swing, JavaFX & SWT 12
B BorderLayout.WEST (JTree strecken in Höhe) AWT, Swing, JavaFX & SWT 2
D Jtable Header Höhe setzen ? AWT, Swing, JavaFX & SWT 2
B JEditorPane: Höhe für bestimmte Breite bestimmen AWT, Swing, JavaFX & SWT 4
M Höhe von eines Strings in Pixeln (nicht Höhe einer Zeile) AWT, Swing, JavaFX & SWT 12
K Höhe und Breite eines Panels im GridBagLayout ermitteln AWT, Swing, JavaFX & SWT 9
javasdann Höhe von Titlebar in jInternalFrame ändern AWT, Swing, JavaFX & SWT 5
J DefaultTableCellRenderer & Höhe AWT, Swing, JavaFX & SWT 3
D JLabel mit fester Breite und beliebiger Höhe AWT, Swing, JavaFX & SWT 4
O warum ist die Höhe meines JPanels 0? AWT, Swing, JavaFX & SWT 8
L wie kann man die Höhe und Breite von JList festlegen AWT, Swing, JavaFX & SWT 3
C Titel-Balken höhe?! AWT, Swing, JavaFX & SWT 4
C Höhe der Titelleiste in JInternalFrame AWT, Swing, JavaFX & SWT 4
P JTextField wird nur sehr klein angezeigt und verändert die Größe nicht AWT, Swing, JavaFX & SWT 3
M Wieso verändert sich die Framerate nach erneutem Starten des AnimationTimer? AWT, Swing, JavaFX & SWT 18
K GridBagLayout verändert die größe? AWT, Swing, JavaFX & SWT 1
C SWT Treeview mit Bilder im Label verändert Expanded Icon AWT, Swing, JavaFX & SWT 1
J ComboBoxModel addElement verändert Layout AWT, Swing, JavaFX & SWT 8
X mouseover verändert ungewollt die farbe AWT, Swing, JavaFX & SWT 4
S g.setStroke verändert auch Buttonrahmen AWT, Swing, JavaFX & SWT 2
R JPanel-Größe verändert sich nicht. Warum? AWT, Swing, JavaFX & SWT 5
S Button (ActionListener) funktioniert nicht, wenn y-Koordinate verändert wird AWT, Swing, JavaFX & SWT 5
N Methode zum Prüfen ob Jtextfield verändert worden ist AWT, Swing, JavaFX & SWT 2
R Fensterinhalt erscheint erst, wenn das Fenster verändert wird AWT, Swing, JavaFX & SWT 7
N Button akivieren, wenn Tabelle verändert worden ist AWT, Swing, JavaFX & SWT 2
S JScrollpane verändert sich? AWT, Swing, JavaFX & SWT 5
J Menü beschriftung wird nicht verändert AWT, Swing, JavaFX & SWT 7
V JTable - SelectionMode wird durch RowFilter verändert AWT, Swing, JavaFX & SWT 2
R LayoutManager GridLayout verändert isch andauernd AWT, Swing, JavaFX & SWT 4
hdi SWT Shell: Auslagerung von Code verändert Verhalten AWT, Swing, JavaFX & SWT 6
O JSlider - wie unterscheide ich mit Maus verändert und durch setValue verändert. AWT, Swing, JavaFX & SWT 16
J JComboBox verändert Größe sobald editierbar AWT, Swing, JavaFX & SWT 2
L GridLayout verändert festgesetzte Größe der Komponenten AWT, Swing, JavaFX & SWT 12
N Die Zeile einer JTable verändert beim klicken ihre Farbe? AWT, Swing, JavaFX & SWT 7
K Fenstergröße soll nicht verändert werden AWT, Swing, JavaFX & SWT 2
V JComboBox-Größe verändert sich im GridBagLayout AWT, Swing, JavaFX & SWT 4

Ähnliche Java Themen

Neue Themen


Oben