Reputation: 2516
I am making a table with JavaFX. Every row has text. One row has a graphic because the text of that cell has multiple colors.
The code only applies when a certain condition is true (that part works):
departTimeCol.setCellFactory(column -> new TableCell<Ride, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(item);
if(item != null && ! empty){
if(item.matches("^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]\\s\\+[\\d]")) {
Text timeText = new Text(item.split(" ")[0].trim() + " ");
Text delayText = new Text(item.split(" ")[1].trim());
delayText.setFill(Color.RED);
TextFlow flow = new TextFlow(timeText, delayText);
setText(null);
setGraphic(flow);
}
}
}
});
The result is:
The row with the red +2 is the graphic. All the other rows contain text. How can I give the row - containing a graphic - the same height?
Upvotes: 0
Views: 76
Reputation: 82451
Simply set the prefered height to 0
to make the height just what is needed to store the text.
Pattern pattern = Pattern.compile("((?:[0-9]|[01][0-9]|2[0-3]):[0-5][0-9]\\s)(\\+\\d)");
departTimeCol.setCellFactory(column -> new TableCell<Ride, String>() {
private final Text timeText = new Text();
private final Text delayText = new Text();
private final TextFlow flow = new TextFlow(timeText, delayText);
{
delayText.setFill(Color.RED);
flow.setPrefHeight(0);
flow.heightProperty().addListener((observable, oldValue, newValue) -> {
this.setMinHeight(newValue.doubleValue() + 4);
});
flow.setMinHeight(Region.USE_COMPUTED_SIZE);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(flow);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
timeText.setText("");
delayText.setText("");
delayText.setVisible(false);
} else {
Matcher m = pattern.matcher(item);
if (m.matches()) {
timeText.setText(m.group(1));
delayText.setText(m.group(2));
delayText.setVisible(true);
} else {
timeText.setText(item);
delayText.setText("");
delayText.setVisible(false);
}
}
}
});
Note that there are a few more things in the code that should be fixed:
null
, even if the String
no longer matches the regex or if the cell becomes empty. This means you can get the TableCell
into a state where the text
property is not empty and the graphic
contains a TextFlow
. Note: Always make sure the state of the look of a cell is correct no matter how often the updateItem
method is called and independent of the arguments passed.graphic
+ a TextFlow
for one case and the text
property for another. (Just take a look at the leftmost part of the text in your screenshot! Those are not properly aligned).Cell
s is reusing the node to prevent unnecessary creation of nodes. You kind of ruin this attempt by recreating the TextFlow
, ect. in the updateItem
method instead of reusing those nodes.The regex needs not start with ^
since matches
already makes sure the whole input is matched. Furthermore the delimiter used for split
does not have an exact equivalent in the regex. There are other space chars than , such as tab. Just check what the following code does...
System.out.println("a\tb".matches(".\\s."));
System.out.println("a\tb".split(" ")[1]);
You can also parse the input and match it in the same step by using Pattern
+Matcher
and capturing groups. This way you also do not have the issue mentioned above.
Upvotes: 1