javaFX:listview selectionmodel中的单选按钮

javaFX:listview selectionmodel中的单选按钮,java,javafx,Java,Javafx,我需要单选按钮在列表视图中,因此我找到了以下答案: 但问题是ListView中选定的单元格和选定的RadioButton未绑定。如果单击列表中的单元格,我希望自动选择相应的单选按钮 所以我的问题是如何将这两者结合起来 更新: 因此,我唯一能做到这一点的方法与@Sedrick Jefferson answer类似,但没有在RadioButton前面添加StackPane。 我将单选按钮列表名称单选按钮添加到切换组,并将侦听器添加到selectedToggleProperty:选择新建单选按钮时,

我需要
单选按钮
列表视图
中,因此我找到了以下答案:

但问题是
ListView
中选定的单元格和选定的
RadioButton
未绑定。如果单击列表中的单元格,我希望自动选择相应的
单选按钮

所以我的问题是如何将这两者结合起来

更新: 因此,我唯一能做到这一点的方法与@Sedrick Jefferson answer类似,但没有在
RadioButton
前面添加
StackPane
。 我将
单选按钮列表
名称单选按钮添加到
切换组
,并将侦听器添加到
selectedToggleProperty
:选择新建
单选按钮
时,我在
列表视图中选择相应的行

    import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
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.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class RadioButtonListView extends Application
{

    public static final ObservableList<RadioButton> namesRadioButtons
            = FXCollections.observableArrayList();
    private ToggleGroup group = new ToggleGroup();

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

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

        String[] names =
        {
            "Adam", "Alex", "Alfred", "Albert",
            "Brenda", "Connie", "Derek", "Donny",
            "Lynne", "Myrtle", "Rose", "Rudolph",
            "Tony", "Trudy", "Williams", "Zach"
        };

        for (String name : names)
        {
            namesRadioButtons.add(new RadioButton(name));
        }
        group.getToggles().addAll(namesRadioButtons);
        listView.setItems(namesRadioButtons);
        group.selectedToggleProperty().addListener((obs, oldSel, newSel) -> {
            listView.getSelectionModel().select((RadioButton) newSel);
            listView.getFocusModel().focus(listView.getSelectionModel().getSelectedIndex());
        });
        listView.setCellFactory(param -> new RadioListCell());
        listView.getSelectionModel().selectedItemProperty().addListener((obs, oldSel, newSel) ->
        {
            if (newSel != null)
            {
                RadioButton tempRadioButton = (RadioButton) newSel;
                tempRadioButton.setSelected(true);
            }
            if (oldSel != null)
            {
                RadioButton tempRadioButton = (RadioButton) oldSel;
                tempRadioButton.setSelected(false);
            }
        });

        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<RadioButton>
    {

        @Override
        public void updateItem(RadioButton obj, boolean empty)
        {
            super.updateItem(obj, empty);
            if (empty)
            {
                setText(null);
                setGraphic(null);
            }
            else
            {
                setGraphic(obj);
            }
        }

    }
}
导入javafx.application.application;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.ListCell;
导入javafx.scene.control.ListView;
导入javafx.scene.control.RadioButton;
导入javafx.scene.control.ToggleGroup;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.StackPane;
导入javafx.stage.stage;
公共类RadioButtonListView扩展了应用程序
{
公共静态最终可观察列表名称单选按钮
=FXCollections.observableArrayList();
private-ToggleGroup-group=new-ToggleGroup();
@凌驾
公共无效开始(阶段primaryStage)
{
setTitle(“列表视图示例”);
最终ListView ListView=新建ListView();
setPrefSize(200250);
listView.setEditable(true);
字符串[]名称=
{
“亚当”、“亚历克斯”、“阿尔弗雷德”、“阿尔伯特”,
“布伦达”,“康妮”,“德里克”,“唐尼”,
“林恩”、“桃金娘”、“玫瑰”、“鲁道夫”,
“托尼”、“特鲁迪”、“威廉姆斯”、“扎克”
};
for(字符串名称:名称)
{
名称RadioButtons.add(新的RadioButton(名称));
}
group.getToggles().addAll(名称单选按钮);
setItems(名称单选按钮);
group.selectedToggleProperty().addListener((obs、oldSel、newSel)->{
listView.getSelectionModel().select((单选按钮)newSel);
listView.getFocusModel().focus(listView.getSelectionModel().getSelectedIndex());
});
setCellFactory(参数->新建RadioListCell());
listView.getSelectionModel().SelectEditeProperty().addListener((obs、oldSel、newSel)->
{
if(newSel!=null)
{
RadioButton tempRadioButton=(RadioButton)newSel;
tempRadioButton.setSelected(真);
}
如果(oldSel!=null)
{
RadioButton tempRadioButton=(RadioButton)oldSel;
tempRadioButton.setSelected(假);
}
});
StackPane root=新的StackPane();
root.getChildren().add(listView);
原始阶段。设置场景(新场景(根,200250));
primaryStage.show();
}
公共静态void main(字符串[]args)
{
发射(args);
}
私有类RadioListCell扩展了ListCell
{
@凌驾
public void updateItem(RadioButton obj,布尔空)
{
super.updateItem(对象,空);
if(空)
{
setText(空);
设置图形(空);
}
其他的
{
设置图形(obj);
}
}
}
}

问题:有没有更好的解决办法

重复:添加控件作为数据项不是解决方案

相反,使用一个自定义单元格,该单元格根据需要具有一个控件,并使用项/列表/选择的状态进行配置,就像在中一样。唯一缺少的部分是反向同步(从无线电状态到列表选择):要实现这一点,请在单元中安装一个侦听器

类似(修改后的示例):

公共类RadioButtonListView扩展应用程序{
公共静态最终可观察列表名称=
FXCollections.observableArrayList();
private-ToggleGroup-group=new-ToggleGroup();
@凌驾
公共无效开始(阶段primaryStage){
setTitle(“列表视图示例”);
最终ListView ListView=新建ListView();
setPrefSize(200250);
listView.setEditable(true);
name.addAll(
“亚当”、“亚历克斯”、“阿尔弗雷德”、“阿尔伯特”,
“布伦达”,“康妮”,“德里克”,“唐尼”,
“林恩”、“桃金娘”、“玫瑰”、“鲁道夫”,
“托尼”、“特鲁迪”、“威廉姆斯”、“扎克”
);
setItems(名称);
setCellFactory(参数->新建RadioListCell());
StackPane root=新的StackPane();
root.getChildren().add(listView);
原始阶段。设置场景(新场景(根,200250));
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
私有类RadioListCell扩展了ListCell{
单选按钮单选按钮;
ChangeListener radioListener=(src、ov、nv)->radioChanged(nv);
WeakChangeListener weakRadioListener=新的WeakChangeListener(radioListener);
公共放射室(){
radioButton=新的radioButton();
radioButton.selectedProperty().addListener(weakRadioListener);
radioButton.setFocusTraversable(假);
//让它跨越列表的整个宽度
//fx8中需要更新选择状态
radioButton.setMaxWidth(双倍最大值);
}
受保护的无效项已更改(已选择布尔值){
if(selected&&getListView()!=null&&isEmpty()&&getIndex()>=0){
getListView().getSelectionModel().select(getIndex());
}
}
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> {

        RadioButton radioButton;
        ChangeListener<Boolean> radioListener = (src, ov, nv) -> radioChanged(nv);
        WeakChangeListener<Boolean> weakRadioListener = new WeakChangeListener(radioListener);

        public RadioListCell() {
            radioButton = new RadioButton();
            radioButton.selectedProperty().addListener(weakRadioListener);
            radioButton.setFocusTraversable(false);
            // let it span the complete width of the list
            // needed in fx8 to update selection state
            radioButton.setMaxWidth(Double.MAX_VALUE);
        }

        protected void radioChanged(boolean selected) {
            if (selected && getListView() != null && !isEmpty() && getIndex() >= 0) {
                getListView().getSelectionModel().select(getIndex());
            }
        }

        @Override
        public void updateItem(String obj, boolean empty) {
            super.updateItem(obj, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
                radioButton.setToggleGroup(null);
            } else {
                radioButton.setText(obj);
                radioButton.setToggleGroup(group);
                radioButton.setSelected(isSelected());
                setGraphic(radioButton);
            }
        }
    }
}