When items are added/removed from a tableview's item list, editing is cancelled. This results in odd behavior when using a combo box. The combo box opens up but when the update to the item list occurs, the combo box bugs out leaving an un-editable drop down (see test case): -
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
class EditableComboBoxCell extends TableCell<String, String>
{
private ComboBox<Object> comboBox;
@Override
public void startEdit()
{
super.startEdit();
comboBox = new ComboBox<>();
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(comboBox);
}
@Override
public void cancelEdit()
{
super.cancelEdit();
comboBox = null;
setContentDisplay(ContentDisplay.TEXT_ONLY);
setText(getItem());
}
@Override
public void updateItem(final String item, final boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setText(null);
setGraphic(null);
}
else
{
if (isEditing())
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(comboBox);
}
else
{
setContentDisplay(ContentDisplay.TEXT_ONLY);
setText(getItem());
}
}
}
}
public class Foo extends Application implements Runnable
{
@Override
public void start(final Stage stage)
{
final TableView table = new TableView();
final TableColumn column = new TableColumn();
table.setEditable(true);
column.setEditable(true);
table.setItems(FXCollections.observableArrayList());
column.setCellFactory(cell -> new EditableComboBoxCell());
column.setCellValueFactory(param -> new SimpleStringProperty("foo"));
table.getColumns().add(column);
// Simple thread loop to demonstrate adding items
new Thread(() ->
{
try
{
while (true)
{
Thread.sleep(5000);
Platform.runLater(() -> table.getItems().add("foo"));
}
} catch (InterruptedException e)
{
}
}).start();
Scene scene = new Scene(new StackPane(table));
stage.setScene(scene);
stage.show();
}
@Override
public void run()
{
launch();
}
}
A suggestion on stackoverflow as a more sophisticated fix is attached below: -
"if the content change removes the item that is being edited, cancel edit, otherwise make sure the correct cell is now in editing state"
See the following post on stackoverflow: -
http://stackoverflow.com/questions/30073165/javafx-controls-inside-tableview-behaving-strangely
Classifying this as major as in a fast updating table view, an editable combo box table cell is unusable as the pop out box where you select an item just closes upon update. I noticed in versions prior to 8u60 (early access), the combo box would jump around on the tableview.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
class EditableComboBoxCell extends TableCell<String, String>
{
private ComboBox<Object> comboBox;
@Override
public void startEdit()
{
super.startEdit();
comboBox = new ComboBox<>();
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(comboBox);
}
@Override
public void cancelEdit()
{
super.cancelEdit();
comboBox = null;
setContentDisplay(ContentDisplay.TEXT_ONLY);
setText(getItem());
}
@Override
public void updateItem(final String item, final boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setText(null);
setGraphic(null);
}
else
{
if (isEditing())
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(comboBox);
}
else
{
setContentDisplay(ContentDisplay.TEXT_ONLY);
setText(getItem());
}
}
}
}
public class Foo extends Application implements Runnable
{
@Override
public void start(final Stage stage)
{
final TableView table = new TableView();
final TableColumn column = new TableColumn();
table.setEditable(true);
column.setEditable(true);
table.setItems(FXCollections.observableArrayList());
column.setCellFactory(cell -> new EditableComboBoxCell());
column.setCellValueFactory(param -> new SimpleStringProperty("foo"));
table.getColumns().add(column);
// Simple thread loop to demonstrate adding items
new Thread(() ->
{
try
{
while (true)
{
Thread.sleep(5000);
Platform.runLater(() -> table.getItems().add("foo"));
}
} catch (InterruptedException e)
{
}
}).start();
Scene scene = new Scene(new StackPane(table));
stage.setScene(scene);
stage.show();
}
@Override
public void run()
{
launch();
}
}
A suggestion on stackoverflow as a more sophisticated fix is attached below: -
"if the content change removes the item that is being edited, cancel edit, otherwise make sure the correct cell is now in editing state"
See the following post on stackoverflow: -
http://stackoverflow.com/questions/30073165/javafx-controls-inside-tableview-behaving-strangely
Classifying this as major as in a fast updating table view, an editable combo box table cell is unusable as the pop out box where you select an item just closes upon update. I noticed in versions prior to 8u60 (early access), the combo box would jump around on the tableview.
- relates to
-
JDK-8089514 [TableView, TreeView, ListView, TreeTableView] Clicking outside of the edited cell, node, or entry should commit the value
- Open