【发布时间】:2020-06-21 09:17:00
【问题描述】:
目标:
我正在为基于 Matplotlib 的嵌套样本库编写 Gui 前端(如果你想看看,请pip install anesthetic)。
我将如何在 C++ 中实现它:我之前使用 QML 的经验是一个 C++ 程序,我没有进入 QML 寻找要渲染的画布,而是创建了一个 C++ 对象,在 QML 的类型系统中注册它,并让它像 QtQuick 控件小部件一样工作。据我所知,这是推荐的做事方式:所有渲染都在 QML 中完成,所有业务端逻辑都在 C++ 中。
最好的方法以及为什么我不能这样做:这种方法在这里行不通。 AFAIK,您只能使用 C++ 实现自定义 QML,我需要程序是纯 Python(以便其他人能够维护它)一些 JS 是可访问的,QML 很容易理解和编辑,所以我没有反对意见(C++ 很难拒绝)。
我的工作内容:我有一个我想要的工作实现。这一切都在一个文件中。所以,很自然地,我想将我正在绘制的画布拆分为一个单独的文件:figure.qml。麻烦的是,每当从单独的文件加载对象时,我似乎都找不到该名称的对象(下一步是使用Loader,因为Figure 非常笨重)。
我有一个以view.qml 为根的两个文件项目,以及Figure.qml 中的一个组件。
问题是,只有当我在view.qml 中而不是在Component.qml 中加载带有objectName: "component" 的东西时,它才有效。
那么,Pyside 中的 findChild 是如何处理另一个 .qml 文件中的 objectName 的?
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_()
view.qml
import QtQuick.Controls 2.12
import QtQuick.Windows 2.12
ApplicationWindow{
Figure {
}
}
Figure.qml
import QtQuick.Controls 2.12
import QtQuick 2.12
Component{
Rectangle{
objectName: "figure"
}
}
【问题讨论】:
-
不太清楚你在问什么。什么不起作用 - 删除
objectName、嵌套项目,以及其他什么? -
已更新。问题是我得到一个
None作为查找文件的结果。它实际上迫使我将Component保留在view.qml中,我想知道是否有一些我错过的语义。 -
首先值得注意的是,QtQuick 不适用于“文件”,而是用于排列在树中的
QML项目。 QObject::findChild 在这棵树中查找一个名为 的项目,在 QML 中是objectName的同义词,所以这个属性总是强制性的(也许你错过了)。您可能会错过的另一件事是options,应该是Qt::FindChildrenRecursively。 “失去”孩子的另一种方法是间接加载它,即使用 Loader 或类似的东西。 -
@AlexPetrosyan 请提供minimal reproducible example
-
@AlexPetrosyan 1)组件是异步加载的,所以你找不到它,2)你不应该从 python 访问 QML 元素,因为它们只会产生这种类型的不便,3)你可以解释你的基本目标(更详细地解释我正在尝试从 QML 对画布进行一些 Python 端渲染)对我来说你有一个 XY 问题,4)提供一个 MRE 来帮助你。