llenar data java checkbox tableview tablecell javafx-2

data - Cómo agregar CheckBox a un TableView en JavaFX



llenar tableview javafx (12)

Aquí hay un ejemplo completo de trabajo que muestra cómo mantener el modelo sincronizado con la vista ...

package org.pauquette.example; import javafx.application.Application; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; 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.Scene; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ContentDisplay; import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.util.Callback; public class CheckBoxExample extends Application { class BooleanCell extends TableCell<TableData, Boolean> { private CheckBox checkBox; public BooleanCell() { checkBox = new CheckBox(); checkBox.setDisable(true); checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (isEditing()) commitEdit(newValue == null ? false : newValue); } }); this.setGraphic(checkBox); this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); this.setEditable(true); } @Override public void cancelEdit() { super.cancelEdit(); checkBox.setDisable(true); } public void commitEdit(Boolean value) { super.commitEdit(value); checkBox.setDisable(true); } @Override public void startEdit() { super.startEdit(); if (isEmpty()) { return; } checkBox.setDisable(false); checkBox.requestFocus(); } @Override public void updateItem(Boolean item, boolean empty) { super.updateItem(item, empty); if (!isEmpty()) { checkBox.setSelected(item); } } } // Pojo class. A Javabean public class TableData { SimpleBooleanProperty favorite; SimpleStringProperty stooge; // A javabean typically has a zero arg constructor // https://docs.oracle.com/javase/tutorial/javabeans/ public TableData() { } // but can have others also public TableData(String stoogeIn, Boolean favoriteIn) { stooge = new SimpleStringProperty(stoogeIn); favorite = new SimpleBooleanProperty(favoriteIn); } /** * @return the stooge */ public String getStooge() { return stooge.get(); } /** * @return the favorite */ public Boolean isFavorite() { return favorite.get(); } /** * @param favorite * the favorite to set */ public void setFavorite(Boolean favorite) { this.favorite.setValue(favorite); } /** * @param stooge * the stooge to set */ public void setStooge(String stooge) { this.stooge.setValue(stooge); } } // Model class - The model in mvc // Typically a representation of a database or nosql source public class TableModel { ObservableList<TableData> stooges = FXCollections.observableArrayList(); public TableModel() { stooges.add(new TableData("Larry", false)); stooges.add(new TableData("Moe", true)); stooges.add(new TableData("Curly", false)); } public String displayModel() { StringBuilder sb=new StringBuilder(); for (TableData stooge : stooges) { sb.append(stooge.getStooge() + "=" + stooge.isFavorite() + "|"); } return sb.toString(); } /** * @return the stooges */ public ObservableList<TableData> getStooges() { return stooges; } public void updateStooge(TableData dataIn) { int index=stooges.indexOf(dataIn); stooges.set(index, dataIn); } } public static void main(String[] args) { launch(args); } private TableModel model; private TableModel getModel() { if (model == null) { model = new TableModel(); } return model; } @Override public void start(Stage primaryStage) throws Exception { final VBox view=new VBox(10); final TableView<TableData> table = new TableView<>(); final ObservableList<TableColumn<TableData, ?>> columns = table.getColumns(); final TableModel model = getModel(); final TableColumn<TableData, String> stoogeColumn = new TableColumn<>("Stooge"); stoogeColumn.setCellValueFactory(new PropertyValueFactory<>("stooge")); columns.add(stoogeColumn); final Button showModelButton = new Button("Show me the Model, woo,woo,woo"); final Label showModelLabel = new Label("Model? Whats that?"); showModelButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { showModelLabel.setText(model.displayModel()); }}); final TableColumn<TableData, CheckBox> favoriteColumn = new TableColumn<TableData, CheckBox>("Favorite"); favoriteColumn.setCellValueFactory( new Callback<TableColumn.CellDataFeatures<TableData, CheckBox>, ObservableValue<CheckBox>>() { @Override public ObservableValue<CheckBox> call(TableColumn.CellDataFeatures<TableData, CheckBox> arg0) { TableData data = arg0.getValue(); CheckBox checkBox = new CheckBox(); checkBox.selectedProperty().setValue(data.isFavorite()); checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) { data.setFavorite(new_val); checkBox.setSelected(new_val); model.updateStooge(data); } }); return new SimpleObjectProperty<CheckBox>(checkBox); } }); columns.add(favoriteColumn); table.setItems(model.getStooges()); HBox hbox = new HBox(10); hbox.getChildren().addAll(showModelButton,showModelLabel); view.getChildren().add(hbox); view.getChildren().add(table); Scene scene = new Scene(view, 640, 380); primaryStage.setScene(scene); primaryStage.show(); } }

En mi aplicación de escritorio Java tengo una TableView en la que quiero tener una columna con CheckBoxes.

Encontré dónde se ha hecho esto http://www.jonathangiles.net/javafx/2.0/CellFactories/ pero como la descarga no está disponible y porque no sé qué tan pronto Jonathan Giles responderá mi correo electrónico, pensé d preguntar ...

¿Cómo coloco un CheckBox en una celda de mi TableView?



Es necesario establecer un CellFactory en TableColumn.

Por ejemplo:

Callback<TableColumn<TableData, Boolean>, TableCell<TableData, Boolean>> booleanCellFactory = new Callback<TableColumn<TableData, Boolean>, TableCell<TableData, Boolean>>() { @Override public TableCell<TableData, Boolean> call(TableColumn<TableData, Boolean> p) { return new BooleanCell(); } }; active.setCellValueFactory(new PropertyValueFactory<TableData,Boolean>("active")); active.setCellFactory(booleanCellFactory); class BooleanCell extends TableCell<TableData, Boolean> { private CheckBox checkBox; public BooleanCell() { checkBox = new CheckBox(); checkBox.setDisable(true); checkBox.selectedProperty().addListener(new ChangeListener<Boolean> () { public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if(isEditing()) commitEdit(newValue == null ? false : newValue); } }); this.setGraphic(checkBox); this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); this.setEditable(true); } @Override public void startEdit() { super.startEdit(); if (isEmpty()) { return; } checkBox.setDisable(false); checkBox.requestFocus(); } @Override public void cancelEdit() { super.cancelEdit(); checkBox.setDisable(true); } public void commitEdit(Boolean value) { super.commitEdit(value); checkBox.setDisable(true); } @Override public void updateItem(Boolean item, boolean empty) { super.updateItem(item, empty); if (!isEmpty()) { checkBox.setSelected(item); } } }


Este es el camino es hacerlo

tbcSingleton.setCellValueFactory(data -> data.getValue().singletonProperty()); tbcSingleton.setCellFactory( param -> { return new TableCell<FXMLController, Boolean>(){ { setAlignment(Pos.CENTER); } protected void updateItem(Boolean item, boolean empty){ if(!empty && item!=null) { CheckBox cb = new CheckBox(); cb.setSelected(item); cb.setFocusTraversable(false); cb.selectedProperty().addListener((obs,old,niu)->listaFXMLController.get(getIndex()).setSingleton(niu)); setGraphic(cb); }else setGraphic(null); } }; });

  • cb.setFocusTraversable (falso) es necesario para evitar que el enfoque se atasque en él.

  • setGraphic (null) es necesario para borrar todo lo que haya quedado después de eliminar un elemento o cada vez que cambie la lista de fuentes

  • cb.selectedProperty (). addListener ((obs, old, niu) -> (tus cosas ...)); aquí es donde se captura el nuevo valor de CheckBox y hace lo que quiera con él.

Heres otro con un ToggleGroup y ToggleButtons

tbcTipoControlador.setCellValueFactory(data -> data.getValue().controllerTypeProperty()); tbcTipoControlador.setCellFactory( param -> { return new TableCell<FXMLController, ControllerType>() { { setAlignment(Pos.CENTER); } protected void updateItem(ControllerType item, boolean empty){ if(!empty && item!=null) { ToggleButton tbModal = new ToggleButton("Modal"); tbModal.selectedProperty().addListener((obs,old,niu)->{ if(niu) listaFXMLController.get(getIndex()).setControllerType(ControllerType.MODAL); }); tbModal.setSelected(item.equals(ControllerType.MODAL)); ToggleButton tbPlain = new ToggleButton("Plain"); tbPlain.selectedProperty().addListener((obs,old,niu)->{ if(niu) listaFXMLController.get(getIndex()).setControllerType(ControllerType.PLAIN); }); tbPlain.setSelected(item.equals(ControllerType.PLAIN)); ToggleButton tbApplication= new ToggleButton("Application"); tbApplication.selectedProperty().addListener((obs,old,niu)->{ if(niu) listaFXMLController.get(getIndex()).setControllerType(ControllerType.APPLICATION); }); tbApplication.setSelected(item.equals(ControllerType.APPLICATION)); ToggleGroup gp = new ToggleGroup(); tbModal.setFocusTraversable(false); tbPlain.setFocusTraversable(false); tbApplication.setFocusTraversable(false); tbModal.setPrefWidth(120); tbPlain.setPrefWidth(120); tbApplication.setPrefWidth(120); gp.getToggles().addAll(tbModal,tbPlain,tbApplication); HBox hb = new HBox(); hb.setAlignment(Pos.CENTER); hb.getChildren().addAll(tbModal,tbPlain,tbApplication); setGraphic(hb); }else setGraphic(null); } }; });

Hice algunas pruebas y el consumo de memoria es básicamente lo mismo que usar un ComboBoxTableCell

Así es como se ve mi pequeña aplicación (sry, mi idioma principal es el español y lo construyo para uso personal)


Hay una forma muy sencilla de hacer esto, no necesita modificar su clase de modelo con SimpleBooleanProperty o lo que sea, solo siga estos pasos:

1 - Supongamos que tiene un objeto "Persona" con un método isUnemployed:

public class Person { private String name; private Boolean unemployed; public String getName(){return this.name;} public void setName(String name){this.name = name;} public Boolean isUnemployed(){return this.unemployed;} public void setUnemployed(Boolean unemployed){this.unemployed = unemployed;} }

2 - Crear la clase de devolución de llamada

import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.scene.control.CheckBox; import javafx.scene.control.TableColumn; import javafx.util.Callback; public class PersonUnemployedValueFactory implements Callback<TableColumn.CellDataFeatures<Person, CheckBox>, ObservableValue<CheckBox>> { @Override public ObservableValue<CheckBox> call(TableColumn.CellDataFeatures<Person, CheckBox> param) { Person person = param.getValue(); CheckBox checkBox = new CheckBox(); checkBox.selectedProperty().setValue(person.isUnemployed()); checkBox.selectedProperty().addListener((ov, old_val, new_val) -> { person.setUnemployed(new_val); }); return new SimpleObjectProperty<>(checkBox); } }

3 - Enlazar la devolución de llamada a la columna de la tabla

Si usa FXML, ponga la clase de devolución de llamada dentro de su columna:

<TableView fx:id="personList" prefHeight="200.0" prefWidth="200.0"> <columns> <TableColumn prefWidth="196.0" text="Unemployed"> <cellValueFactory> <PersonUnemployedValueFactory/> <!--This is how the magic happens--> </cellValueFactory> </TableColumn> ... </columns> </TableView>

No olvides importar la clase en tu FXML:

<?import org.yourcompany.yourapp.util.PersonUnemployedValueFactory?>

Sin FXML, hazlo así:

TableColumn<Person, CheckBox> column = (TableColumn<Person, CheckBox>) personTable.getColumns().get(0); column.setCellValueFactory(new PersonUnemployedValueFactory());

4 - eso es todo

Todo debería funcionar como se esperaba, con el valor establecido en el bean de respaldo al hacer clic en la casilla de verificación y el valor de la casilla de verificación correctamente configurado al cargar la lista de elementos en su tabla.


Inspirado en las respuestas anteriores, esta es la versión más corta posible, creo.

checkBoxColumn.setCellValueFactory(c -> { c.getValue().booleanProperty().addListener((ch, o, n) -> { // do something }); return c.getValue().booleanProperty(); }); checkBoxColumn.setCellFactory(CheckBoxTableCell.forTableColumn(checkBoxColumn));


La solución más simple es probablemente hacerlo en FXML:

  1. Primero crea la clase a continuación:

    public class CheckBoxCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> { @Override public TableCell<S, T> call(TableColumn<S, T> p) { return new CheckBoxTableCell<>(); } }

  2. Luego incluye una fábrica de células en tu FXML:

    <TableColumn text="Select" fx:id="selectColumn" > <cellFactory> <CheckBoxCellFactory/> </cellFactory> </TableColumn>

También debe agregar una importación en el FXML, como <?import com.assylias.factories.*?>

Bonificación: puede hacer que la fábrica sea más personalizable, por ejemplo, para determinar dónde debe aparecer la casilla de verificación, agregando campos a la clase CheckBoxCellFactory , como:

private Pos alignment = Pos.CENTER; public Pos getAlignment() { return alignment; } public void setAlignment(Pos alignment) { this.alignment = alignment; }

Y el FXML:

<cellFactory> <CheckBoxCellFactory alignment="BOTTOM_RIGHT"/> </cellFactory>


La solución más simple para tener una casilla de verificación EDITABLE vinculada al modelo es:

Suponiendo que tiene una clase de modelo de Person con dos campos, una cadena de "nombre" y el valor booleano "seleccionado":

public class Person { private final SimpleBooleanProperty selected; private final SimpleStringProperty name; public Person(String name) { this.selected = new SimpleBooleanProperty(false); this.name = new SimpleStringProperty(name); } public boolean isSelected() { return selected.get(); } public SimpleBooleanProperty selectedProperty() { return selected; } public void setSelected(boolean selected) { this.selected.set(selected); } public String getName() { return name.get(); } public SimpleStringProperty nameProperty() { return name; } public void setName(String name) { this.name.set(name); } }

Todo lo que tienes que hacer en el controlador es:

@FXML private TableColumn<Person, Boolean> checkBoxCol; @FXML private TableColumn<Person, String> nameCol; @Override public void initialize(URL location, ResourceBundle resources) { checkBoxCol.setCellFactory( CheckBoxTableCell.forTableColumn(checkBoxCol) ); checkBoxCol.setCellValueFactory( new PropertyValueFactory<>("selected") ); nameCol.setCellValueFactory( new PropertyValueFactory<>("name") ); }


Para mí, trabaja con esta solución:

Callback<TableColumn, TableCell> checkboxCellFactory = new Callback<TableColumn, TableCell>() { @Override public TableCell call(TableColumn p) { return new CheckboxCell(); } }; TableColumn selectColumn = (TableColumn) tbvDatos.getColumns().get(1); selectColumn.setCellValueFactory(new PropertyValueFactory("selected")); selectColumn.setCellFactory(checkboxCellFactory);

y el tableCell:

public class CheckboxCell extends TableCell<RowData, Boolean> { CheckBox checkbox; @Override protected void updateItem(Boolean arg0, boolean arg1) { super.updateItem(arg0, arg1); paintCell(); } private void paintCell() { if (checkbox == null) { checkbox = new CheckBox(); checkbox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) { setItem(new_val); ((RowData)getTableView().getItems().get(getTableRow().getIndex())).setSelected(new_val); } }); } checkbox.setSelected(getValue()); setText(null); setGraphic(checkbox); } private Boolean getValue() { return getItem() == null ? false : getItem(); } }

Si no necesita hacer la casilla de verificación con el evento de edición


Pequeño y sencillo.

row.setCellValueFactory(c -> new SimpleBooleanProperty(c.getValue().getIsDefault())); row.setCellFactory(tc -> new CheckBoxTableCell<>());


Utiliza javafx.scene.control.cell.CheckBoxTableCell<S,T> y el trabajo está hecho!

ObservableList< TableColumn< RSSReader, ? >> columns = _rssStreamsView.getColumns(); [...] TableColumn< RSSReader, Boolean > loadedColumn = new TableColumn<>( "Loaded" ); loadedColumn.setCellValueFactory( new Callback<CellDataFeatures<RSSReader,Boolean>,ObservableValue<Boolean>>(){ @Override public ObservableValue<Boolean> call( CellDataFeatures<RSSReader,Boolean> p ){ return p.getValue().getCompleted(); }}); loadedColumn.setCellFactory( new Callback<TableColumn<RSSReader,Boolean>,TableCell<RSSReader,Boolean>>(){ @Override public TableCell<RSSReader,Boolean> call( TableColumn<RSSReader,Boolean> p ){ return new CheckBoxTableCell<>(); }}); [...] columns.add( loadedColumn );

ACTUALIZACIÓN: mismo código usando Java 8 lambda expresiones

ObservableList< TableColumn< RSSReader, ? >> columns = _rssStreamsView.getColumns(); [...] TableColumn< RSSReader, Boolean > loadedColumn = new TableColumn<>( "Loaded" ); loadedColumn.setCellValueFactory( f -> f.getValue().getCompleted()); loadedColumn.setCellFactory( tc -> new CheckBoxTableCell<>()); [...] columns.add( loadedColumn );

¡El conteo de líneas está dividido por dos! (16 ==> 8)

ACTUALIZACIÓN: mismo código usando la palabra contextual "var" de Java 10

var columns = _rssStreamsView.getColumns(); [...] var loadedColumn = new TableColumn<RSSReader, Boolean>( "Loaded" ); loadedColumn.setCellValueFactory( f -> f.getValue().getCompleted()); loadedColumn.setCellFactory( tc -> new CheckBoxTableCell<>()); [...] columns.add( loadedColumn );

EDITAR para agregar ejemplo editable funcional completo (Java 8)

public class Os { private final StringProperty name = new SimpleStringProperty(); private final BooleanProperty delete = new SimpleBooleanProperty(); public Os( String nm, boolean del ) { name .set( nm ); delete.set( del ); } public StringProperty nameProperty () { return name; } public BooleanProperty deleteProperty() { return delete; } } public class FxEditableCheckBox extends Application { @Override public void start( Stage stage ) throws Exception { final TableView<Os> view = new TableView<>(); final ObservableList<TableColumn<Os, ?>> columns = view.getColumns(); final TableColumn<Os, Boolean> nameColumn = new TableColumn<>( "Name" ); nameColumn.setCellValueFactory( new PropertyValueFactory<>( "name" )); columns.add( nameColumn ); final TableColumn<Os, Boolean> loadedColumn = new TableColumn<>( "Delete" ); loadedColumn.setCellValueFactory( new PropertyValueFactory<>( "delete" )); loadedColumn.setCellFactory( tc -> new CheckBoxTableCell<>()); columns.add( loadedColumn ); final ObservableList<Os> items = FXCollections.observableArrayList( new Os( "Microsoft Windows 3.1" , true ), new Os( "Microsoft Windows 3.11" , true ), new Os( "Microsoft Windows 95" , true ), new Os( "Microsoft Windows NT 3.51", true ), new Os( "Microsoft Windows NT 4" , true ), new Os( "Microsoft Windows 2000" , true ), new Os( "Microsoft Windows Vista" , true ), new Os( "Microsoft Windows Seven" , false ), new Os( "Linux all versions :-)" , false )); view.setItems( items ); view.setEditable( true ); final Button delBtn = new Button( "Delete" ); delBtn.setMaxWidth( Double.MAX_VALUE ); delBtn.setOnAction( e -> { final Set<Os> del = new HashSet<>(); for( final Os os : view.getItems()) { if( os.deleteProperty().get()) { del.add( os ); } } view.getItems().removeAll( del ); }); stage.setScene( new Scene( new BorderPane( view, null, null, delBtn, null ))); BorderPane.setAlignment( delBtn, Pos.CENTER ); stage.show(); } public static void main( String[] args ) { launch( args ); } }

EDITAR para agregar ejemplo editable funcional completo (Java 10)

public class Os { private final StringProperty name = new SimpleStringProperty(); private final BooleanProperty delete = new SimpleBooleanProperty(); public Os( String nm, boolean del ) { name .set( nm ); delete.set( del ); } public StringProperty nameProperty () { return name; } public BooleanProperty deleteProperty() { return delete; } } public class FxEditableCheckBoxJava10 extends Application { @Override public void start( Stage stage ) throws Exception { final var view = new TableView<Os>(); final var columns = view.getColumns(); final var nameColumn = new TableColumn<Os, Boolean>( "Name" ); nameColumn.setCellValueFactory( new PropertyValueFactory<>( "name" )); columns.add( nameColumn ); final var loadedColumn = new TableColumn<Os, Boolean>( "Delete" ); loadedColumn.setCellValueFactory( new PropertyValueFactory<>( "delete" )); loadedColumn.setCellFactory( tc -> new CheckBoxTableCell<>()); columns.add( loadedColumn ); final var items = FXCollections.observableArrayList( new Os( "Microsoft Windows 3.1" , true ), new Os( "Microsoft Windows 3.11" , true ), new Os( "Microsoft Windows 95" , true ), new Os( "Microsoft Windows NT 3.51", true ), new Os( "Microsoft Windows NT 4" , true ), new Os( "Microsoft Windows 2000" , true ), new Os( "Microsoft Windows Vista" , true ), new Os( "Microsoft Windows Seven" , false ), new Os( "Linux all versions :-)" , false )); view.setItems( items ); view.setEditable( true ); final var delBtn = new Button( "Delete" ); delBtn.setMaxWidth( Double.MAX_VALUE ); delBtn.setOnAction( e -> { final var del = new HashSet<Os>(); for( final var os : view.getItems()) { if( os.deleteProperty().get()) { del.add( os ); } } view.getItems().removeAll( del ); }); stage.setScene( new Scene( new BorderPane( view, null, null, delBtn, null ))); BorderPane.setAlignment( delBtn, Pos.CENTER ); stage.show(); } public static void main( String[] args ) { launch( args ); } }


TableColumn select = new TableColumn("CheckBox"); select.setMinWidth(200); select.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, CheckBox>, ObservableValue<CheckBox>>() { @Override public ObservableValue<CheckBox> call( TableColumn.CellDataFeatures<Person, CheckBox> arg0) { Person user = arg0.getValue(); CheckBox checkBox = new CheckBox(); checkBox.selectedProperty().setValue(user.isSelected()); checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() { public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) { user.setSelected(new_val); } }); return new SimpleObjectProperty<CheckBox>(checkBox); } }); table.getColumns().addAll( select);