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

Posted

技术标签:

【中文标题】Javafx:TableView根据行列获取特定表格单元格的图形节点【英文标题】:Javafx: TableView get graphic node of a particular Table cell based on row column 【发布时间】:2017-09-10 07:40:09 【问题描述】:

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

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

请找到我需要的快照:

这是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 SamplingPtX 和 SamplingPtY 组合列表是静态加载的。与ModelInput 无关。我需要执行的所有操作是选择校准组合框,我必须在 SamplingPtX & Y 中设置特定项目,组合框对应的行。 ModelInput 是否包含 3 列值?作为 SimpleStringProperty?它还遗漏了 seItems 部分和 setCellValueFactory 绑定。 (在全球范围内,我们需要更多资源来获得完整的可测试示例) @pdem No ModelInput 实际上没有 3 Coulmns 的数据。还有另一列,其数据取自 ModelInput 作为 SimpleStringProperty。这在图像中不可见。 【参考方案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 是不可见的。您必须在行元素上显式双击。 这个想法是用户必须使用 ComboBox,因此必须设置另一个 ComboBox。编辑每一行时没有提交任何内容。 @zIronManBox 虽然我不明白你为什么坚持不使用通常的 ComboBox-TextField 样式(我无法想象一个有 20 行显示 60 个 ComboBoxes 的表格),但另一种方法是制作一个 @ 987654323@,然后手动设置并获取updateItem()中的ComboBox【参考方案2】:

您可以从 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 );

【讨论】:

我问的问题是'在选择一个组合框时,我需要在另一个组合框中选择项目'。您所说的已添加到选择侦听器中。另外,我只需要知道,我怎样才能在对应行的另一个TableColumn 上设置GraphicNode 对不起,我的回答的重点是在这种情况下不需要gettnig GraphicNode来设置另一个ComboBox。 如果你看到了,我没有使用根元素来修改东西。填充到其他列的数据不是来自父元素。它在每列的cellFactoryupdate 方法的运行时加载。 this question 中提到访问 Cell 不是好方法。您可以在Example 12-5 Setting Data Properties to Columns 中找到如何使用定义数据模型。不要忘记每个更新模型的属性会自动触发updateItem(T, boolean)

以上是关于Javafx:TableView根据行列获取特定表格单元格的图形节点的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX 2 TableView:根据单元格内的数据不同的单元格工厂

JavaFX,如何冻结TableView中某些列的位置

JavaFX:按行和列获取节点

从 JavaFX TableView 中获取选定项目

JavaFX布尔绑定和TableView绑定多个

用于大型数据库表的 JavaFx TableView CRUD