[英]How to connect signals and slots over different class-instances
我有带有相应自定义模型的自定义列表视图。 我使用 QML 作为前端并使用 Python 加载主文件并使用 python 作为后端。 不同模型的模型数据相互依赖很大。 使用不同的列表视图、测试模型和委托,一切都按预期工作。
由于模型相互依赖,我引入了一个“PythonDataManager”-Class,它应该从三个模型中获取数据,使用它并将输出返回给相应的模型实例。 我想用 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())
}
}
}
}
感谢您的帮助
我现在自己解决了这个问题。
在 Python 中定义 QML 组件,然后在 QML 中导入它们,并使用“Connections{}”QML 类型连接 QML 中的信号和插槽(参见: https ://doc.qt.io/qt-6/qml-qtqml- connections.html ) 有效。
例如在 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()
}
}
并从 main.py 中删除:
# 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.