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_1531879249244_9090909.jpg
    各位上午好哦。很高兴告诉大家,我们的萌梦社区又进行了一波更新了!
    这次主要更新在论坛代码层面上的,也就是说我们根据NodeBB官方的指示,将论坛从1.9.3升级到了1.10.1了!整个升级过程会产生一些服务暂停的现象,不过没有关系,很快就可以得到恢复,现在咱们可以顺利地在新的论坛上玩耍了!
    这次更新按照NodeBB官方的说法,主要在论坛的稳定性和迎合欧盟的GPDR政策(隐私权保护政策)上,也就是说,咱们论坛默认是支持用户的隐私权保护的~不要担心自己的隐私会被黑客利用什么的,但是大家还是要保护好平时论坛登录的密码哦。合适的时候还是使用浏览器的记住密码功能~

    此外,之前萌梦论坛之前的SSL加密是免费的,费时效果又不好。在手机浏览器上显示并非可靠的颁发者,现在换了新的证书,感觉好了不少。现在又可以在论坛上玩耍啦。

    好了,就是这样~

    阅读更多
  • @jiangcaiyang 是不支持QVector3D类型么,需要引用头文件还是需要转换类型呢

    阅读更多
  • 可能是Qt制作的Python绑定Shiboken遇到了问题。求先行者能够解忧~😵

    阅读更多
  • 0_1531804634749_5.jpg
    我使用的是PyCharm作为IDE,下载了Qt for Python(使用Qt 5.11),并且使用git克隆了pyside的源代码 + 例子。因为自己对OpenGL感兴趣,所以随手运行了一个例子。首先是PyOpenGL没有安装。

    0_1531804316021_1f365ea0-46b3-460d-9a00-c8cdeccf98af-image.png

    通过对话框弹出的命令,在terminal上运行

    python -m pip install PyOpenGL PyOpenGL_accelerate

    就可以了。

    虽然窗体以及3D内容出来了,但是命令提示符中会出现一些问题:

    D:/QtProject/pyside-setup/examples/opengl/hellogl2.py:394: RuntimeWarning: SbkConverter: Unimplemented C++ array type. self.program.setUniformValue(self.lightPosLoc, QVector3D(0, 0, 70)) D:/QtProject/pyside-setup/examples/opengl/hellogl2.py:423: RuntimeWarning: SbkConverter: Unimplemented C++ array type. self.program.setUniformValue(self.projMatrixLoc, self.proj) D:/QtProject/pyside-setup/examples/opengl/hellogl2.py:424: RuntimeWarning: SbkConverter: Unimplemented C++ array type. self.program.setUniformValue(self.mvMatrixLoc, self.camera * self.world) D:/QtProject/pyside-setup/examples/opengl/hellogl2.py:426: RuntimeWarning: SbkConverter: Unimplemented C++ array type. self.program.setUniformValue(self.normalMatrixLoc, normalMatrix)

    刚学习Python,还不清楚是怎么回事,怎么解决才好。

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔