FULL PRODUCT VERSION :
A DESCRIPTION OF THE PROBLEM :
If you change the content in current Tab
(add / resize Node)
The TabPane dont render this content or update its size
onle select oter tab and go triggerst the layout change
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run the test programm
add Tabs
add Content to tab
-> switch to second tab and layout is updated
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package TabPaneLayout;
import static TabPaneLayout.TabPaneLayoutMaxMain.USE_COMPUTED_SIZE;
import static TabPaneLayout.TabPaneLayoutMaxMain.USE_PREF_SIZE;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* @author sst
*/
public class TabPaneLayoutMain extends Application {
/**
* @param args
*/
public static void main(String[] args) {
launch(TabPaneLayoutMain.class, args);
}
@Override
public void start(final Stage stage) throws Exception {
final BorderPane root = new BorderPane();
final TabPane tabs = new TabPane();
tabs.minWidthProperty().addListener(new Change("minWidthProperty"));
tabs.minHeightProperty().addListener(new Change("minHeightProperty"));
tabs.prefWidthProperty().addListener(new Change("prefWidthProperty"));
tabs.prefHeightProperty().addListener(new Change("prefHeightProperty"));
tabs.maxWidthProperty().addListener(new Change("maxWidthProperty"));
tabs.maxHeightProperty().addListener(new Change("maxHeightProperty"));
tabs.widthProperty().addListener(new Change("widthProperty"));
tabs.heightProperty().addListener(new Change("heightProperty"));
final Button add = new Button("add");
root.setTop(add);
add.setOnAction((event) -> tabs.getTabs().add(new AddTab()));
final ScrollPane pane = new ScrollPane();
pane.setContent(tabs);
root.setCenter(pane);
stage.setScene(new Scene(root, 400, 400));
stage.show();
}
private void tabPane(final TabPane tabs) {
for (int tab = 0; tab < 2; tab++) {
final BorderPane root = new BorderPane();
final VBox box = new VBox(4);
BorderPane.setAlignment(box, Pos.TOP_LEFT);
root.setCenter(box);
final Tab t = new Tab(String.valueOf(tab));
t.setContent(root);
tabs.getTabs().add(t);
}
}
private static final void changeTabPaneSize(final TabPane tabPane) {
final int index = tabPane.getSelectionModel().getSelectedIndex();
if (index < 0 || tabPane.getTabs().isEmpty()) {
return;
}
if (tabPane.getTabs().size() == 1) {
final Tab tab = tabPane.getTabs().remove(0);
tabPane.getTabs().add(tab);
} else if (tabPane.getTabs().size() > 1 && index == 0) {
tabPane.getSelectionModel().select(1);
} else if (tabPane.getTabs().size() > 1 && index != 0) {
tabPane.getSelectionModel().select(1);
}
tabPane.getSelectionModel().select(index);
}
private final class AddTab extends Tab {
private final int[] row;
private final GridPane grid;
private AddTab() {
super(String.valueOf(System.currentTimeMillis()));
this.row = new int[]{0};
this.grid = new GridPane();
this.grid.setMinSize(USE_PREF_SIZE, USE_PREF_SIZE);
this.grid.setPrefSize(USE_COMPUTED_SIZE, USE_COMPUTED_SIZE);
this.grid.setMaxSize(USE_PREF_SIZE, USE_PREF_SIZE);
this.grid.getColumnConstraints().add(new ColumnConstraints(USE_PREF_SIZE, USE_COMPUTED_SIZE, USE_PREF_SIZE));
final Button add = new Button("add");
add.setOnAction((event) -> add(new Label("label")));
add(add);
setContent(this.grid);
}
private final void add(final Node node) {
GridPane.setConstraints(node, 0, this.row[0]++);
this.grid.getChildren().add(node);
this.grid.getRowConstraints().add(new RowConstraints(USE_PREF_SIZE, USE_COMPUTED_SIZE, USE_PREF_SIZE));
if (getTabPane() != null) {
// changeTabPaneSize(getTabPane());
}
}
}
private final class Change implements ChangeListener<Number> {
private final String property;
/**
* @param property
*/
private Change(String property) {
super();
this.property = property;
}
@Override
public void changed(final ObservableValue<? extends Number> ov, final Number from, Number to) {
System.out.println(String.format("%s: [%s] -> [%s]", this.property, from, to));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
- select other tab and go back
- remove + add the tab (only one tab is pressent)
private static final void changeTabPaneSize(final TabPane tabPane) {
final int index = tabPane.getSelectionModel().getSelectedIndex();
if (index < 0 || tabPane.getTabs().isEmpty()) {
return;
}
if (tabPane.getTabs().size() == 1) {
final Tab tab = tabPane.getTabs().remove(0);
tabPane.getTabs().add(tab);
} else if (tabPane.getTabs().size() > 1 && index == 0) {
tabPane.getSelectionModel().select(1);
} else if (tabPane.getTabs().size() > 1 && index != 0) {
tabPane.getSelectionModel().select(1);
}
tabPane.getSelectionModel().select(index);
}
A DESCRIPTION OF THE PROBLEM :
If you change the content in current Tab
(add / resize Node)
The TabPane dont render this content or update its size
onle select oter tab and go triggerst the layout change
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run the test programm
add Tabs
add Content to tab
-> switch to second tab and layout is updated
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package TabPaneLayout;
import static TabPaneLayout.TabPaneLayoutMaxMain.USE_COMPUTED_SIZE;
import static TabPaneLayout.TabPaneLayoutMaxMain.USE_PREF_SIZE;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* @author sst
*/
public class TabPaneLayoutMain extends Application {
/**
* @param args
*/
public static void main(String[] args) {
launch(TabPaneLayoutMain.class, args);
}
@Override
public void start(final Stage stage) throws Exception {
final BorderPane root = new BorderPane();
final TabPane tabs = new TabPane();
tabs.minWidthProperty().addListener(new Change("minWidthProperty"));
tabs.minHeightProperty().addListener(new Change("minHeightProperty"));
tabs.prefWidthProperty().addListener(new Change("prefWidthProperty"));
tabs.prefHeightProperty().addListener(new Change("prefHeightProperty"));
tabs.maxWidthProperty().addListener(new Change("maxWidthProperty"));
tabs.maxHeightProperty().addListener(new Change("maxHeightProperty"));
tabs.widthProperty().addListener(new Change("widthProperty"));
tabs.heightProperty().addListener(new Change("heightProperty"));
final Button add = new Button("add");
root.setTop(add);
add.setOnAction((event) -> tabs.getTabs().add(new AddTab()));
final ScrollPane pane = new ScrollPane();
pane.setContent(tabs);
root.setCenter(pane);
stage.setScene(new Scene(root, 400, 400));
stage.show();
}
private void tabPane(final TabPane tabs) {
for (int tab = 0; tab < 2; tab++) {
final BorderPane root = new BorderPane();
final VBox box = new VBox(4);
BorderPane.setAlignment(box, Pos.TOP_LEFT);
root.setCenter(box);
final Tab t = new Tab(String.valueOf(tab));
t.setContent(root);
tabs.getTabs().add(t);
}
}
private static final void changeTabPaneSize(final TabPane tabPane) {
final int index = tabPane.getSelectionModel().getSelectedIndex();
if (index < 0 || tabPane.getTabs().isEmpty()) {
return;
}
if (tabPane.getTabs().size() == 1) {
final Tab tab = tabPane.getTabs().remove(0);
tabPane.getTabs().add(tab);
} else if (tabPane.getTabs().size() > 1 && index == 0) {
tabPane.getSelectionModel().select(1);
} else if (tabPane.getTabs().size() > 1 && index != 0) {
tabPane.getSelectionModel().select(1);
}
tabPane.getSelectionModel().select(index);
}
private final class AddTab extends Tab {
private final int[] row;
private final GridPane grid;
private AddTab() {
super(String.valueOf(System.currentTimeMillis()));
this.row = new int[]{0};
this.grid = new GridPane();
this.grid.setMinSize(USE_PREF_SIZE, USE_PREF_SIZE);
this.grid.setPrefSize(USE_COMPUTED_SIZE, USE_COMPUTED_SIZE);
this.grid.setMaxSize(USE_PREF_SIZE, USE_PREF_SIZE);
this.grid.getColumnConstraints().add(new ColumnConstraints(USE_PREF_SIZE, USE_COMPUTED_SIZE, USE_PREF_SIZE));
final Button add = new Button("add");
add.setOnAction((event) -> add(new Label("label")));
add(add);
setContent(this.grid);
}
private final void add(final Node node) {
GridPane.setConstraints(node, 0, this.row[0]++);
this.grid.getChildren().add(node);
this.grid.getRowConstraints().add(new RowConstraints(USE_PREF_SIZE, USE_COMPUTED_SIZE, USE_PREF_SIZE));
if (getTabPane() != null) {
// changeTabPaneSize(getTabPane());
}
}
}
private final class Change implements ChangeListener<Number> {
private final String property;
/**
* @param property
*/
private Change(String property) {
super();
this.property = property;
}
@Override
public void changed(final ObservableValue<? extends Number> ov, final Number from, Number to) {
System.out.println(String.format("%s: [%s] -> [%s]", this.property, from, to));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
- select other tab and go back
- remove + add the tab (only one tab is pressent)
private static final void changeTabPaneSize(final TabPane tabPane) {
final int index = tabPane.getSelectionModel().getSelectedIndex();
if (index < 0 || tabPane.getTabs().isEmpty()) {
return;
}
if (tabPane.getTabs().size() == 1) {
final Tab tab = tabPane.getTabs().remove(0);
tabPane.getTabs().add(tab);
} else if (tabPane.getTabs().size() > 1 && index == 0) {
tabPane.getSelectionModel().select(1);
} else if (tabPane.getTabs().size() > 1 && index != 0) {
tabPane.getSelectionModel().select(1);
}
tabPane.getSelectionModel().select(index);
}