如何在 JavaFX 中将 CheckBox 添加到 TableView

Posted

技术标签:

【中文标题】如何在 JavaFX 中将 CheckBox 添加到 TableView【英文标题】:How to add CheckBox's to a TableView in JavaFX 【发布时间】:2011-11-05 06:24:55 【问题描述】:

在我的 Java 桌面应用程序中,我有一个 TableView,我希望在其中有一列带有 CheckBoxes。

我确实找到了在哪里完成此操作 http://www.jonathangiles.net/javafx/2.0/CellFactories/,但由于无法下载,而且我不知道 Jonathan Giles 多久会回复我的电子邮件,所以我想我会问...

如何将 CheckBox 放入 TableView 的单元格中?

【问题讨论】:

【参考方案1】:

使用javafx.scene.control.cell.CheckBoxTableCell<S,T>,工作就完成了!

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

更新:使用Java 8 lambda expressions的相同代码

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

行数除以二! (16 ==> 8)

更新:使用Java 10 "var" contextual word的相同代码

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

编辑以添加功能齐全的可编辑示例 (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 );
   

编辑以添加全功能可编辑示例 (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 );
   

【讨论】:

使用此代码,添加了复选框列,但它们不响应点击(检查不会改变)。 使用setEditable(true); 也无济于事。 只有setEditable 才能编辑表格。列可能是可编辑的,并且基础模型必须设置为可编辑。这是另一个问题,另一个帖子。请创建一篇新帖子,其中包含有关可编辑 JavaFX 表的完整问题。 checkbox的重点不就是可以勾选和取消勾选吗? 不,复选框可以用作内部状态的查看器。它也可能是一个编辑器。【参考方案2】:

您需要在 TableColumn 上设置一个 CellFactory。

例如:

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

【讨论】:

对不起,我已经想通了。这不是我的做法,但它可能有效。还是谢谢。 这不是 Java FX 2.2+ 的推荐方式 - 参见其他答案。 @assylias。你能澄清和具体化你的评论吗?你是说 CheckBoxTableCell 吗? @UlukBiy 是的-在编写此答案时可能不可用。我错过了什么吗? @assylias。不,大多数新手可能不知道 CheckBoxTableCell 是在更高版本中添加的,这就是“澄清”的原因。您可能会在推荐的方式上找到/写了一些很好的比较文章,这就是“实现”的原因。【参考方案3】:
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);

【讨论】:

按预期工作:) 完美:) 简单完美 这应该是公认的答案!这是唯一有效的解决方案。【参考方案4】:

小而简单。

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

【讨论】:

爱它! :-) 干净简单【参考方案5】:

最简单的解决方案可能是在 FXML 中进行:

    首先创建下面的类:

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

    然后在您的 FXML 中包含一个单元工厂:

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

你还需要在FXML中添加一个import,比如&lt;?import com.assylias.factories.*?&gt;


奖励:您可以使工厂更加可定制,例如,通过向CheckBoxCellFactory 类添加字段来确定复选框应该出现的位置,例如:

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

还有 FXML:

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

【讨论】:

但最重要的是,如何检查某行是否“选中”了复选框?【参考方案6】:

有一种非常简单的方法可以做到这一点,您不需要使用 SimpleBooleanProperty 或其他方式修改模型类,只需按照以下步骤操作即可:

1 - 假设您有一个带有 isUnemployed 方法的“Person”对象:

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 - 创建回调类

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 - 将回调绑定到表格列

如果您使用 FXML,请将回调类放在您的列中:

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

别忘了在你的 FXML 中导入类:

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

如果没有 FXML,请这样做:

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

4 - 就是这样

一切都应该按预期工作,当您单击复选框时将值设置为支持 bean,并且当您在表中加载项目列表时正确设置复选框值。

【讨论】:

【参考方案7】:

这最终对我有用(请注意,我的模型中的对象是Candidate,复选框确定它们是否被排除在外,因此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);
    );

【讨论】:

【参考方案8】:

为了将 EDITABLE 复选框链接到模型,最简单的解决方案是:

假设您有一个 Person 模型类,其中包含两个字段,一个“名称”字符串和一个“选定”布尔值:

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

您在控制器中所要做的就是:

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

【讨论】:

【参考方案9】:

这是一个完整的工作示例,展示了如何使模型与视图保持同步.....

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

    


【讨论】:

只有 227 行来展示如何在表格视图中使用复选框。呜呜呜呜纳赫纳赫纳赫。【参考方案10】:

受先前答案的启发,我认为这是最短的版本。

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

【讨论】:

【参考方案11】:

这就是方法

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) 是防止获得焦点所必需的 坚持下去。

setGraphic(null) 用于在删除项目后或源列表更改时擦除遗留的任何内容

cb.selectedProperty().addListener((obs,old,niu)->(你的东西...));在这里,您可以获取 CheckBox 的新值并使用它做任何您想做的事情。

这是另一个带有 ToggleGroup 和 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);
        
    ;
);

我做了一些测试,内存消耗和使用ComboBoxTableCell基本一样

这就是我的小应用程序的外观(抱歉,我的主要语言是西班牙语,我构建它供个人使用)

【讨论】:

【参考方案12】:

这是一个可以做到的第 3 方库 http://www.jonathangiles.net/javafx/2.0/CellFactories/docs/api/net/jonathangiles/javafx/control/cell/tableview/CheckBoxTableCell.html

【讨论】:

我确实找到了这个库我只是看不到下载它以将其包含在我的项目中的方法。事实上,这正是我向 Jonathan Giles 提出的要求。 看起来他在支持 2.0 时禁用了它jonathangiles.net/javafx/2.0/CellFactories【参考方案13】:

对我来说,使用这个解决方案:

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

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


如果您不需要使用编辑事件制作复选框

【讨论】:

您从哪里导入 RowData?我无法调用 .setSelected 。

以上是关于如何在 JavaFX 中将 CheckBox 添加到 TableView的主要内容,如果未能解决你的问题,请参考以下文章

在 JavaFX 中将元素动态添加到固定大小的 GridPane

在 JavaFX 中将 BlendMode 添加到裁剪节点

javafx 在tableView里插入checkbox

如何从编码中将复选框添加到datagridview

我可以在 JavaFX 中将自签名证书添加到我的 WebEngine 以连接到 https Web 服务器吗?

如何在 JavaFX 中将图像设置为按钮的大小