【问题标题】:javafx ListView with custom cell factory not retaining the selected cell具有自定义单元工厂的 javafx ListView 不保留所选单元格
【发布时间】:2016-11-09 12:40:29
【问题描述】:

我有一个 controlsfx CheckListView(甚至与 javafx ListView 控件相同的问题),我想在其中显示 RadioButtons 而不是 CheckBox。因此,我通过几个 javafx 教程的帮助实现了自定义单元工厂,并且它正在工作。 问题是我选择了第一个单选按钮并向下滚动一点,以便我的顶部单选按钮很少向上滚动并且现在不可见。然后我再次向上滚动,现在选择消失了。

我调试代码了解到每次都会创建新单元格,这会导致此问题,但不幸的是无法找出解决方案。

我附上了一个示例代码,它是从堆栈溢出中得到的,它有同样的问题。

package application;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class RadioButtonListView extends Application {

    public static final ObservableList names = FXCollections.observableArrayList();
    private ToggleGroup group = new ToggleGroup();

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("List View Sample");

        final ListView listView = new ListView();
        listView.setPrefSize(200, 250);
        listView.setEditable(true);

        names.addAll("Adam", "Alex", "Alfred", "Albert", "Brenda", "Connie", "Derek", "Donny", "Lynne", "Myrtle", "Rose", "Rudolph", "Tony", "Trudy", "Williams", "Zach");

        listView.setItems(names);
        listView.setCellFactory(param -> new RadioListCell());
        StackPane root = new StackPane();
        root.getChildren().add(listView);
        primaryStage.setScene(new Scene(root, 200, 250));
        primaryStage.show();
    }

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

    private class RadioListCell extends ListCell<String> {
        @Override
        public void updateItem(String obj, boolean empty) {
            super.updateItem(obj, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                RadioButton radioButton = new RadioButton(obj);
                radioButton.setToggleGroup(group);
                // Add Listeners if any
                setGraphic(radioButton);
            }
        }
    }
}

这方面需要你的帮助。(我使用的是 javafx 8)

【问题讨论】:

    标签: javafx java-8 javafx-2 javafx-8


    【解决方案1】:

    您应该为单元格创建一个单选按钮(而不是每次调用 updateItem(...) 时都创建一个新单选按钮,并使用数据表示中的适当逻辑在 updateItem(...) 方法中更新其选定状态。

    private class RadioListCell extends ListCell<String> {
    
        private final RadioButton radioButton = new RadioButton();
    
        RadioListCell() {
            radioButton.setToggleGroup(group);
            // Add listeners here...
        }
    
        @Override
        public void updateItem(String obj, boolean empty) {
            super.updateItem(obj, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                radioButton.setText(obj);
    
                radioButton.setSelected(...);
    
                setGraphic(radioButton);
            }
        }
    }
    

    例如:

    import java.util.Objects;
    
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Scene;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.scene.control.RadioButton;
    import javafx.scene.control.ToggleGroup;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class RadioButtonListView extends Application {
    
        public static final ObservableList<String> names = FXCollections.observableArrayList();
        private ToggleGroup group = new ToggleGroup();
    
        private String selectedName ;
    
        @Override
        public void start(Stage primaryStage) {
            primaryStage.setTitle("List View Sample");
    
            final ListView<String> listView = new ListView<>();
            listView.setPrefSize(200, 250);
            listView.setEditable(true);
    
            names.addAll("Adam", "Alex", "Alfred", "Albert", "Brenda", "Connie", "Derek", "Donny", "Lynne", "Myrtle", "Rose", "Rudolph", "Tony", "Trudy", "Williams", "Zach");
    
            listView.setItems(names);
            listView.setCellFactory(param -> new RadioListCell());
            StackPane root = new StackPane();
            root.getChildren().add(listView);
            primaryStage.setScene(new Scene(root, 200, 250));
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        private class RadioListCell extends ListCell<String> {
    
            private final RadioButton radioButton = new RadioButton();
    
            RadioListCell() {
                radioButton.setToggleGroup(group);
                radioButton.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
                    if (isNowSelected) {
                        selectedName = getItem();
                    }
                });
            }
    
            @Override
            public void updateItem(String obj, boolean empty) {
                super.updateItem(obj, empty);
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    radioButton.setText(obj);
    
                    radioButton.setSelected(Objects.equals(obj, selectedName));
    
                    setGraphic(radioButton);
                }
            }
        }
    }
    

    【讨论】:

    • 你拯救了我的一天。非常感谢。实际上,我尝试了相同的方法,但不知何故在中间迷路了。我想把这个告诉你。您的解决方案正在运行,但如果我选择第一个单选按钮,它会被选中,但第 11 个单选按钮的轮次(如果 10 个按钮可见)也会突出显示。 (未选择但获得焦点)。暂时不是问题。再次感谢。
    • @SaravanaKumar 我知道为什么会发生这种情况,但我无法可靠地重现它。单元格中的选择/焦点有点棘手。
    猜你喜欢
    • 2016-04-22
    • 1970-01-01
    • 2013-10-15
    • 2013-11-27
    • 2015-02-09
    • 1970-01-01
    • 2016-05-13
    • 2012-05-18
    • 2018-04-09
    相关资源
    最近更新 更多