In a quite complex javafx application I faced a possible rendering bug. The last two days I could track it down to the following simple application. The following SSCCE demonstrates that in certain circumstances some javafx components are not correctly rendered. As a result, ComboBox and ListView do not show changed content:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ComboManagedBug extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
// add combo box
ComboBox<String> combo = new ComboBox<>();
combo.setPromptText("Choose a value...");
combo.getItems().setAll("1", "2", "3");
// add list view
ListView<Label> list = new ListView<>();
// add "add" button
Button add = new Button("Add");
add.setOnAction(e -> list.getItems().add(
new Label(combo.getSelectionModel().getSelectedItem())));
// add tab pane
Tab tab1 = new Tab("First", new VBox(combo, add, list));
Tab tab2 = new Tab("Second");
TabPane tabs = new TabPane(tab1, tab2);
tabs.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); // important!
// add "next" and "cancel" buttons at bottom
Button next = new Button("Next");
Button cancel = new Button("Cancel (Triggers refresh)");
HBox buttons = new HBox(next, cancel);
// install tab listener
tabs.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> {
// intention is to show next button only on first tab
boolean firstTab = c == tab1;
next.setVisible(firstTab);
next.setManaged(firstTab); // important!
});
// show
VBox root = new VBox(new VBox(tabs, buttons)); // important!
Scene scene = new Scene(root, 400, 400);
primaryStage.setTitle("ComboBox/ListView Rendering Bug Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Steps to reproduce:
- Launch program
- Choose combo value -> ComboBox shows chosen value -> OK
- Click "Add" -> value gets added to the ListView and is shown -> OK
- Activate second tab
- Activate first tab
- Choose a combo value being different than the previous one -> value in ComboBox does not change -> BUG
- Click "Add" -> ListView content does not change -> BUG
- Click "Cancel" at the bottom -> although there was no listener added to this button, both the ComboBox and the ListView show the correct values now. So, both containers seem to contain the correct values but they won't be rendered correctly until some UI refreshing is triggered.
Note that there are three important reqiurements to reproduce this bug (marked with "important"):
- Toggle managed state of the "Next" button when toggling the tabs to hide this button (usual way to hide a node along with visible state of the node, see JavaFX - setVisible doesn't "hide" the element)
- TabClosingPolicy.UNAVAILABLE (a very common case)
- a VBox in a VBox (which can easily happen in real life when nesting different javafx component nodes).
Is this bug already known, and does anybody know a workaround for this? I tried Platform.runLater(cancel.fire()) and similar things but without success.
Thank you for any hints, Peter.
Btw., apart from this, our company uses javafx for some years now. In our experience, it is very reliable and programming javafx is fun. I hope there is a simple solution for our problem :)