【问题标题】:How to connect signals and slots over different class-instances如何在不同的类实例上连接信号和插槽
【发布时间】:2022-07-17 00:30:36
【问题描述】:

我有带有相应自定义模型的自定义列表视图。我使用 QML 作为前端并使用 Python 加载主文件并使用 python 作为后端。 不同模型的模型数据相互依赖很大。使用不同的列表视图、测试-模型和委托,一切都按预期工作。

由于模型相互依赖,我引入了一个“PythonDataManager”类,它应该从三个模型中获取数据,使用它并将输出返回给相应的模型实例。 我想用 Qt 提供的 Signal/Slot 技术来做到这一点。我连接了不同类实例的信号和插槽。我声明了一个通过 QML 中的按钮按下来调用的插槽。这个槽被执行并且应该发出一个信号,因此应该在不同的类/实例中调用不同的槽。 当我在信号上调用 .emit() 函数时,什么也没有发生。

我的问题是,如何使用 PySide6 将不同类的不同实例与信号和插槽连接起来?

以下示例代码的目标是读出 TimeseriesesModel 类的 self.db 属性,并将其发送到 PythonDataManager 打印出来。预期的结果是: [{"name": "hello", "selected": True},{"name": "zwei", "selected": False}] 但我得到一个空列表:[]。

其中一个自定义模型的短代码:

QML_IMPORT_NAME = "library.measure"
QML_IMPORT_MAJOR_VERSION = 1

@QmlElement
class TimeseriesesModel(QAbstractListModel):
    SelectedRole = Qt.UserRole + 1
    NameRole = Qt.UserRole + 2
    
    # The signal that later gets emitted
    send_ts_model_data = Signal(list)


    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.db = [
            {"name": "hello", "selected": True},
            {"name": "zwei", "selected": False},
        ]

    # --- In this place I left out a lot of code that shouldn't be relevant
    #----------------------------------------------------------------------
    
    # The slot, that should get called by the "askModelsForData" signal
    @Slot()
    def request_handling(self):
        self.send_ts_model_data.emit(self.db)

PythonDataManager-Class的相关代码:

@QmlElement
class PythonDataManager(QObject):
    askModelsForData = Signal()

    def __init__(self,  parent=None):
        super(PythonDataManager, self).__init__(parent=parent)
        self.ts_model_db = []

    @Slot(list)
    def get_ts_model_data(self, data):
        self.ts_model_db = data
    
    # The slot that get's called successfully from QML
    @Slot()
    def print_something(self):
        self.askModelsForData.emit()
        print(self.ts_model_db)

main.py的相关代码:

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    
    data_manager = PythonDataManager()
    ts_model = TimeseriesesModel()

    # Connect the signals and the slots
    data_manager.askModelsForData.connect(ts_model.request_handling)
    ts_model.send_ts_model_data.connect(data_manager.get_ts_model_data)
    

    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("TimeseriesesModel", ts_model)
    engine.rootContext().setContextProperty("PythonDataManager", data_manager)
    engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec())

调用pythonDataManager.print_something()槽的qml文件代码:

import QtQuick 2.0
import QtQuick.Window
import library.measure // The library that gets invoked in the python part 
import QtQuick.Controls

Item {
    id: root

    PythonDataManager {
        id:pythonDataManager
    }

    // Lists the Different Window/ScreenQMLs--------------------------
    // (In the reprex only one)
    Window {
        id: accessGrantedWindow

        visible: true

        minimumWidth: 955
        minimumHeight: 730

        Button {
            id: resetButton
            x: 0
            y: 0
            width: 88
            height: 25
            text: qsTr("Reset All")

            onClicked: {
                // The print_something() slot gets called successfully
                console.log(pythonDataManager.print_something())
            }
        }
    }
}

感谢您的帮助

【问题讨论】:

  • 请提供minimal reproducible example,显示您的.qml
  • @eyllanesc 我编辑了我的问题并添加了 qml 文件。我还在第一个 python 块中添加了“QML_IMPORT_NAME”变量。如果您需要更多信息,或者我可以进一步改进我的问题,请告诉我。谢谢

标签: python qml pyside6


【解决方案1】:

我现在自己解决了这个问题。

在 Python 中定义 QML 组件,然后在 QML 中导入它们,并使用“Connections{}”QML 类型(参见:https://doc.qt.io/qt-6/qml-qtqml-connections.html)连接 QML 中的信号和插槽。

例如在 QML 文件中添加:

TimeseriesesModel {
        id:ts_model
    }

Connections {
    target: pythonDataManager
    function onAskModelsForData() {
                console.log("received onAskModelsForData-signal")
                // Call your slot here like id.slot()
                ts_model.request_handling()
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多