[英]Pyside2 QQmlPropertyMap's slot not accessible from QML; Python version of old C++ bug?
我遇到了一个看起来很像现代 Python 版本的错误,该错误是几年前在(C++)Qt 中修复的: 无法从 BQQ 子类中的 ZC477ABFB7FD4959A20D5E0240008D25Z 中调用 slot 或 Q_INVOKABLE
我在我的系统上测试了问题中的示例(Qt 5.15.0,根据需要修改语法)并验证它确实是固定的; 对象的槽被正确访问,无论它是继承自 QObject 还是 QQmlPropertyMap。
但是,仍然使用 Qt 5.15.0,从 PySide2 工作似乎复制了同样的问题:
主要.py:
from PySide2.QtCore import QObject, Property, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine, QQmlPropertyMap
class MyObj(QObject):
@Property(str)
def field(self):
return 'Field from QObject'
@Slot()
def test_func(self):
print('QObject signal worked')
class MyMap(QQmlPropertyMap):
def __init__(self):
super().__init__()
self.insert('field', 'Field from QQmlPropertyMap')
@Slot()
def test_func(self):
print('QQmlPropertyMap signal worked')
app = QGuiApplication()
engine = QQmlApplicationEngine()
qobj = MyObj()
engine.rootContext().setContextProperty('qobj', qobj)
qmap = MyMap()
engine.rootContext().setContextProperty('qmap', qmap)
engine.load('main.qml')
app.exec_()
main.qml:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
visible: true
width: 200
height: 200
Text {
text: qobj.field + '\n' + qmap.field
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
qobj.test_func();
qmap.test_func();
}
}
}
这两个字段都在生成的 window 中正确显示,但单击它会生成此控制台 output:
QObject slot worked
file:///Users/charles/Projects/qt/map-signal-test/main.qml:20: TypeError: Property 'test_func' of object QQmlPropertyMap(0x7fb954f5f460) is not a function
我不太了解 PySide2 是如何实现的。 这是同一个错误,未修复还是重新出现? 或者是别的什么? 无论哪种情况,是否有解决方法?
编辑:响应 eyllanesc 的回答如下。 虽然您发布的代码重现了 C++ 中的错误,但这个有点不同的 class 定义(源自上面链接的旧问题)可以正常工作:
class MyMap: public QQmlPropertyMap {
Q_OBJECT
public:
MyMap(QObject* parent = 0): QQmlPropertyMap(this, parent) {}
public slots:
Q_INVOKABLE void test_func() {
qDebug() << "QQmlPropertyMap signal worked";
}
};
我对 C++ 了解不够,无法理解其中的含义。
不幸的是,这是一个 Qt 错误,请查看QTBUG-29836中的评论。 我已经使用 Qt 5.15 使用以下 MRE 对其进行了验证:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlPropertyMap>
class MyMap: public QQmlPropertyMap{
Q_OBJECT
public:
using QQmlPropertyMap::QQmlPropertyMap;
Q_INVOKABLE void test_func(){
qDebug() << "QQmlPropertyMap signal worked";
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
MyMap qmap;
engine.rootContext()->setContextProperty("qmap", &qmap);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
#include "main.moc"
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: {
qmap.test_func()
}
}
}
更新:
似乎该错误的解决方法是使用使用派生 class 的 QMetaObject 的 受保护构造函数,与仅访问 QQmlProperty 的 QMetaObject 的默认构造函数不同,因此新 class 的 Q_SLOTS、Q_INVOKABLES 等元素是映射。 不幸的是,无法从 Python 访问该构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.