Javafx:根据行列获取特定表格单元格的图形节点

4
我有一个JavaFX表格视图组件,并且正在使用ComboBox作为单个列的setGraphic动态加载数据。我想在cellFactory中添加ComboBox

现在,当用户选择第一个ComboBox时,下一列ComboBox必须相应地设置。 为此,我使用了选择侦听器,但是如何获取其他TableColumnComboBox

请查看我所需要的快照: enter image description here

这是TableView的片段:

        TableColumn< ModelInput, String > colCalibration = new TableColumn<>( "Calibration" );
        TableColumn< ModelInput, String > colSamplingX = new TableColumn<>( "Sampling point X" );
        TableColumn< ModelInput, String > colSamplingY = new TableColumn<>( "Sampling point Y" );
        List< TableColumn< ModelInput, String > > tableColList =
            Stream.of( colCalibration, colSamplingX, colSamplingY )
                  .collect( Collectors.toList() );
        tableviewCalibMatching.getColumns().addAll( tableColList );

        //initialize
        colCalibration.setCellFactory( param -> new TableCell< ModelInput, String >() {

          @Override
          public void updateItem( String item, boolean empty ) {
            super.updateItem( item, empty );
            if( empty ) {
              setText( null );
            } else {
              ComboBox< String > comboBoxCalibMatchingNames = new ComboBox<>( listCalibNames );
              comboBoxCalibMatchingNames.setPrefWidth( splitWidth );
              comboBoxCalibMatchingNames.getSelectionModel().selectedItemProperty()
                                        .addListener( (ChangeListener< String >)( observable, oldValue,
                                            newValue ) -> {

//TODO
//How can I get ComboBox of other TableColumn, need to set according to current //selection

                                        } );
              setGraphic( comboBoxCalibMatchingNames );
              setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
            }
          }
        } );

        colSamplingX.setCellFactory( param -> new TableCell< ModelInput, String >() {

          @Override
          public void updateItem( String item, boolean empty ) {
            super.updateItem( item, empty );
            if( empty ) {
              setText( null );
            } else {
              final ComboBox< String > comboBox = new ComboBox<>();
              setGraphic( comboBox );
              setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
            }
          }
        } );

        colSamplingY.setCellFactory( param -> new TableCell< ModelInput, String >() {

          @Override
          public void updateItem( String item, boolean empty ) {
            super.updateItem( item, empty );
            if( empty ) {
              setText( null );
            } else {
              final ComboBox< String > comboBox = new ComboBox<>();
              setGraphic( comboBox );
              setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
            }
          }
        } );

这三个列表之间有什么关系?如果我选择了特定的校准值,它会生成一个全新的采样点X和Y列表吗?这些列表是否在“ModelInput”中,并且它们是如何定义的? - Jai
@Jai SamplingPtX和SamplingPtY组合框是静态加载的,与“ModelInput”无关。我需要做的就是在选择校准组合框时,为相应行设置SamplingPtX和Y组合框中的特定项目。 - zIronManBox
ModelInput是否包含3列值作为SimpleStringProperty?它还缺少seItems部分和setCellValueFactory绑定。(全局而言,我们需要更多资源来提供完整的可测试示例) - pdem
@pdem ModelInput并没有真正拥有三个列的数据。还有另一列,其数据通过SimpleStringProperty从ModelInput中取得。这在图像中是不可见的。 - zIronManBox
2个回答

1

试试这个:

public class Test
{
    private final TableView<ModelInput> tableviewCalibMatching = new TableView<>();

    private final TableColumn<ModelInput, String> colCalibration = new TableColumn<>("Calibration");
    private final TableColumn<ModelInput, String> colSamplingX = new TableColumn<>("Sampling Point X");
    private final TableColumn<ModelInput, String> colSamplingY = new TableColumn<>("Sampling Point Y");

    private final ObservableList<String> listCalibNames = FXCollections.observableArrayList();
    private final ObservableList<String> listSamplingXNames = FXCollections.observableArrayList();
    private final ObservableList<String> listSamplingYNames = FXCollections.observableArrayList();

    private final ObservableList<ModelInput> items = FXCollections.observableArrayList();

    public Test()
    {
        tableviewCalibMatching.setItems(items);
        tableviewCalibMatching.getColumns().addAll(colCalibration, colSamplingX, colSamplingY);

        colCalibration.setCellFactory(ComboBoxTableCell.forTableColumn(listCalibNames));
        colSamplingX.setCellFactory(ComboBoxTableCell.forTableColumn(listSamplingXNames));
        colSamplingY.setCellFactory(ComboBoxTableCell.forTableColumn(listSamplingYNames));

        colCalibration.setCellValueFactory(new PropertyValueFactory<>("calibration"));
        colSamplingX.setCellValueFactory(new PropertyValueFactory<>("samplingX"));
        colSamplingY.setCellValueFactory(new PropertyValueFactory<>("samplingY"));

        colCalibration.setOnEditCommit(event ->
        {
            final String newCalibrationValue = event.getNewValue();

            event.getRowValue().setCalibration(newCalibrationValue);

            // You can change the logic here based on what you need
            event.getRowValue().setSamplingX(listSamplingXNames.get(1));
            event.getRowValue().setSamplingY(listSamplingXNames.get(1));
        });

        colSamplingX.setOnEditCommit(event ->
        {
            final String newSamplingXValue = event.getNewValue();

            event.getRowValue().setSamplingX(newSamplingXValue);
        });

        colSamplingY.setOnEditCommit(event ->
        {
            final String newSamplingYValue = event.getNewValue();

            event.getRowValue().setSamplingY(newSamplingYValue);
        });
    }

    public static class ModelInput
    {
        private final StringProperty calibration = new SimpleStringProperty();
        private final StringProperty samplingX = new SimpleStringProperty();
        private final StringProperty samplingY = new SimpleStringProperty();

        public final StringProperty calibrationProperty()
        {
            return this.calibration;
        }

        public final String getCalibration()
        {
            return this.calibrationProperty().get();
        }

        public final void setCalibration(final String calibration)
        {
            this.calibrationProperty().set(calibration);
        }

        public final StringProperty samplingXProperty()
        {
            return this.samplingX;
        }

        public final String getSamplingX()
        {
            return this.samplingXProperty().get();
        }

        public final void setSamplingX(final String samplingX)
        {
            this.samplingXProperty().set(samplingX);
        }

        public final StringProperty samplingYProperty()
        {
            return this.samplingY;
        }

        public final String getSamplingY()
        {
            return this.samplingYProperty().get();
        }

        public final void setSamplingY(final String samplingY)
        {
            this.samplingYProperty().set(samplingY);
        }
    }
}

默认情况下,ComboBox 是不可见的。您需要显式地双击行元素。 - zIronManBox
这个想法是用户必须使用ComboBox,并相应地设置其他ComboBox。在每行的编辑中没有任何提交。 - zIronManBox
@zIronManBox 虽然我不明白为什么你坚持不使用通常的ComboBox-TextField样式(我无法想象一个显示60个ComboBox的20行表格),但另一种选择是创建一个Map<ModelInput, ComboBox[]>,然后在updateItem()中手动设置和获取ComboBox - Jai

-1
您可以通过TableCell::getIndex()获取当前行。 首先,更新包含在TableView项中的对象。
comboBoxCalibMatchingNames.setOnAction(event -> {
    tableView.getItems().get(getIndex()).someProperty().set(anyValue1);
    tableView.getItems().get(getIndex()).otherProperty().set(anyValue2);
});

它将使用新值触发已更新列的TableCell :: updateItem(T,boolean)。 您必须在updateItem上更新ComboBox的选择。

// in updteItem code on colSamplingX
final ComboBox< String > comboBox = new ComboBox<>();
comboBox.getSelectionModel().select(item);    // Select updated item.
setGraphic( comboBox );
setContentDisplay( ContentDisplay.GRAPHIC_ONLY );

我提出的问题是:“在选择一个comboBox时,我需要在另一个ComboBox中选择项目。”你所说的已经添加到选择监听器中了。此外,我只需要知道如何获取对应行另一个TableColumn上已设置的GraphicNode。 - zIronManBox
抱歉,我的回答的重点是在这种情况下没有必要让GraphicNode设置另一个ComboBox。 - monolith52
如果你看到了,我没有使用根元素来修改东西。填充到其他列中的数据不是来自父元素。它是在每个列的cellFactoryupdate方法运行时加载的。 - zIronManBox
这个问题 中提到访问单元格不是一个好方法。你可以在 示例 12-5 将数据属性设置到列中 中找到如何使用定义的数据模型。不要忘记每次更新模型的属性都会自动触发 updateItem(T, boolean) 方法。 - monolith52

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接