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



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

            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)
            }
    

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



  • 我好像看到有人点赞我~😲


 

最近的回复

  • 0_1539655233041_329385492.jpg
    各位大家好哦。
    经过一个晚上对论坛的维护更新,我们成功地将论坛更新到最新的版本。这次的版本更新主要是提升了稳定性,因此功能上和原来的一样,请大家放心,不会出现奇怪的东西什么的啦。然后呢,由于提升了稳定性,因此论坛不会莫名其妙地出现未响应的情况,总之比以前好就对啦。

    此外,论坛新增了自己研制的一个分享的插件:nodebb-plugin-share-sns-cn。这个插件呢,主要是做主流社交网站的分享的。目前暂时支持QQ、微博以及微信的分享。目前初版是1.0。

    希望大家常常来论坛玩~

    阅读更多
  • 发一些二次元妹子图吧。谁叫我有时候也挺无聊的呢~
    0_1539486167719_119.jpg

    阅读更多
  • 0_1539445819168_123.jpg
    各位大家好!
    又有一段时间啦。我们的萌梦动作编辑器又进行更新啦!☺ ☺
    这次的更新呢,主要是完善了一下自动构建系统。也就是说为了持续构建并且能够给到爱好者可用并且稳定的软件,我们做了很多的努力,其中一点就是制作了脚本进行持续构建,以前要花很多很多的时间对动作编辑器进行构建,现在呢,没有那么复杂了。简简单单地数个批处理操作,即可快速构建咱们的动作编辑器,使得从代码到产品只需要十几分钟即可完成,比以前的速度节省了90%的时间,可谓神速!这套系统已经成功地应用到Windows平台线上了,现在基本可以做到每日构建的水平。而且为每次构建专门准备了pdb文件,即一旦用户运行动作编辑器出现了问题,可以通过程序调试数据库定位到问题的位置,从而提升服务的水平,想想这对于我一直坚持的萌梦这款产品来说算是革命性的操作呢。

    当然现在这套系统只能应用在Windows线上,Mac OS X这条线是我接下来努力的方向,也希望能够实现Mac这条线的每日构建效果。然后Linux平台也比较重要,想起Linux开发应该比Windows等等要方便,所以我想难度比Windows的要小很多,甚至比Mac OS X的都要小。总之路途还很遥远,加油努力吧!

    这次的Windows版本已经成功地在Windows的安装包中进行测试,同时提供在线的和离线的安装包。下面就是这些安装包的github下载地址。

    Windows在线安装包
    Windows离线安装包

    阅读更多
  • 手动给一个赞!!☺ 🤗
    0_1539264026793_好美的图啊.jpg

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔