Cómo agregar CheckBox a un TableView en JavaFX

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

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

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

preguntado el 27 de agosto de 11 a las 21:08

13 Respuestas

Utiliza materiales de javafx.scene.control.cell.CheckBoxTableCell<S,T> y el trabajo esta 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 Expresiones lambda de Java 8

  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 recuento de líneas se divide por dos! (16 ==> 8)

ACTUALIZACIÓN: mismo código usando 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 un 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 un 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 );
   }
}

Respondido 29 Abr '18, 18:04

Con este código, se agrega la columna de la casilla de verificación, pero no responden a los clics (la marca no cambia). - psyren89

Usar setEditable(true); tampoco hace nada. - psyren89

Una tabla no se vuelve editable solo con setEditable. Las columnas pueden ser editables y el modelo subyacente debe configurarse para que sea editable. Es otro problema, otro post. Cree una nueva publicación con una pregunta con todas las funciones sobre tablas JavaFX editables. - Aubin

¿No es el punto de una casilla de verificación poder marcarla y desmarcarla? - Kyle Bridenstine

No, se puede usar una casilla de verificación como visor de un estado interno. También puede ser un editor. - Aubin

Debe 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);
            }
        }
    }

Respondido 28 Feb 13, 16:02

Lo siento, ya me di cuenta de este. No es así como lo hice, pero probablemente funcione. Gracias de cualquier manera. - Dorothy

Esta no es la forma recomendada con Java FX 2.2+; consulte otras respuestas. - Assylias

@assylias. ¿Puedes aclarar y materializar tu comentario? ¿Te refieres a CheckBoxTableCell? - Uluk Biy

@UlukBiy Sí, que probablemente no estaba disponible cuando se escribió esta respuesta. ¿Yo me perdí algo? - Assylias

@assylias. No. Es posible que la mayoría de los principiantes no sepan que CheckBoxTableCell se agregó en una versión posterior, por eso "aclarar". Puede encontrar / escribir algún buen artículo comparativo sobre la forma recomendada, por eso "materializar". - Uluk Biy

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);

Respondido 30 Abr '16, 12:04

Funcionando como se esperaba :) - TechDog

Perfecto :) simple y perfecto - Nastaran Hakimi

¡Esta debería ser la respuesta aceptada! esta es la única solución que funcionó. - Cryptoharf84

Pequeño y sencillo.

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

Respondido el 05 de diciembre de 16 a las 16:12

¡Me encanta! :-) limpio y simple - Hannes Schneidermayer

La solución más simple probablemente sea 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, incluya una fábrica de células en su FXML:

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

También debe agregar una importación en 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 al CheckBoxCellFactory clase, 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>

Respondido 12 ago 13, 17:08

Pero lo más importante es, ¿cómo comprobar si alguna fila tiene la casilla de verificación "marcada"? - Mateus Viccari

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

1 - Suponga 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 - Crea 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 - Vincular la devolución de llamada a la columna de la tabla

Si usa FXML, coloque 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 olvide importar la clase en su 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 espera, con el valor establecido en el bean de respaldo cuando hace clic en la casilla de verificación, y el valor de la casilla de verificación se establece correctamente cuando carga la lista de elementos en su tabla.

Respondido 02 Feb 17, 14:02

Esto es lo que terminó funcionando para mí (tenga en cuenta que el objeto en mi modelo es Candidate y la casilla de verificación determina si se excluyen o no, por lo tanto isExcluded()):

tableColumnCandidateExcluded.setCellValueFactory(
    c -> {
      Candidate candidate = c.getValue();
      CheckBox checkBox = new CheckBox();
      checkBox.selectedProperty().setValue(candidate.isExcluded());
      checkBox
          .selectedProperty()
          .addListener((ov, old_val, new_val) -> candidate.setExcluded(new_val));
      return new SimpleObjectProperty(checkBox);
    });

Respondido 13 Feb 19, 22:02

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

Asumiendo que tienes un Person clase de modelo 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")
    );
}

contestado el 24 de mayo de 17 a las 20:05

Aquí hay un ejemplo de trabajo completo 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();

    }

}

Respondido 03 Oct 17, 21:10

Solo 227 líneas para mostrar cómo usar una casilla de verificación en una vista de tabla. Woo, Woo, Woo. Nach Nach Nach. - Bryan Pauquette

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

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

Respondido 12 Jul 18, 20:07

Esta es la forma de 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 (false) es necesario para evitar que el enfoque se atasque en él.

  • setGraphic (null) es necesario para borrar todo lo que queda después de eliminar un elemento o cuando cambia la lista de origen

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

Aquí hay otro con 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) enter image description here

Respondido 04 Oct 17, 22:10

Respondido 28 ago 11, 02:08

Encontré esta lib. Simplemente no veo una forma de descargarla para incluirla en mi proyecto. De hecho, esto es exactamente lo que le pedí a Jonathan Giles. - Dorothy

parece que lo desactivó mientras trabaja en la compatibilidad con 2.0 jonathangiles.net/javafx/2.0/CellFactories - Preston

para mí, funciona 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 la 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 marcar la casilla de verificación con el evento de edición

contestado el 28 de mayo de 12 a las 20:05

¿De dónde importó RowData? No puedo llamar a .setSelected. - Markus

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.