python - QML findChild 来自不同的组件
问题描述
目标:我正在为基于 Matplotlib 的嵌套样本库编写 Gui 前端(pip install anesthetic
如果你想看看)。
我将如何在 C++ 中进行操作:我之前使用 QML 的经验是一个C++
程序,我没有进入 QML 来寻找要渲染的画布,而是创建了一个 C++ 对象,在 QML 的类型系统中注册它,并让它表现得像QtQuick 控件小部件。据我所知,这是推荐的做事方式:所有渲染都在 QML 中完成,所有业务端逻辑都在 C++ 中。
最好的方法以及为什么我不能这样做:这种方法在这里不起作用。AFAIK,您只能使用 C++ 实现自定义 QML,我需要程序是纯 Python(以便其他人能够维护它)一些 JS 是可访问的,QML 很容易理解和编辑,所以我没有反对意见(C++ 很难拒绝)。
我得到了什么:我有一个我想要的工作实现。这一切都在一个文件中。所以,很自然地,我想将我正在绘制的画布拆分为一个单独的文件:figure.qml
. 麻烦的是,每当从单独的文件中加载该对象时,我似乎都找不到该名称的对象(下一步是使用 a Loader
,因为Figure
它非常笨重)。
我有一个包含两个文件的项目,view.qml
它是根目录,一个组件位于Figure.qml
. 问题是,它只有在我用objectName: "component"
inview.qml
而不是 in加载东西时才有效Component.qml
。
那么如何使用另一个文件findChild
中Pyside
的 objectName.qml
呢?
MWE:
主文件
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 {
}
}
图.qml
import QtQuick.Controls 2.12
import QtQuick 2.12
Component{
Rectangle{
objectName: "figure"
}
}
解决方案
Component
用于定义QML 元素,它不会实例化它,因此您无法访问该对象。创建一个 Figure.qml 相当于创建一个 Component,而您是在另一个 Component 中创建一个 Component。
解决方案是不使用组件:
图.qml
import QtQuick.Controls 2.12
import QtQuick 2.12
Rectangle{
objectName: "figure"
}
但不建议使用 objectName,例如,如果您创建多个组件,您将如何识别它是哪个组件?o 如果您在时间 T 之后创建对象,或者使用 Loader 或 Repeater,您将无法应用该逻辑。最好创建一个允许获取这些对象的 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)]
# ...
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)
}
推荐阅读
- python - 在 Pygame 中旋转画布
- amazon-web-services - 如何通过 Kinesis 代理传递 AWS 会话令牌?
- flutter - 如何在flutter web上实现苹果登录?
- jwt - 使用 NATS.io 的 NAS 和 NSC 时出现意外的“ed25519-nkey”算法错误
- c# - 如何在 C# 中写入和读取 .xlsb 文件而不使用 Excel 互操作
- php - 出现错误 PHP 致命错误:Class 'Zend\Mvc\Controller\AbstractActionController'
- java - 如何在android studio中将Html页面转换为Pdf
- azure - ARM 模板抛出“共享吞吐量集合应该有一个分区键”
- python - sklearn.tree.plot_tree 显示返回文本块而不是可视化树
- prolog - Prolog 语法错误:. 或表达式 1 错误编译失败后预期的运算符