如何在JavaFX中以编程方式打开组合框时确定组合框的方向和位置?

时间:2016-12-23 17:05:00

标签: javafx combobox

在使用表格行以编程方式打开组合框时,我遇到了定位和方向问题。由于组合框位于表中的表行内,因此用户必须在一个单元格中单击总共三次才能打开组合框。为方便起见,我创建了一个自定义类,允许单击编辑组合框。这非常有用!但是,当组合框打开时,生成的对话框的左上角会隐藏在所选单元格的左上角,而不只是在下方并与组合框对齐。例如:

Misaligned combo box

当用户使用鼠标滚轮或单击滚动条并移动它来滚动组合框时,此问题会自行解决。

另一个有趣的问题是组合框不会始终以正确的方向打开。在我的UI底部的一个特定表格中,组合框将在第1行到第5行向下打开。在第四行和第五行中,一旦用户滚动,组合框将移动到 上方 组合框的正确位置。第4行显示的组合框示例:

Combo box below the UI bounds

运行combobox.show()命令后,有没有办法正确对齐组合框?并非我的所有组合框都有足够的项目可以滚动,因此以编程方式滚动组合框对我的所有组合框都不起作用。

这是我自定义的tablecell类。

private class MyCustomComboBoxTableCell extends TableCell<MyCustomRow, String>{

    private final ComboBox<String> comboBox;

    public MyCustomComboBoxTableCell(ObservableList<String> items){
        this.comboBox = new ComboBox<String>(items);

        comboBox.setOnShown(new EventHandler<Event>(){
            @Override
            public void handle(Event event) {
                getTableView().edit(getIndex(), getTableColumn());
                getTableView().getSelectionModel().clearSelection();
            }
        });

        comboBox.valueProperty().addListener(new ChangeListener<String>(){
            @Override
            public void changed(ObservableValue obs, String oldValue, String newValue) {
                if(newValue != null && !newValue.equals(oldValue)){
                    commitEdit(comboBox.getSelectionModel().getSelectedItem());
                }
            }
        });

        addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
            @Override
            public void handle(MouseEvent event){
                if(getIndex() < getTableView().getItems().size()){
                    startEdit();
                    comboBox.show();
                }
            }
        });
    }

    @Override
    public void startEdit(){
        super.startEdit();

        setGraphic(comboBox);
        setText(null);
    }

    @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){
            setGraphic(null);
        } else {
            if(isEditing()){
                setGraphic(comboBox);
                setText(null);
            } else {
                setGraphic(null);
                setText(getItem());
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

开始编辑时,ComboBox尚未布置。弹出窗口将根据ComboBox的当前边界显示,这意味着这些边界很可能是错误的。

触发TableView上的布局传递可以解决此问题:

addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        if (getIndex() < getTableView().getItems().size()) {
            startEdit();

            // trigger layout pass
            getTableView().applyCss();
            getTableView().layout();

            comboBox.show();
        }
    }
});