Python 来自不同组件的QML findChild

Python 来自不同组件的QML findChild,python,qml,pyside2,Python,Qml,Pyside2,目标: 我正在为基于Matplotlib的库编写一个用于嵌套示例的Gui前端(pip install SORINATE,如果您想查看的话) > >我在C++中的经验是: C++ +/>代码程序,在这里,我不创建QC++来寻找一个画布,而是创建了一个C++对象,注册在QML的类型系统中,并将其作为QtQuy控件控件。据我所知,这是推荐的方法:所有的渲染都在QML中完成,并且所有的业务结束逻辑都在C++中。 最佳方法以及我为什么不能这样做:这种方法在这里不起作用。AfAIK只能使用C++实现自定义

目标: 我正在为基于Matplotlib的库编写一个用于嵌套示例的Gui前端(
pip install SORINATE
,如果您想查看的话)

<> > >我在C++中的经验是:<代码> C++ +/>代码程序,在这里,我不创建QC++来寻找一个画布,而是创建了一个C++对象,注册在QML的类型系统中,并将其作为QtQuy控件控件。据我所知,这是推荐的方法:所有的渲染都在QML中完成,并且所有的业务结束逻辑都在C++中。 最佳方法以及我为什么不能这样做:这种方法在这里不起作用。AfAIK只能使用C++实现自定义QML,而且我需要程序是纯ISH Python(其他人能够维护它)一些JS是可访问的,QML很容易理解和编辑,所以我没有异议(C++是硬的)。 我得到了什么工作:我有一个我想要的工作实现。都在一个文件里。因此,我自然希望将要绘制的画布拆分为一个单独的文件:
figure.qml
。问题是,每当从单独的文件加载对象时,我似乎都找不到该名称的对象(下一步是使用
加载程序,因为
相当笨重)

我有一个两个文件的项目,
view.qml
是根目录,在
Figure.qml
中有一个组件。 问题是,只有在
view.qml
中加载带有
objectName:“component”
的东西,而不是在
component.qml
中加载时,它才起作用

那么,对于另一个
.qml
文件中的objectName,如何在
Pyside
中查找child

MWE:

main.py

import sys
from pathlib import Path
from matplotlib_backend_qtquick.backend_qtquickagg import FigureCanvasQtQuickAgg
from matplotlib_backend_qtquick.qt_compat import QtGui, QtQml, QtCore


def main():
    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    displayBridge = DisplayBridge()
    context = engine.rootContext()                       
    qmlFile = Path(Path.cwd(), Path(__file__).parent, "view.qml")
    engine.load(QtCore.QUrl.fromLocalFile(str(qmlFile)))
    win = engine.rootObjects()[0]
    if win.findChild(QtCore.QObject, "figure"):
        print('success') # This fails
    app.exec_()
查看.qml

import QtQuick.Controls 2.12
import QtQuick.Windows 2.12

ApplicationWindow{
   Figure {

   }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Component{
  Rectangle{ 
    objectName: "figure"
  }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Rectangle{ 
    objectName: "figure"
}
图.qml

import QtQuick.Controls 2.12
import QtQuick.Windows 2.12

ApplicationWindow{
   Figure {

   }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Component{
  Rectangle{ 
    objectName: "figure"
  }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Rectangle{ 
    objectName: "figure"
}
用于定义QML元素,它不实例化它,因此您无法访问该对象。创建Figure.qml相当于创建一个组件,您正在另一个组件内创建一个组件

解决方案是不使用组件:

图.qml

import QtQuick.Controls 2.12
import QtQuick.Windows 2.12

ApplicationWindow{
   Figure {

   }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Component{
  Rectangle{ 
    objectName: "figure"
  }
}
import QtQuick.Controls 2.12 
import QtQuick 2.12

Rectangle{ 
    objectName: "figure"
}
但不建议使用objectName,因为例如,如果您创建多个组件,您将如何识别它是哪个组件?o如果您在时间T之后创建对象,或者使用Loader或Repeater,您将无法应用该逻辑。与其创建QObject,不如创建一个QObject来获取这些对象:

from PySide2 import QtCore
import shiboken2


class ObjectManager(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._qobjects = []

    @property
    def qobjects(self):
        return self._qobjects

    @QtCore.Slot(QtCore.QObject)
    def add_qobject(self, obj):
        if obj is not None:
            obj.destroyed.connect(self._handle_destroyed)
            self.qobjects.append(obj)
        print(self.qobjects)

    def _handle_destroyed(self):
        self._qobjects = [o for o in self.qobjects if shiboken2.isValid(o)]

不太清楚你在问什么。什么不起作用-删除
objectName
,嵌套项目,还有什么?已更新。问题是,查找文件后,我得到了一个
None
。它实际上迫使我将
组件
保留在
视图.qml
中,我想知道我是否遗漏了一些语义。首先,值得注意的是,QtQuick不处理“文件”,而是处理排列在树中的
qml
项。按名称在该树中查找一个项,在QML中该项是synonim for
objectName
,因此该属性始终是必需的(可能您遗漏了该属性)。另一件您可能会错过的事情是
选项
,它应该是
Qt::findchildren递归地
。“丢失”子级的另一种方法是间接加载它,即使用Loader或类似的方法。@AlexPetrosyan请提供一个@AlexPetrosyan 1)组件是异步加载的,因此您无法找到它,2)您不应该从python访问QML元素,因为它们只会产生这种不便,3)你可以解释一下你的基本目标(更详细地解释一下,我正试图从QML对画布进行Python端渲染),你有一个XY问题,4)提供一个MRE来帮助你。@AlexPetrosyan,嗯,我不理解你,更好地解释你自己。我没有看到更新的答案。我想知道如何使用加载器,但仍然能够获得画布。。。我很高兴有办法,我也很高兴这不需要我记住名字,让一切都保持在顶级水平。