<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"Times New Roman \(Body CS\)";
panose-1:2 11 6 4 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}
span.EmailStyle18
{mso-style-type:personal-reply;
font-family:"Courier New";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">Scott, can you try styling these nodes via the scene stylesheet (Scene.getStylesheets())?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <openjfx-dev-retn@openjdk.org> on behalf of Scott Palmer <swpalmer@gmail.com><br>
<b>Date: </b>Monday, February 20, 2023 at 11:59<br>
<b>To: </b>openjfx-dev <openjfx-dev@openjdk.org><br>
<b>Subject: </b>CSS styling of Shape in TextFlow causes flickering<o:p></o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">I'm seeing an odd issue with using CSS to colour a Shape when I have it as a child of a TextFlow.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">My use case is a "rich" text Cell in a tree or list. I want to have the text portion in multiple colours and so instead of using the graphic and text parts of a typical Cell,
I'm using only the Graphic and setting it to a TextFlow to get the text colours. This means that I lose the ability to set a graphic independen to the text, and so the graphic is also added to the TextFlow.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">To style the graphics, which are made of simple shapes, I'm using CSS. It makes it easy to adapt the colours for when a cell is selected etc. What I've noticed is that as the
cell selection moves around the Shape component of the TextFlow flickers, as if it is drawn first using default colours and then the CSS is applied afterward. I tried working around this by explicitly calling applyCss() on the Shape from the Cell's update
method, but it did not help. If I explicitly set the Stroke and Fill via the Shape API the flickering does not occur. If I use CSS, but set the Shape as the Cell's graphic and resort to only having plain text, there is no flickering.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">A test program that demonstrates this is below.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">Bug or known limitation?<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">Scott<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">------------------------------------<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif">package bugs;<br>
<br>
import javafx.application.Application;<br>
import javafx.geometry.Insets;<br>
import javafx.scene.Node;<br>
import javafx.scene.Scene;<br>
import javafx.scene.control.CheckBox;<br>
import javafx.scene.control.ContentDisplay;<br>
import javafx.scene.control.Label;<br>
import javafx.scene.control.ListCell;<br>
import javafx.scene.control.ListView;<br>
import javafx.scene.control.Tab;<br>
import javafx.scene.control.TabPane;<br>
import javafx.scene.layout.HBox;<br>
import javafx.scene.layout.VBox;<br>
import javafx.scene.paint.Color;<br>
import javafx.scene.shape.Circle;<br>
import javafx.scene.shape.Rectangle;<br>
import javafx.scene.shape.Shape;<br>
import javafx.scene.text.Text;<br>
import javafx.scene.text.TextFlow;<br>
import javafx.stage.Stage;<br>
<br>
<br>
public class CSSFlickerInTextFlow extends Application {<br>
<br>
public static void main(String[] args) {<br>
launch(args);<br>
}<br>
<br>
private CheckBox onlyCssCB;<br>
<br>
@Override<br>
public void start(Stage stage) throws Exception {<br>
ListView<String> list1 = new ListView<>();<br>
ListView<String> list2 = new ListView<>();<br>
var items1 = list1.getItems();<br>
var items2 = list2.getItems();<br>
for (int i = 1; i < 23; i++) {<br>
var x = "Item #"+i;<br>
items1.add(x);<br>
items2.add(x);<br>
}<br>
list1.setCellFactory(t -> new MyCell1());<br>
list2.setCellFactory(t -> new MyCell2());<br>
<br>
onlyCssCB = new CheckBox("Use only CSS (shapes will flicker in TextFlow)");<br>
HBox buttons = new HBox(8, onlyCssCB);<br>
buttons.setPadding(new Insets(4));<br>
<br>
Tab custom = new Tab("Everything in Graphic", list1);<br>
Tab withoutColoredText = new Tab("Graphic + Text", list2);<br>
TabPane tabs = new TabPane(custom, withoutColoredText);<br>
<br>
VBox root = new VBox(<br>
new Label("""<br>
Focus in list, cursor up and down, pay attention to the circle.<br>
Try the same with the box checked - circle flickers.<br>
Doesn't happen when not using the TextFlow.<br>
"""),<br>
buttons, tabs);<br>
root.setPadding(new Insets(4));<br>
var scene = new Scene(root);<br>
stage.setScene(scene);<br>
stage.setTitle("Flickering with CSS in TextFlow");<br>
stage.show();<br>
}<br>
<br>
private Shape makeGraphic() {<br>
Shape graphic = new Circle(6);<br>
if (!onlyCssCB.isSelected()) {<br>
graphic.setFill(Color.SALMON); // CSS overrides these but causes flickering if not the same<br>
graphic.setStroke(Color.BLACK);<br>
}<br>
graphic.setStyle("-fx-fill: salmon; -fx-stroke: black;");<br>
return graphic;<br>
}<br>
<br>
class MyCell1 extends ListCell<String> {<br>
<br>
@Override<br>
protected void updateItem(String item, boolean empty) {<br>
super.updateItem(item, empty);<br>
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);<br>
setText(null);<br>
if (!empty && item != null) {<br>
TextFlow flow = new TextFlow();<br>
Shape graphic = makeGraphic();<br>
graphic.setTranslateY(2);<br>
var nodeList = flow.getChildren();<br>
Text name = new Text(item + " : ");<br>
name.setStyle("-fx-fill: -fx-text-background-color;");<br>
Text extra = new Text("with Color");<br>
extra.setStyle("-fx-fill:ladder(-fx-background, white 49%, salmon 50%);");<br>
nodeList.add(graphic);<br>
nodeList.add(new Rectangle(4,0)); // gap<br>
nodeList.add(name);<br>
nodeList.add(extra);<br>
setGraphic(flow);<br>
} else {<br>
setGraphic(null);<br>
}<br>
}<br>
}<br>
<br>
class MyCell2 extends ListCell<String> {<br>
@Override<br>
protected void updateItem(String item, boolean empty) {<br>
super.updateItem(item, empty);<br>
if (!empty && item != null) {<br>
setGraphic(makeGraphic());<br>
setText(item);<br>
} else {<br>
setText(null);<br>
setGraphic(null);<br>
}<br>
}<br>
}<br>
}<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
</div>
</div>
</body>
</html>