javafx ListView与自定义单元工厂不保留所选单元格

时间:2016-11-09 12:40:29

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

我有一个controlfx 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)

1 个答案:

答案 0 :(得分:4)

您应该为单元格创建一个单选按钮(而不是每次调用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);
            }
        }
    }
}