java - TableView 中 RadioButton 的奇怪行为

标签 java javafx radio-button tableview

我的问题是关于 tableView 中化合物的奇怪行为。 目的是在 tableView 中显示参加比赛的玩家列表。显示的信息包括玩家的姓名、他的分数、他的连续失败次数以及一个指示器,用于了解是否轮到他玩。

该指示器是一个 RadioButton,因为它看起来比一个复选框更好。当轮到玩家时,RadioButton 将被设置为 setSelected(true),否则,它将被设置为 setSelected(false)。真假信息由tableView中使用的玩家信息给出。当然,RadioButton 处于“只读”模式。

这是我的 tableView 代码:

TableView<PlayerProgressInformations> playersProgressTable = new TableView<PlayerProgressInformations>();       
defineColumns(playersProgressTable);
playersProgressTable.setItems(playersAtThisTable);

对于 defineColumns 方法:

TableColumn<PlayerProgressInformations, Boolean> colPlaying = new TableColumn<PlayerProgressInformations, Boolean>("Tour");
colPlaying.setPrefWidth(70);
TableCell<PlayerProgressInformations, Boolean>>) new RadioButton());

colPlaying.setCellValueFactory(new Callback<CellDataFeatures<PlayerProgressInformations, Boolean>, ObservableValue<Boolean>>() {
    public ObservableValue<Boolean> call(CellDataFeatures<PlayerProgressInformations, Boolean> p) {
        return new SimpleBooleanProperty(p.getValue().isPlaying());
        }
    });

colPlaying.setCellFactory(new Callback<TableColumn<PlayerProgressInformations, Boolean>, TableCell<PlayerProgressInformations, Boolean>>() {

    @Override
    public TableCell<PlayerProgressInformations, Boolean> call( TableColumn<PlayerProgressInformations, Boolean> param) {
        RadioButtonCell<PlayerProgressInformations, Boolean> radioButtonCell = 
            new RadioButtonCell<PlayerProgressInformations, Boolean>();
        return radioButtonCell;
    }           
});

还有 RadioButtoCell 类:

private class RadioButtonCell<S, T> extends TableCell<S,T> {
    public RadioButtonCell () {
    }

    @Override
    protected void updateItem (T item, boolean empty) {

        System.out.println("Count value : "+count); //Indicator to check how many times is used the method "updateItem"
        count+=1;
        if (item instanceof Boolean) {
            Boolean myBoolean = (Boolean) item;
            if (!empty) {
                System.out.println("Valeur du boolean : "+item);
                RadioButton radioButton = new RadioButton();
                radioButton.setDisable(true);
                radioButton.setSelected(myBoolean);
                radioButton.setStyle("-fx-opacity: 1");                 
                setGraphic(radioButton);
            }
        }                       
    }
}

奇怪的行为如下:

  • 问题 1:当我将第一位玩家加入游戏 table 时,updateItem 方法被调用了 17 次。 如果第二个加入,第一个玩家的这个数字增加到 57,或者第二个玩家的 60 和 17。 最后,如果有第三个人加入,则第一个人为 90 次,第二个人为 57 或 60 次,第三个人为 17 次。 为什么经常调用此方法?为什么是那些特定的数字? 此外,在这个“初始化”之后,该方法在每一轮之后都会像我预期的那样被调用 2 次:一次取消选择 RadioButton,一次选择下一个。

  • 问题 2:当第一个玩家加入 table 时,他当然是第一个开始玩的,并且在他的屏幕上,RadioButton 被选中。 当第二个玩家加入 table 时,第二个玩家会看到为第一个玩家选择的 RadioButton 和为他自己取消选择的 RadioButton。这是预期的行为。但对于第一个玩家,2 个 RadioButtons 未被选中。 如果第 3 个玩家加入表,他会看到 RadioButton 为第一个玩家选中,而为他自己和第 2 个玩家取消选中。这也是预期的结果。但是,对于第二个和第一个玩家,所有 3 个 RadioButtons 都未被选中。 为什么会有这种奇怪的行为?此外,在第一轮之后,所有 RadioButton 都按预期显示为选中或未选中,就好像错误消失了一样。

您能帮我了解发生了什么以及如何解决这些错误吗?

非常感谢

最佳答案

示例代码

这是一个有效的表实现。我想您可以将它与您的实现进行比较,看看有什么不同。可能主要的“修复”是空值和空值的 updateItem 处理。

pic

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

public class PlayerViewer extends Application {

    private final ObservableList<Player> data =
        FXCollections.observableArrayList(
            new Player("Jacob", true),
            new Player("Isabella", false),
            new Player("Ethan", true)
        );

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

    @Override
    public void start(Stage stage) {
        TableView<Player> table = new TableView<>(data);
        table.setPrefHeight(130);
        table.setPrefWidth(150);

        TableColumn<Player, String> handleCol = new TableColumn<>("Handle");
        handleCol.setCellValueFactory(new PropertyValueFactory<>("handle"));
        table.getColumns().add(handleCol);

        TableColumn<Player, Boolean> playingCol = new TableColumn<>("Playing");
        playingCol.setCellValueFactory(new PropertyValueFactory<>("playing"));
        playingCol.setCellFactory(param -> new TableCell<>() {
            RadioButton indicator = new RadioButton();

            {
                indicator.setDisable(true);
                indicator.setStyle("-fx-opacity: 1");
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            }

            @Override
            protected void updateItem(Boolean isPlaying, boolean empty) {
                super.updateItem(isPlaying, empty);

                if (empty || isPlaying == null) {
                    setGraphic(null);
                } else {
                    indicator.setSelected(isPlaying);
                    setGraphic(indicator);
                }
            }
        });
        table.getColumns().add(playingCol);

        stage.setScene(new Scene(table));
        stage.show();
    }

    public static class Player {
        private final SimpleStringProperty handle;
        private final SimpleBooleanProperty playing;

        private Player(String handle, boolean playing) {
            this.handle = new SimpleStringProperty(handle);
            this.playing = new SimpleBooleanProperty(playing);
        }

        public SimpleStringProperty handleProperty() {
            return handle;
        }
        public String getHandle() {
            return handle.get();
        }
        public void setHandle(String handle) {
            this.handle.set(handle);
        }

        public SimpleBooleanProperty playingProperty() {
            return playing;
        }
        public boolean isPlaying() {
            return playing.get();
        }
        public void setPlaying(boolean playing) {
            this.playing.set(playing);
        }
    }
}

对您的问题的补充意见

就“问题 1”而言,调用 updateItem 的次数是内部工具包的事情,您的代码不应该真正关心它,它只需要确保无论何时调用它,它都会执行正确的事情。

关于您的“问题2”,关于多个玩家的多个 View 的交互,谁知道呢?如果没有进一步的附加代码就不可能说,这可能最终会使这个问题变得过于宽泛。如果您有关于如何处理多个玩家的显示交互的具体问题,您将需要扩展和澄清您的问题(可能是带有 mcve 的新问题)。

对于您的实现,我建议重新设计单选按钮的样式(通过 CSS),使其看起来不像标准的用户可选单选按钮(因为您禁用了选择功能,然后删除了默认禁用的不透明度设置).或者,您可以使用自定义指示器控件,例如 this answer 中的 Bulb 类,这可能是首选。

关于java - TableView 中 RadioButton 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48408346/

相关文章:

java - OpenJDK 的 LinkedBlockingQueue 实现 : Node class and GC

Android:单选按钮在一个单选组中对齐 2 x 2

java - 如何模拟扩展另一个接口(interface)的接口(interface)

java - 用于隐藏 Java Web 服务的身份验证详细信息的外观

java - Hibernate HBM2DDL 为主外键生成可为空字段?

css - 如何在javafx中计算css外观的效果?

执行过程时 JavaFX 不确定进度条

javafx - 如何在新的 JavaFx 错误跟踪器中查找错误

asp.net - 图像单选按钮 - NFL Weekly

radio-button - 如何使用 React 只选择一个单选按钮