import java.util.ArrayList; import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.stage.Stage; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.util.Callback; public class Bug extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage.setScene(new TableViewScene()); stage.show(); } public class TableViewScene extends Scene { public TableViewScene() { super(new HBox(5)); Pane cont = (Pane) getRoot(); cont.getChildren().add(getTestContainer()); } } Pane content; TableView view; ObservableList data = FXCollections.observableArrayList(); CheckBox multiSelectionCheck = new CheckBox("multi-selection"); ; CheckBox singleCellSelectionCheck = new CheckBox("single cell selection"); protected Node getTestContainer() { content = new Pane(); content.setMinSize(500, 500); content.setMaxSize(500, 500); content.setPrefSize(500, 500); view = new TableView(); view.setItems(data); view.setMinSize(400, 400); view.setMaxSize(400, 400); view.setPrefSize(400, 400); reset(DATA_ITEMS_NUM, DATA_FIELDS_NUM, 0); content.getChildren().add(view); view.setTranslateX(50); view.setTranslateY(50); return content; } protected void reset(int rows, int columns, int length) { fill(rows, columns, length); view.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); view.getSelectionModel().setCellSelectionEnabled(false); multiSelectionCheck.setSelected(false); singleCellSelectionCheck.setSelected(false); } protected void refill(int rows, int columns, int length) { data = FXCollections.observableArrayList(); reset(rows, columns, length); view.setItems(data); } protected void fill(int rows_num, int columns_num, int length) { data.clear(); for (int i = 0; i < rows_num; i++) { data.add(new Data(String.format("%02d", i), columns_num, length)); } view.getColumns().clear(); final ContextMenu context_menu = new ContextMenu(); for (int i = 0; i < columns_num; i++) { view.getColumns().add(createColumn(i, context_menu)); } view.setContextMenu(context_menu); } protected TableColumn createColumn(final int index, final ContextMenu context_menu) { final TableColumn field = new TableColumn("field " + index); final CheckMenuItem visible = new CheckMenuItem("field " + index); visible.setSelected(field.isVisible()); visible.selectedProperty().addListener(new ChangeListener() { public void changed(ObservableValue ov, Boolean t, Boolean t1) { field.setVisible(t1); } }); context_menu.getItems().add(visible); final ContextMenu column_context_menu = new ContextMenu(); field.setContextMenu(column_context_menu); CheckMenuItem sortable = new CheckMenuItem("Sortable"); sortable.setSelected(field.isSortable()); sortable.selectedProperty().addListener(new ChangeListener() { public void changed(ObservableValue ov, Boolean t, Boolean t1) { field.setSortable(t1); } }); column_context_menu.getItems().add(sortable); final MenuItem remove_column = new MenuItem("Remove column"); remove_column.setOnAction(new EventHandler() { public void handle(ActionEvent t) { view.getColumns().remove(field); context_menu.getItems().remove(visible); } }); column_context_menu.getItems().add(remove_column); field.setCellValueFactory(new Callback, ObservableValue>() { public ObservableValue call(TableColumn.CellDataFeatures p) { return ((Data) p.getValue()).data.get(index); } }); return field; } protected static String createItem(int level, int item, int length) { StringBuilder builder = new StringBuilder(); builder.append("Level " + level + " Item " + item); if (length > 0) { builder.append(" l"); for (int j = 0; j < length; j++) { builder.append("o"); } builder.append("ng"); } return builder.toString(); } public static class Data { protected String name; protected ArrayList data = new ArrayList(); public Data(String name, int fields_num, int length) { this.name = name; for (int i = 0; i < fields_num; i++) { data.add(new SimpleStringProperty("item " + name + " field " + i + getLongItem(length))); } } protected String getLongItem(int length) { if (length == 0) { return ""; } String str = " l"; for (int i = 0; i < length; i++) { str += "o"; } return str + "ng"; } } static final int DATA_FIELDS_NUM = 10; static final int DATA_ITEMS_NUM = 30; }