我的问题是关于 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
处理。
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/