自定义radiobuttomtablecell未正确保存值javafx公司

v440hwme  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(238)

我有tableview和model类,只有两个属性字段, name ,和 selected . 我试着用单选按钮制作tablecell,它允许你选择一个并且只能选择一个项目。问题是,当我单击单选按钮时,它会将新值保存到模型类中,但未选中项中的旧值不会被覆盖,因此我有两个带有 selected 属性为true,但它显示为仅选择了一个。这是我的最小可执行代码。
tablecell类radiobuttontablecell.java

import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;

import javax.swing.table.TableColumn;

public class RadioButtonTableCell extends TableCell<Model, Boolean> {
    private RadioButton radioButton = new RadioButton();
    private HBox hBox = new HBox();

    public RadioButtonTableCell(javafx.scene.control.TableColumn<Model, Boolean> column) {
        hBox.getChildren().add(radioButton);
        hBox.setAlignment(Pos.CENTER);
        radioButton.disableProperty().bind(column.editableProperty().not());

        radioButton.setOnMouseEntered(event -> {
            final TableView<Model> tableView = getTableView();
            tableView.getSelectionModel().select(getTableRow().getIndex());
            super.startEdit();
            tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);
        });

        radioButton.selectedProperty().addListener((observable, oldValue, newValue) -> {
            if (isEditing()) {
                commitEdit(newValue);
            }
        });
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }

    @Override
    protected void updateItem(Boolean item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) setGraphic(null);
        else {
            radioButton.setSelected(item);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            setGraphic(hBox);
        }
    }

    public RadioButton getRadioButton() {
        return this.radioButton;
    }
}

数据模型.java

import javafx.beans.property.BooleanProperty;
        import javafx.beans.property.SimpleBooleanProperty;
        import javafx.beans.property.SimpleStringProperty;
        import javafx.beans.property.StringProperty;

public class Model {
    private StringProperty name = new SimpleStringProperty();
    private BooleanProperty selected = new SimpleBooleanProperty();

    public Model(String name, boolean selected) {
        this.name.set(name);
        this.selected.set(selected);
    }

    public BooleanProperty selectedProperty() {
        return selected;
    }

    public StringProperty nameProperty() {
        return name;
    }

    @Override
    public String toString() {
        return "Model{" +
                "name=" + name +
                ", selected=" + selected +
                '}';
    }
}

main类main.java

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Model> tableView = new TableView<>();
        tableView.setEditable(true);
        ToggleGroup toggleGroup = new ToggleGroup();

        TableColumn<Model, Boolean> selectedColumn = new TableColumn<>("selected");
        selectedColumn.setCellValueFactory(item -> item.getValue().selectedProperty());
        selectedColumn.setCellFactory(tableCell -> {
            RadioButtonTableCell cell = new RadioButtonTableCell(selectedColumn);
            toggleGroup.getToggles().add(cell.getRadioButton());
            return cell;
        });
        selectedColumn.setEditable(true);

        TableColumn<Model, String> nameColumn = new TableColumn<>("name");
        nameColumn.setCellValueFactory(item -> item.getValue().nameProperty());

        tableView.getColumns().addAll(nameColumn, selectedColumn);

        Scene scene = new Scene(tableView);
        ObservableList<Model> list = FXCollections.observableArrayList();
        list.add(new Model("Alisa", true));
        list.add(new Model("Bob", false));
        list.add(new Model("Jonh", false));
        list.add(new Model("Sam", false));
        list.add(new Model("Maria", false));

        tableView.setItems(list);

        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.setOnCloseRequest(event -> {
            for (Model item : tableView.getItems()) {
                System.out.println(item.toString());
            }
        });
    }

    public static void main(String[] args) {
        launch(args);
    }
}
v6ylcynt

v6ylcynt1#

我明白你的习惯 TableCell 导入到 swing 我不知道为什么,因为我不知道你在哪里用它,但我认为这不是问题所在。如我所见,你从不把它们加到 ToggleGroup ,将它们分组,如果选择其中一个,则将取消选择其他组。
我写了一个简单的例子 RadioButton 在一个 TableCell ,我为每个 RadioButton 这个 ToggleGroup 来处理选择。下面是代码:

public class Controller implements Initializable {

    @FXML
    private Label label;

    @FXML
    private TableView<MyModel> table;
    @FXML
    private TableColumn<MyModel, String> first;
    @FXML
    private TableColumn<MyModel, Boolean> second;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        ToggleGroup toggleGroup = new ToggleGroup();

        first.setCellValueFactory(data -> data.getValue().nameProperty());
        second.setCellValueFactory(data -> data.getValue().selectedProperty());
        second.setCellFactory(factory -> new RadioButtonTableCell(toggleGroup));

        MyModel john = new MyModel("John");
        MyModel andrew = new MyModel("Andrew");

        table.getItems().addAll(john, andrew);

        label.textProperty().bind(john.selectedProperty().asString()); // easy check if it works for the backing model.
    }

    private class MyModel {

        private StringProperty name;
        private BooleanProperty selected;

        MyModel(String name) {
            this.name = new SimpleStringProperty(name);
            this.selected = new SimpleBooleanProperty(false);
        }

        StringProperty nameProperty() {
            return name;
        }

        BooleanProperty selectedProperty() {
            return selected;
        }
    }

    private class RadioButtonTableCell extends TableCell<MyModel, Boolean> {

        private RadioButton radioButton;

        RadioButtonTableCell(ToggleGroup toggleGroup) {
            this.radioButton = new RadioButton();
            radioButton.setToggleGroup(toggleGroup);
            // Since you don't edit the cell while select a radioButton, this is the simplest way to set the value to
            // the backing model        
            radioButton.selectedProperty().addListener((observable, oldValue, newValue) ->
                    ((MyModel) getTableRow().getItem()).selectedProperty().set(newValue));
        }

        @Override 
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
                return;
            }
            setGraphic(radioButton);
        }
    }

}

相关问题