Qt Quick设置父子的操作不简单



  • 题图送给论坛大大。post_cover
    今天我告诉大家一个事儿,Qt Quick设置父子操作不简单!:astonished:
    比如这段代码:

            function insertItem_impl( item, splitIndex )
            {
                // 尝试在某个项目之前插入项目
                fillIndex = splitIndex;
    
    // 注意这段Start
                var handlesToResetIndex = [ ];
                print( "previous it has: " + splitterHandles.children.length + " splitters." );
                var i = 0;
                for ( i = splitIndex; i < splitterHandles.children.length; ++i )
                {
                    var handle = splitterHandles.children[i];
                    print( "[][] the previous handle(" + handle.__handleIndex + ") will be set to: " + ( i + 1 ) );
                    handle.__handleIndex = i + 1;
                    handle.parent = null;
                    handlesToResetIndex.push( handle );
                }
    
                var newHandle = handleLoader.createObject( splitterHandles, {"__handleIndex": splitIndex } );
                newHandle.parent = splitterHandles;
    
                for ( i in handlesToResetIndex )
                {
                    handlesToResetIndex[i].parent = splitterHandles;
                }
    // 注意这段End
    
                print( "insertItem_impl: Finally, inserting item ( objectName: " + item.objectName +
                      " ) at splitIndex: " + splitIndex );
                var childrenToRestore = [ ];            
                for ( i = splitIndex; i < splitterItems.children.length; ++i )
                {
                    var child = splitterItems.children[i];
                    child.objectName = i + 1;
                    childrenToRestore.push( child );
                    child.parent = null;
                }
    
                // 新增该item为孩子
                item.parent = splitterItems;
    
                // 把其余的补充进来
                for ( i in childrenToRestore )
                {
                    childrenToRestore[i].parent = splitterItems;
                }
    
    
                //splitterItems.children
                //item.parent = splitterItems
                d.initItemConnections(item)
            }
    

    本来我想通过handle拉出界面的。像Blender这样的。
    0_1499333766101_bff2255b-e14e-4580-8a0e-67bf83b7d05a-image.png
    但是……
    0_1499333781416_070450ee-d392-4f1c-a74b-40a2e8d5d55d-image.png
    OK
    0_1499333801993_7fd1c332-d0e2-41ba-a93b-a2509b0494fb-image.png
    OK
    0_1499333833534_d9962576-ee02-42b8-987b-4eb4a65432ca-image.png
    OK
    0_1499333849468_6224144e-7a82-4900-ab94-f68639903233-image.png
    Error

    为什么会这样呢?查了好多的代码,最后我终于理解了其中的奥秘。为了以后不再犯错误,我记录一下。



  • 上面的截图表示,本来按照0、1、2、3的顺序一次排列的handle(抓手),但是错乱了。原来是Qt Quick的item设置父子关系的问题。

    好了,为了阐述问题,你需要明白两点。

    1. 如何在运行期创建新的item呢?答案是Component.createObject()函数,就像这样写的:
    var newHandle = handleLoader.createObject( splitterHandles, {"__handleIndex": splitIndex } );
    
    1. 如何在运行期将item从它的父亲中移除吗?因为Item没有remove这样操作,所以想从Item中找到答案是很难的。但是其实方法相当简单:
    handle.parent = null;
    

    这样就可以将Item和它的父亲解除关系。

    好了,有了这些知识,再看看我原来的代码有哪些问题呢?

                for ( i = splitIndex; i < splitterHandles.children.length; ++i )
                {
                    var handle = splitterHandles.children[i];
                    print( "[][] the previous handle(" + handle.__handleIndex + ") will be set to: " + ( i + 1 ) );
                    handle.__handleIndex = i + 1;
                    handle.parent = null;
                    handlesToResetIndex.push( handle );
                }
    

    看出来了没有?问题在于for循环中设置结束条件是需要对splitterHandles.children.length求值,但是在循环体中却对每一个handle都解除了父子关系,结果导致循环过早结束。导致程序出现了大的BUG。

    知道问题所在了,解决起来就方便了。下面是我解决后的代码(请忽视一些输出语句和注释,会优化的……)

    function insertItem_impl( item, splitIndex )
            {
                // 尝试在某个项目之前插入项目
                fillIndex = splitIndex;
    // 注意这段Start
                var handlesToResetIndex = [ ];
                print( "previous it has: " + splitterHandles.children.length + " splitters." );
                var i = 0;
                for ( i = splitIndex; i < splitterHandles.children.length; ++i )
                {
                    var handle = splitterHandles.children[i];
                    print( "[][] the previous handle(" + handle.__handleIndex + ") will be set to: " + ( i + 1 ) );
                    handle.__handleIndex = i + 1;
                    //handle.parent = null;
                    handlesToResetIndex.push( handle );
                }
                for ( i in handlesToResetIndex )
                {
                    handlesToResetIndex[i].parent = null;
                }
    
                var newHandle = handleLoader.createObject( splitterHandles, {"__handleIndex": splitIndex } );
                newHandle.parent = splitterHandles;
    
                for ( i in handlesToResetIndex )
                {
                    handlesToResetIndex[i].parent = splitterHandles;
                }
    // 注意这段End
                print( "insertItem_impl: Finally, inserting item ( objectName: " + item.objectName +
                      " ) at splitIndex: " + splitIndex );
                var childrenToRestore = [ ];            
                for ( i = splitIndex; i < splitterItems.children.length; ++i )
                {
                    var child = splitterItems.children[i];
                    child.objectName = i + 1;
                    childrenToRestore.push( child );
                    //child.parent = null;
                }
                for ( i in childrenToRestore )
                {
                    childrenToRestore[i].parent = null;
                }
    
                // 新增该item为孩子
                item.parent = splitterItems;
    
                // 把其余的补充进来
                for ( i in childrenToRestore )
                {
                    childrenToRestore[i].parent = splitterItems;
                }
    
    
                //splitterItems.children
                //item.parent = splitterItems
                d.initItemConnections(item)
            }
    

    希望遇到的这些问题给大家提供一些有益的启示,以后可不要犯我同样的错误了哦。学到了没有学过的操作,真好。



  • 我好像看到有人点赞我~:astonished:


登录后回复
 

与 萌梦社区 的连接断开,我们正在尝试重连,请耐心等待