来自不同组件的 QML findChild [英] QML findChild from a different component

查看:117
本文介绍了来自不同组件的 QML findChild的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:我正在为嵌套样本的基于 Matplotlib 的库编写 Gui 前端(pip install anesthetic 如果你想看一看).

The objective: I'm writing a Gui front-end for a Matplotlib-based library for nested samples (pip install anesthetic if you want to have a look).

我将如何在 C++ 中进行操作:我之前使用 QML 的经验是一个 C++ 程序,而不是进入 QML 寻找要渲染的画布,我创建了一个 C++ 对象,在 QML 的类型系统中注册了它,并让它作为 QtQuick 控件小部件运行.据我所知,这是推荐的做事方式:在 QML 中完成所有渲染,在 C++ 中完成所有业务端逻辑.

How I would go about it in C++: My previous experience with QML was a C++ program, where instead of going into QML to find a canvas to render to, I created a C++ object, registered it in QML's type system, and had it behave as a QtQuick controls widget. As far as I know this is the recommended way of doing things: have all the rendering be done in QML, and have all the business-end-logic in C++.

最好的方法以及为什么我不能这样做:这种方法在这里不起作用.AFAIK 你只能使用 C++ 实现自定义 QML,我需要程序是纯 Python(为了其他人能够维护它)一些 JS 是可访问的,QML 很容易理解和编辑,所以我没有反对意见(C++ 很难拒绝).

THe best approach and why I can't do it: This approach doesn't work here. AFAIK you can only implement custom QML using C++, and I need for the program to be pure-ish Python (for others to be able to maintain it) some JS is accessible and QML is pretty easy to understand and edit, so I had no objections (C++ was a hard no).

我的工作:我有我想要的工作实现.这一切都在一个文件中.所以,很自然地,我想将要绘制到的画布拆分为一个单独的文件:figure.qml.问题是,每当从单独的文件中加载对象时,我似乎都找不到该名称的对象(下一步是使用 Loader,因为 Figure 是相当笨重).

what I got working: I have a working implementation of what I want. It was all in one file. So, naturally I wanted to split the canvas to which I'm drawing to into a separate file: figure.qml. Trouble is, I can't seem to find the object by that name whenever it's loaded from a separate file (the next step is to use a Loader, because the Figure is quite clunky).

我有一个两文件项目,view.qml 是根目录,Figure.qml 中有一个组件.问题是,它仅适用于我在 view.qml 中使用 objectName: "component" 而不是在 Component.qml 中加载的东西.

I have a two-file project with view.qml being the root, and a component in Figure.qml. The trouble is, it only works if I load the thing with objectName: "component" in view.qml and not in Component.qml.

那么 Pyside 中的一个 findChild 是如何用于不同 .qml 文件中的 objectName 的?

So how does one findChild in Pyside for an objectName that's in a different .qml file?

MWE:

ma​​in.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_()

view.qml

import QtQuick.Controls 2.12
import QtQuick.Windows 2.12

ApplicationWindow{
   Figure {

   }
}

图.qml

import QtQuick.Controls 2.12 
import QtQuick 2.12

Component{
  Rectangle{ 
    objectName: "figure"
  }
}

推荐答案

Component 用于定义 QML 元素,它不实例化,因此您无法访问该对象.创建一个 Figure.qml 就相当于创建了一个 Component,而你是在另一个 Component 内部创建了一个 Component.

Component is used to define a QML element, it does not instantiate it, therefore you cannot access the object. Creating a Figure.qml is equivalent to creating a Component, and you are creating a Component inside another Component.

解决方案是不使用组件:

The solution is not to use Component:

图.qml

import QtQuick.Controls 2.12 
import QtQuick 2.12

Rectangle{ 
    objectName: "figure"
}

但是不建议使用 objectName 因为例如,如果您创建多个组件,您将如何识别它是哪个组件?o 如果您在时间 T 之后创建对象,或者使用 Loader 或 Repeater,您将无法应用该逻辑.最好创建一个允许获取这些对象的 QObject 来代替它们:

But it is not recommended to use objectName since, for example, if you create multiple components, how will you identify which component it is? o If you create the object after a time T, or use Loader or Repeater you will not be able to apply that logic. Instead of them it is better to create a QObject that allows obtaining those objects:

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

# ...
object_manager = ObjectManager()
context = engine.rootContext()
context.setContextProperty("object_manager", object_manager)
qmlFile = Path(Path.cwd(), Path(__file__).parent, "view.qml")
engine.load(QtCore.QUrl.fromLocalFile(str(qmlFile)))
# ...

import QtQuick.Controls 2.12 
import QtQuick 2.12

Rectangle{ 
    Component.onCompleted: object_manager.add_qobject(this)
}

这篇关于来自不同组件的 QML findChild的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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