如何启用对TableView / TreeTableView focusLost提交? [英] How to enable commit on focusLost for TableView/TreeTableView?

查看:212
本文介绍了如何启用对TableView / TreeTableView focusLost提交?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有简单的方法让TreeTableView(或TableView)尝试提交焦点上的值丢失?

不幸的是,我没有成功实现任何默认实现javafx TableCellFactories,这就是为什么我尝试我自己的TreeTableCell实现,还有一些不同的tableCell实现,如,这似乎是最直接的,因为它已经实现了焦点丢失的钩子,但是价值永远不会提交,用户更改重置为原来的值。

我的猜测是,每当焦点丢失时,受影响Cell的editingProperty总是为false,导致Cell永远不会在focusLost上提交一个值。这里的原始(oracle-)TreeTableCell实现(8u20ea)的相关部分,这会导致我的方法失败:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ @ $> public void commitEdit(T newValue){
if(!isEditing())return; //< - 在这里,我的方法被阻止,因为焦点失去了不再编辑。

最终TreeTableView< S> table = getTreeTableView();
if(table!= null){
@SuppressWarnings(unchecked)
TreeTablePosition< S,T> editingCell =(TreeTablePosition< S,T>)table.getEditingCell();

//通知编辑的TableView准备提交。
CellEditEvent< S,T> editEvent = new CellEditEvent< S,T>(
表,
editingCell,
TreeTableColumn。< S,T> editCommitEvent(),
newValue
);

Event.fireEvent(getTableColumn(),editEvent);
}

//通知提交的父类,以便他们可以将
//切换到编辑状态之外。
//这必须在下面的updateItem调用之前,否则它会
//调用cancelEdit(),导致提交和取消事件都是
//被触发(如RT- 29650)
super.commitEdit(newValue);

//更新此单元格中的项目,以便表示新值
updateItem(newValue,false);
$ b $ if(table!= null){
//重置TableView的编辑单元
table.edit(-1,null);

//仅当当前焦点
//拥有者将表作为父项(否则用户可能有
// //点击退出这个表完全被赋予了别的东西
//我们再次请求它是不礼貌的
ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(table);
}
} $


$ b我已经成功地重写了这个方法并且在原来的commitEdit()方法之前提交了by hand但是这会导致像enter这样的提交键提交值两次(在key +上失去焦点),而且我真的不喜欢我的方法,所以我想知道,如果其他人已经解决了这个更好这样做的原因是什么?(一):在textField失去焦点之前取消编辑的合作者)是Tab leCellBehaviour / Base处理mousePressed:

$ ul

  • mousePressed调用 simpleSelect(..)
  • 检测到一次点击,它调用 edit(-1,null)

  • 在TableView上调用相同的方法
  • 将其editingCell属性设置为null
    tableCell监听该属性,并通过取消自己的编辑


    不幸的是,一个解决方案需要3个合作者


    • 一个带有附加API的TableView终止一个编辑

    • 一个TableCellBehaviour被覆盖 simpleSelect(...) (而不是编辑(-1 ..))在调用超级
    • 之前,使用扩展行为配置的TableCell知道表的扩展属性
    • li>


    一些代码片段(完整的代码):

      //在XTableView上:
    public void terminateEdit(){
    if(!isEditing ())return;
    // terminatingCell是支持TableCells可以监听
    setTerminatingCell(getEditingCell())的属性。
    if(isEditing())抛出新的IllegalStateException(
    期望编辑被终止,但是+ getEditingCell());
    setTerminatingCell(null);
    }

    //在XTableCellBehaviour上:覆盖simpleSelect
    @Override
    protected void simpleSelect(MouseEvent e){
    TableCell< S,T> cell = getControl();
    TableView< S> table = cell.getTableColumn()。getTableView();
    ((XTableView< S>)table).terminateEdit();
    }
    super.simpleSelect(e);
    }

    //在XTextFieldTableCell上 - 这个方法从监听器
    //被调用到表的terminatingCell属性
    protected void terminateEdit(TablePosition< S,?> newPosition ){
    if(!isEditing()||!match(newPosition))return;
    commitEdit();


    protected void commitEdit(){
    T edited = getConverter()。fromString(myTextField.getText());
    commitEdit(edited);
    }

    / **
    *实现创建支持终止编辑的XTableCellSkin。
    * /
    @Override
    受保护的皮肤<?> createDefaultSkin(){
    return new XTableCellSkin< S,T>(this);





    注意:TableCellBehaviour的实现在jdk8u5和jdk8u20之间发生了巨大的变化(黑客的快乐 - 不适合生产使用;-) - 在后者覆盖的方法是 handleClicks(..)



    BTW: JDK-8089514 (RT-18492 in old jira)可能会加速核心修复。不幸的是,至少需要作者角色投票/评论新追踪器中的错误。


    Is there any simple approach to let the TreeTableView (or TableView) try to commit values on focus lost?

    Unfortunatly I didn't succed with any default-implementations of javafx TableCellFactories, which is why I tried my own TreeTableCell implementations and also some different tableCell implementations like the one from Graham Smith, which seemed the most straight forward, since it already implemented a hook for focus lost, but nevertheless the value is never committed and the userchanges are resetted to the original value.

    My guess is, whenever focus is lost, the editingProperty of the affected Cell is always already false which causes the Cell never to commit a value on focusLost. Here the relevant part from the original (oracle-)TreeTableCell Implementation (8u20ea), which causes my approaches to fail:

     @Override public void commitEdit(T newValue) {
            if (! isEditing()) return; // <-- here my approaches are blocked, because on focus lost its not editing anymore.
    
            final TreeTableView<S> table = getTreeTableView();
            if (table != null) {
                @SuppressWarnings("unchecked")
                TreeTablePosition<S,T> editingCell = (TreeTablePosition<S,T>) table.getEditingCell();
    
                // Inform the TableView of the edit being ready to be committed.
                CellEditEvent<S,T> editEvent = new CellEditEvent<S,T>(
                    table,
                    editingCell,
                    TreeTableColumn.<S,T>editCommitEvent(),
                    newValue
                );
    
                Event.fireEvent(getTableColumn(), editEvent);
            }
    
            // inform parent classes of the commit, so that they can switch us
            // out of the editing state.
            // This MUST come before the updateItem call below, otherwise it will
            // call cancelEdit(), resulting in both commit and cancel events being
            // fired (as identified in RT-29650)
            super.commitEdit(newValue);
    
            // update the item within this cell, so that it represents the new value
            updateItem(newValue, false);
    
            if (table != null) {
                // reset the editing cell on the TableView
                table.edit(-1, null);
    
                // request focus back onto the table, only if the current focus
                // owner has the table as a parent (otherwise the user might have
                // clicked out of the table entirely and given focus to something else.
                // It would be rude of us to request it back again.
                ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(table);
            }
        }
    

    I succeded with overriding this method and commiting the value "by hand" before the original commitEdit() method is called, but this causes the commit on keys like enter to commit the value twice (on key + on focus lost). Moreover I dont really like my approach at all, so I wonder, if anyone else has solved this in a "nicer" way?

    解决方案

    After some digging, turned out that the culprit (aka: the collaborator that cancels the edit before the textField looses focus) is the TableCellBehaviour/Base in its processing of a mousePressed:

    • mousePressed calls simpleSelect(..)
    • on detecting a single click it calls edit(-1, null)
    • which calls the same method on TableView
    • which sets its editingCell property to null
    • a tableCell listens to that property and reacts by canceling its own edit

    Unfortunately, a hackaround requires 3 collaborators

    • a TableView with additional api to terminate an edit
    • a TableCellBehaviour with overridden simpleSelect(...) that calls the additional api (instead of edit(-1..)) before calling super
    • a TableCell that is configured with the extended behaviour and is aware of table's extended properties

    Some code snippets (full code) :

    // on XTableView:
    public void terminateEdit() {
        if (!isEditing()) return;
        // terminatingCell is a property that supporting TableCells can listen to
        setTerminatingCell(getEditingCell());
        if (isEditing()) throw new IllegalStateException(
              "expected editing to be terminated but was " + getEditingCell());
        setTerminatingCell(null);
    }
    
    // on XTableCellBehaviour: override simpleSelect
    @Override
    protected void simpleSelect(MouseEvent e) {
        TableCell<S, T> cell = getControl();
        TableView<S> table = cell.getTableColumn().getTableView();
        if (table instanceof XTableView) {
            ((XTableView<S>) table).terminateEdit();
        }
        super.simpleSelect(e);
    }
    
    // on XTextFieldTableCell - this method is called from listener
    // to table's terminatingCell property
    protected void terminateEdit(TablePosition<S, ?> newPosition) {
        if (!isEditing() || !match(newPosition)) return;
        commitEdit();
    }
    
    protected void commitEdit() {
        T edited = getConverter().fromString(myTextField.getText());
        commitEdit(edited);
    }
    
    /**
     * Implemented to create XTableCellSkin which supports terminating edits.
     */
    @Override
    protected Skin<?> createDefaultSkin() {
        return new XTableCellSkin<S, T>(this);
    }
    

    Note: the implementation of TableCellBehaviour changed massively between jdk8u5 and jdk8u20 (joys of hacking - not fit for production use ;-) - the method to override in the latter is handleClicks(..)

    BTW: massive votingfor JDK-8089514 (was RT-18492 in old jira) might speed up a core fix. Unfortunately, at least the author role is needed to vote/comment bugs in the new tracker.

    这篇关于如何启用对TableView / TreeTableView focusLost提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆