繁体   English   中英

Pyside2 QQmlPropertyMap 的插槽无法从 QML 访问; Python 版本的旧 C++ 错误?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM