【问题标题】:custom RadioButtomTableCell does not properly save value. JavaFX自定义 RadioButtomTableCell 无法正确保存值。 JavaFX
【发布时间】:2018-04-12 17:30:40
【问题描述】:

我有 TableView 和模型类,只有两个属性字段 nameselected。我尝试使用 RadioButton 制作 TableCell,它允许您选择一项且仅一项。问题是,当我单击 RadioButton 时,它会将新值保存到模型类,但未选择项中的旧值不会被覆盖,所以我有两个具有 selected 属性的项目,但它显示为只选择了一个。这是我的最小可执行代码。

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

数据模型类Model.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.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);
    }
}

【问题讨论】:

  • 可以发一下主课吗? (相反,您再次发布了单元实现。)
  • 抱歉,更新了问题。

标签: java javafx javafx-8


【解决方案1】:

我在您的自定义TableCell 中看到了对swing 的导入我并没有真正明白为什么,因为我看不到您在哪里使用它,但我认为这不是问题。如我所见,您永远不会将它们添加到ToggleGroup,它将它们分组,如果您选择其中一个,其他将被取消选择。

我写了一个简单的例子,它在TableCell 中使用了RadioButtons,我为每个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);
        }
    }

}

【讨论】:

  • 完美运行!谢谢!
猜你喜欢
  • 1970-01-01
  • 2017-01-12
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2020-11-15
  • 2015-03-18
相关资源
最近更新 更多