如何在 JavaFX 中将 CheckBox 添加到 TableView

发布于 2024-12-01 18:09:34 字数 295 浏览 2 评论 0 原文

在我的 Java 桌面应用程序中,我有一个 TableView,我想在其中有一列带有复选框。

我确实在 Jonathan Giles 的网站 http://www.jonathangiles.net (页面2011 年发布的这篇文章不再有效,所以我从帖子中删除了旧链接),但是,下载不可用,乔纳森·吉尔斯没有回复我的电子邮件,所以我想我应该问...

我该怎么办放一个我的 TableView 单元格中的复选框?

In my Java Desktop Application I have a TableView in which I want to have a column with CheckBoxes.

I did find where this has been done on Jonathan Giles's website http://www.jonathangiles.net (the page where this was published in 2011 is no longer active so I removed the old link from the post), However, the download is not available and Jonathan Giles did not answer my email, so I thought I'd ask...

How do I put a CheckBox in a cell of my TableView?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

梦里南柯 2024-12-08 18:09:34

使用 javafx.scene.control.cell .CheckBoxTableCell 工作就完成了!

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

更新:使用Java 8 lambda表达式<的相同代码/a>

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

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

更新:使用 Java 10 "var" 的相同代码上下文单词

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

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

Uses javafx.scene.control.cell.CheckBoxTableCell<S,T> and the work's done !

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

UPDATE: same code using Java 8 lambda expressions

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

Lines count is divided by two! (16 ==> 8)

UPDATE: same code using Java 10 "var" contextual word

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

EDIT to add full functional editable example (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 );
   }
}

EDIT to add full functional editable example (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 );
   }
}
傲娇萝莉攻 2024-12-08 18:09:34

您需要在 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);
            }
        }
    }

You need to set a CellFactory on the TableColumn.

For example:

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);
            }
        }
    }
醉酒的小男人 2024-12-08 18:09:34
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);
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);
沧桑㈠ 2024-12-08 18:09:34

小而简单。

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

Small and simple.

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

云雾 2024-12-08 18:09:34

最简单的解决方案可能是在 FXML 中执行此操作:

  1. 首先创建以下类:

    public class CheckBoxCellFactory;
              实现回调, TableCell> {
        @Override public TableCell;调用(TableColumn  p){
            返回新的 CheckBoxTableCell<>();
        }
    }
    
  2. 然后在 FXML 中包含一个单元工厂:

    
        <细胞工厂>
            >
        
    
    

您还需要在 FXML 中添加导入,例如


额外好处:您可以使工厂更具可定制性,例如通过向 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>

The simplest solution is probably to do it in FXML:

  1. First create the class below:

    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. Then include a cell factory in your FXML:

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

You also need to add an import in the FXML, such as <?import com.assylias.factories.*?>


Bonus: you can make the factory more customisable, for example to determine where the checkbox should appear, by adding fields to the CheckBoxCellFactory class, such as:

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

And the FXML:

<cellFactory>
    <CheckBoxCellFactory alignment="BOTTOM_RIGHT"/>
</cellFactory>
黑寡妇 2024-12-08 18:09:34

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

1 - 假设您有一个带有 isUnowned 方法的“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,并且当您在表中加载项目列表时,该复选框值将被正确设置。

There is a very simple way of doing this, you don't need to modify your model class with SimpleBooleanProperty or whatever, just follow these steps:

1 - Suppose you have a "Person" object with a isUnemployed method:

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 - Create the callback class

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 - Bind the callback to the table column

If you use FXML, put the callback class inside your column:

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

Don't forget to import the class in your FXML:

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

Without FXML, do it like this:

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

4 - That's it

Everything should work as expected, with the value being set to the backing bean when you click on the checkbox, and the checkbox value correctly being set when you load the items list in your table.

别想她 2024-12-08 18:09:34

这就是最终为我工作的结果(请注意,我的模型中的对象是 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);
    });

This is what ended up working for me (note that the object in my model is Candidate and the checkbox determines whether or not they are excluded, hence 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);
    });
無心 2024-12-08 18:09:34

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

您有一个包含两个字段的 Person 模型类,一个“name”字符串和“selected”布尔值:

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

The simplest solution in order to have an EDITABLE checkbox linked to the model is:

Assuming that you have a Person model class with two fields, a "name" string and the "selected" boolean value:

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

All you have to do in the controller is:

@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")
    );
}
偏闹i 2024-12-08 18:09:34

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

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

    }

}

Here is a complete working example showing how to keep the model in sync with the view.....

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

    }

}
§普罗旺斯的薰衣草 2024-12-08 18:09:34

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

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

Inspired from the previous answers, this is the shortest possible version, I think.

checkBoxColumn.setCellValueFactory(c -> {
    c.getValue().booleanProperty().addListener((ch, o, n) -> {
    // do something
    });
    return c.getValue().booleanProperty();
});
checkBoxColumn.setCellFactory(CheckBoxTableCell.forTableColumn(checkBoxColumn));
去了角落 2024-12-08 18:09:34

这就是这样做的方法

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 相同,

这就是我的小应用程序的外观(抱歉,我的主要语言是西班牙语,我构建它供个人使用)
输入图片此处描述

This is the way is do it

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) is necesary to prevent focus getting
    stuck on it.

  • setGraphic(null) is necesary to erase anything left behind after deleting an item or whenever the source list changes

  • cb.selectedProperty().addListener((obs,old,niu)->(your stuff...)); this is where you catch the new value of the CheckBox and do whatever you want with it.

Heres another one with a ToggleGroup and 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);
        }
    };
});

I did some test and memory consumption is basically the same as using a ComboBoxTableCell

This is how my little application looks (sry, my main language is Spanish and i build it for personal use)
enter image description here

难得心□动 2024-12-08 18:09:34

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

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

如果您不需要使用编辑事件创建复选框

for me, works with this solution:

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

and the 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();
}
}

if you dont need to make the checkbox with edit event

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文