为 javaFx 表视图中的每一行动态填充组合框列表

Posted

技术标签:

【中文标题】为 javaFx 表视图中的每一行动态填充组合框列表【英文标题】:Populate combo box list dynamically for each row in javaFx table view 【发布时间】:2015-06-05 21:34:36 【问题描述】:

我在 java Fx 中创建了一个表视图,表视图中的列之一包括 ComboBoxTableCell.请在下面找到表格视图的代码

public class TabViewController 
    @FXML
    private TabPane cnfmTab;

    @FXML
    private TableView<TabVO> partsTable;

    @FXML
    private TableColumn<TabVO, String> column1;

    @FXML
    private TableColumn<TabVO, String> column2;

    @FXML
    private TableColumn<TabVO, String> column3;

    private ObservableList<TabVO> tableData = FXCollections.observableArrayList();

    private ObservableList<String> column1List;

    @FXML
    public void initialize()

    tableData = FXCollections.observableArrayList(callDAO.getTableData(1));

    column1.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getColumn1()));

    column1
        .setCellFactory(new Callback<TableColumn<tabVO, String>, TableCell<tabVO, String>>() 
            @SuppressWarnings( "rawtypes", "unchecked" )
            public TableCell call(TableColumn p) 
                ComboBoxTableCell cell = new ComboBoxTableCell(column1List)
                    @Override
                    public void updateItem(Object item, boolean empty) 


                    
                ;
                cell.setAlignment(Pos.CENTER);
                return cell;
            
        );

    column1.setOnEditCommit(
                new EventHandler<CellEditEvent<tabVO, String>>() 
                    @Override
                    public void handle(CellEditEvent<tabVO,String> t) 

                    ;
                
                );
    

    partsTable.setItems(tableData);

数据对象:

public class TabVO 


    private String column1; 

    private String column2; 

    private String column3;

    private ObservableList<String> column1List;


    /* Getters and Setters */


在上面的代码中,表格的每一行都是 TabVo 类型。

在表中 column1 是类型组合框。现在 column1 组合框的列表由 在“TabViewController”中声明的“column1List”,因为它填充了表格视图的所有行 使用相同的下拉菜单。

但我希望表格的每一行都填充有 TabVo 中存在的不同列表。

谁能告诉我如何访问 TabVo 对象并使用 TabVo 中存在的列表填充组合框?

【问题讨论】:

我如何仅使用 FXML 执行此操作?我有一家工厂,但我不能给它一个清单。 【参考方案1】:

这是一个带有问题中描述的用例的 MVCE:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;


public class ComboBoxCellTableExample extends Application


    private final TableView<TabVo> table = new TableView<>();
    private final ObservableList<TabVo> data
            = FXCollections.observableArrayList(
                    new TabVo( "2222", "column2", FXCollections.<String>observableArrayList( "111", "2222", "3333" ) ),
                    new TabVo( "bbbb", "column2", FXCollections.<String>observableArrayList( "aaaa", "bbbb", "ccccc" ) ),
                    new TabVo( "6666", "column2", FXCollections.<String>observableArrayList( "444", "5555", "6666" ) ),
                    new TabVo( "7777", "column2", FXCollections.<String>observableArrayList( "7777", "8888", "99999" ) ),
                    new TabVo( "hhhh", "column2", FXCollections.<String>observableArrayList( "hhhh", "jjjj", "kkkkk" ) )
            );


    @Override
    public void start( Stage stage )
    
        Scene scene = new Scene( new Group() );
        stage.setWidth( 450 );
        stage.setHeight( 550 );

        table.setEditable( true );
        Callback<TableColumn, TableCell> cellFactory = new Callback<TableColumn, TableCell>()
        
            @Override
            public TableCell call( TableColumn p )
            
                return new ComboBoxCell();
            
        ;

        TableColumn column1Col = new TableColumn( "Column 1" );
        column1Col.setMinWidth( 100 );
        column1Col.setCellValueFactory( new PropertyValueFactory<TabVo, String>( "column1" ) );
        column1Col.setCellFactory( cellFactory );
        column1Col.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<TabVo, String>>()
                
                    @Override
                    public void handle( TableColumn.CellEditEvent<TabVo, String> t )
                    
                        (( TabVo ) t.getTableView().getItems().get(
                                t.getTablePosition().getRow() )).setColumn1( t.getNewValue() );
                    
                
        );

        TableColumn column2Col = new TableColumn( "Column 2" );
        column2Col.setMinWidth( 100 );
        column2Col.setCellValueFactory( new PropertyValueFactory<TabVo, String>( "column2" ) );
        column2Col.setCellFactory( TextFieldTableCell.forTableColumn() );
        column2Col.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<TabVo, String>>()
                
                    @Override
                    public void handle( TableColumn.CellEditEvent<TabVo, String> t )
                    
                        (( TabVo ) t.getTableView().getItems().get(
                                t.getTablePosition().getRow() )).setColumn2( t.getNewValue() );
                    
                
        );

        table.setItems( data );
        table.getColumns().addAll( column1Col, column2Col );

        (( Group ) scene.getRoot()).getChildren().add( table );

        stage.setScene( scene );
        stage.show();
    


    class ComboBoxCell extends TableCell<TabVo, String>
    

        private ComboBox<String> comboBox;


        public ComboBoxCell()
        
            comboBox = new ComboBox<>();
        


        @Override
        public void startEdit()
        
            if ( !isEmpty() )
            
                super.startEdit();

                comboBox.setItems( getTableView().getItems().get( getIndex() ).getColumn1List() );
                comboBox.getSelectionModel().select( getItem() );

                comboBox.focusedProperty().addListener( new ChangeListener<Boolean>()
                
                    @Override
                    public void changed( ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue )
                    
                        if ( !newValue )
                        
                            commitEdit( comboBox.getSelectionModel().getSelectedItem() );
                        
                    
                 );

                setText( null );
                setGraphic( comboBox );
            
        


        @Override
        public void cancelEdit()
        
            super.cancelEdit();

            setText( ( String ) getItem() );
            setGraphic( null );
        


        @Override
        public void updateItem( String item, boolean empty )
        
            super.updateItem( item, empty );

            if ( empty )
            
                setText( null );
                setGraphic( null );
            
            else
            
                if ( isEditing() )
                
                    setText( null );
                    setGraphic( comboBox );
                
                else
                
                    setText( getItem() );
                    setGraphic( null );
                
            
        

    


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


    public static class TabVo
    

        private String column1;
        private String column2;

        private ObservableList<String> column1List;


        private TabVo( String column1, String column2, ObservableList<String> column1List )
        
            this.column1 = column1;
            this.column2 = column2;
            this.column1List = column1List;
        


        public String getColumn1()
        
            return column1;
        


        public void setColumn1( String column1 )
        
            this.column1 = column1;
        


        public String getColumn2()
        
            return column2;
        


        public void setColumn2( String column2 )
        
            this.column2 = column2;
        


        public ObservableList<String> getColumn1List()
        
            return column1List;
        


        public void setColumn1List( ObservableList<String> column1List )
        
            this.column1List = column1List;
        

    


第一列在编辑模式下使用组合框,而第二列使用文本字段的默认工厂。

【讨论】:

感谢您的解决方案。但是当我单击下拉菜单时,setOnEditCommit 侦听器在初始选择期间仅被调用一次。如果我尝试在下拉列表中选择其他值,则不会调用它。 @SyedAmmar,改变combobox的值后,单元格仍处于编辑模式,您需要从单元格中聚焦,因此combobox.focusProperty可以commitEdit。或者,如果需要,您可以将 commitEdit() 放在组合框项 changeListener 上。【参考方案2】:

您需要为单元格定义一个 CellValueFactory。该工厂使用给定行的表项列表的当前值来定义将在列中显示的值。见此链接:Cell factory in javafx

【讨论】:

TableColumn 的setCellValueFactory 接受Callback&lt;CellDataFeatures&lt;S,T&gt;, ObservableValue&lt;T&gt;&gt; value。我只是想知道是否可以将ObservableList&lt;T&gt; 类型转换/包装为ObservableValue&lt;T&gt;

以上是关于为 javaFx 表视图中的每一行动态填充组合框列表的主要内容,如果未能解决你的问题,请参考以下文章

单击时在JavaFX中填充组合框

MS Access:组合框列顺序问题

用 subsonic & vb.net 填充 datagridview 组合框列

MS Access 组合框列查找第三个表(多维查找?)

动态填充和更新组合框中的项目

使用javascript-HTML格式化动态表中的每一行