如何将CheckBox添加到JavaFX中的TableView

Dor*_*thy 25 java checkbox tableview tablecell javafx-2

在我的Java桌面应用程序中,我有一个TableView,其中我想要一个包含CheckBoxes的列.

我确实找到了这个已经完成的地方http://www.jonathangiles.net/javafx/2.0/CellFactories/但由于下载不可用,因为我不知道Jonathan Giles多久会回复我的电子邮件我以为我'请问......

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

Aub*_*bin 46

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

  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 );
Run Code Online (Sandbox Code Playgroud)

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

  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 );
Run Code Online (Sandbox Code Playgroud)

行数除以2!(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 );
Run Code Online (Sandbox Code Playgroud)

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

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

  • 复选框是不是能够检查和取消选中它? (5认同)
  • 使用此代码,会添加复选框列,但它们不会响应点击(检查不会更改). (4认同)
  • 不,复选框可以用作内部状态的查看器.它也可能是一个编辑. (2认同)

小智 23

您需要在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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • @assylias.不是.大多数新手可能都不知道CheckBoxTableCell是在以后的版本中添加的,这就是"澄清"的原因.您可以在推荐的方式上找到/写一些好的比较文章,这就是"实现"的原因. (2认同)

She*_* Fn 10

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);
Run Code Online (Sandbox Code Playgroud)


ass*_*ias 7

最简单的解决方案可能是在FXML中做到这一点:

  1. 首先创建以下类:

    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<>();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后在FXML中包含一个单元工厂:

    <TableColumn text="Select" fx:id="selectColumn" >
        <cellFactory>
            <CheckBoxCellFactory/>
        </cellFactory>
    </TableColumn>
    
    Run Code Online (Sandbox Code Playgroud)

您还需要在FXML中添加导入,例如 <?import com.assylias.factories.*?>


额外奖励:您可以通过向CheckBoxCellFactory类添加字段来使工厂更具可自定义性,例如确定复选框的显示位置,例如:

private Pos alignment = Pos.CENTER;
public Pos getAlignment() { return alignment; }
public void setAlignment(Pos alignment) { this.alignment = alignment; }
Run Code Online (Sandbox Code Playgroud)

和FXML:

<cellFactory>
    <CheckBoxCellFactory alignment="BOTTOM_RIGHT"/>
</cellFactory>
Run Code Online (Sandbox Code Playgroud)


Kef*_*iks 7

小而简单。

row.setCellValueFactory(c -> new SimpleBooleanProperty(c.getValue().getIsDefault()));
row.setCellFactory(tc -> new CheckBoxTableCell<>());
Run Code Online (Sandbox Code Playgroud)


Mat*_*ari 5

有一种非常简单的方法,您不需要使用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;}
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

不要忘记在FXML中导入该类:

<?import org.yourcompany.yourapp.util.PersonUnemployedValueFactory?>
Run Code Online (Sandbox Code Playgroud)

没有FXML,就这样做:

TableColumn<Person, CheckBox> column = (TableColumn<Person, CheckBox>) personTable.getColumns().get(0);
column.setCellValueFactory(new PersonUnemployedValueFactory());
Run Code Online (Sandbox Code Playgroud)

4 - 就是这样

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