java - 刷新 TableView 中的一列组合框,javafx

标签 java javafx combobox javafx-8

所以我有一个包含 3 列的表格 View ,其中一列是组合框列,我创建组合框列的方式如下

    Source = new TableColumn<>("Configure Interface as..");
    Source.setCellValueFactory(i -> {
        final StringProperty value = i.getValue().optionProperty();
        // binding to constant value
        return Bindings.createObjectBinding(() -> value);
    });

    Source.setCellFactory(col -> {
        TableCell<TableViewTest, StringProperty> c = new TableCell<>();
        ComboBox<String> comboBox = new ComboBox<>(options);
        c.itemProperty().addListener((observable, oldValue, newValue) -> {
            if (oldValue != null) {
                comboBox.valueProperty().unbindBidirectional(oldValue);
            }
            if (newValue != null) {
                comboBox.valueProperty().bindBidirectional(newValue);
            }
        });
        c.graphicProperty().bind(Bindings.when(c.emptyProperty()).then((Node) null).otherwise(comboBox));
        return c;
    }); 

该列从位于我的 TableViewTest 类中的 getter 方法 optionProperty() 获取其值。

所以我遇到的问题是我的 gui 中的 tableview 表上方有另一个 combobox (comboBoxA),每当我更改comboBoxA 我想用列更改组合框的值。

我可以通过在监听组合框A的选择更改的方法中调用以下代码来完成此操作

Source.setCellValueFactory(i -> {
    final StringProperty value = i.getValue().optionTwoProperty();
    // binding to constant value
    return Bindings.createObjectBinding(() -> value);
});

但这些值不会改变,除非开始向下滚动到表格底部附近。有没有办法强制组合框在 getter 方法 optionTwoProperty() 中更改为新值,而无需我向下滚动?

编辑

好的,就这样吧

      final StringProperty value = i.getValue().optionTwoProperty();

在我开始向下滚动之前,实际上不会被调用。

最佳答案

因此,在 fabian 的帮助下,我想我明白您希望表格上方的组合框更改模型类中表格列的单元格中表示的属性。

实现此目的的一种方法是创建将模型类映射到属性的组合框函数的类型,并使用映射到您想要的每个属性的函数填充它。

然后,您可以使用绑定(bind)来表示表列的单元格值工厂,该绑定(bind)观察可以表示的所有可能属性以及组合框中的选定值,并返回通过应用来自组合框到模型实例(并检索其包装值)。

对于列的单元格工厂,您可以在单元格的组合框中观察所选值。当它发生变化时,使用表格上方组合框中的选定项目来确定要更新哪个属性。

这是 SSCCE:

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableWithSetAllComboBox extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();
        TableColumn<Item, String> itemCol = new TableColumn<>("Item");
        itemCol.setCellValueFactory(cellData -> Bindings.createStringBinding(() -> cellData.getValue().getName()));
        table.getColumns().add(itemCol);

        TableColumn<Item, String> choiceCol = new TableColumn<>("Choice");

        ComboBox<Function<Item, StringProperty>> option = new ComboBox<>();

        option.getItems().add(Item::choiceProperty);
        option.getItems().add(Item::choice2Property);

        option.setCellFactory(lv -> createListCell());
        option.setButtonCell(createListCell());

        option.getSelectionModel().select(0);           


        ObservableList<String> choices = FXCollections.observableArrayList("First choice", "Second choice", "Third choice");

        choiceCol.setCellFactory(col -> {
            TableCell<Item, String> cell = new TableCell<>();
            ComboBox<String> combo = new ComboBox<>(choices);
            cell.graphicProperty().bind(Bindings.when(cell.emptyProperty()).then((Node)null).otherwise(combo));
            combo.valueProperty().addListener((obs, oldValue, newValue) -> {
                if (! cell.isEmpty() && newValue != null) {
                    Item item = table.getItems().get(cell.getIndex()) ;
                    StringProperty property = option.getValue().apply(item);
                    property.set(newValue);
                }
            });
            cell.itemProperty().addListener((obs, oldItem, newItem) -> combo.setValue(newItem));
            return cell ;
        });

        choiceCol.setPrefWidth(150);

        table.getColumns().add(choiceCol);

        choiceCol.setCellValueFactory(cellData -> Bindings.createStringBinding( 
                () -> option.getValue().apply(cellData.getValue()).get(), 
                cellData.getValue().choiceProperty(), 
                cellData.getValue().choice2Property(),
                option.valueProperty()));

        choiceCol.setGraphic(option);

        choiceCol.setPrefWidth(200);

        for (int i = 1; i <= 30 ; i++) table.getItems().add(new Item("Item "+i ,choices.get(0)));

        Button debug = new Button("Debug");
        debug.setOnAction(e -> table.getItems().stream().
                map(item -> String.format("%s (%s, %s)", item.getName(), item.getChoice(), item.getChoice2())).
                forEach(System.out::println));

        BorderPane root = new BorderPane(table);
        BorderPane.setMargin(debug, new Insets(5));
        root.setBottom(debug);

        primaryStage.setScene(new Scene(root, 600, 600));
        primaryStage.show();
    }

    private ListCell<Function<Item, StringProperty>> createListCell() {
        return new ListCell<Function<Item, StringProperty>>() {
            @Override
            public void updateItem(Function<Item, StringProperty> item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty ? null : item.apply(new Item("", "")).getName());
            }
        };
    }

    public static class Item {
        private final String name ;
        private final StringProperty choice ;

        private final StringProperty choice2 ;

        public Item(String name, String choice) {
            this.choice = new SimpleStringProperty(this, "Choice", choice);
            this.choice2 = new SimpleStringProperty(this, "Choice 2", "Second choice");
            this.name = name ;
        }

        public final StringProperty choiceProperty() {
            return this.choice;
        }

        public final java.lang.String getChoice() {
            return this.choiceProperty().get();
        }

        public final void setChoice(final java.lang.String choice) {
            this.choiceProperty().set(choice);
        }

        public String getName() {
            return name;
        }
        public final StringProperty choice2Property() {
            return this.choice2;
        }

        public final java.lang.String getChoice2() {
            return this.choice2Property().get();
        }

        public final void setChoice2(final java.lang.String choice2) {
            this.choice2Property().set(choice2);
        }

    }

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

关于java - 刷新 TableView 中的一列组合框,javafx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35727262/

相关文章:

java - 连续生成随机枚举值而不两次获得相同的值

javafx - 输入键事件在 Javafx 对话框中不起作用?

JavaFX 与 Java Swing

c# - 两个组合框上的空第一个值相互更新

.net - Winforms ComboBox SelectedValueChange 事件

java - 在 tomcat 版本 8.0.24 中放置类和 beans 文件的位置

java - 加快 Java 版 WordNet 词形还原器的使用速度

java - 为什么 JavaFX API 不包含在 Java 8 J2SE 中?

javascript - 专业的基于 jQuery 的 Combobox 控件?

java - replaceAll 悬挂元字符