【发布时间】:2017-01-07 22:08:37
【问题描述】:
我现在花了很长时间来弄清楚如何将 QML 信号连接到 python 中的插槽,以及如何再次与 QML GUI 通信。但我不知道如何将多个 GUI 输入发送到 python 中的同一个插槽/函数。
以下是应该发生的事情的基本示例: 用户在 GUI 中操作 SpinBox,它们的总和再次显示在 GUI 中。 我假设这是通过将多个信号路由到一个插槽或通过将每个信号路由到一个单独的插槽并让 python 以某种方式进行组合来完成的。但显然 pyqt 插槽也不允许“返回”。
非常感谢您的帮助!
QML: (注释的行是我认为可能有效的,但它没有。当信号线未注释时,它会导致“预期的令牌‘标识符’”。)
import QtQuick 2.6
import QtQuick.Controls 2.0
ApplicationWindow{
visible:true
width:200
height:300
id:window
title: "Signal/Slot Test"
Rectangle{
//signal somethingChanged(int, int)
//function exportSignals() {
// somethingChanged(spin1.value, spin2.value)
//}
Column {
spacing: 20
width: parent.width
SpinBox {
id: spin1
signal sig_spin1(int spin1_int)
objectName: "spin1"
value: 50
width: 120
editable: true
Component.onCompleted: {
console.log("Spin1: " + spin1.value)
sig_spin1(spin1.value)
//exportSignals()
}
onValueChanged: {
console.log("Spin1: " + spin1.value)
sig_spin1(spin1.value)
//exportSignals()
}
}
SpinBox {
id: spin2
signal sig_spin2(int spin2_int)
objectName: "spin2"
value: 50
width: 120
editable: true
Component.onCompleted: {
console.log("Spin2: " + spin2.value)
sig_spin2(spin2.value)
//exportSignals()
}
onValueChanged: {
console.log("Spin2: " + spin2.value)
sig_spin2(spin2.value)
//exportSignals()
}
}
Label {
id: label_spin1
objectName: "label_spin1"
text: "Start Value"
}
Label {
id: label_spin2
objectName: "label_spin2"
text: "Start Value"
}
Label {
id: label_result
objectName: "label_result"
text: "Sum"
}
}
}
}
和python代码:
import sys
from PyQt5.QtCore import QObject, QUrl, Qt, pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
def spin1_update(spin1_int):
print("Spin 1 updated")
label_spin1 = win.findChild(QObject, "label_spin1")
label_spin1.setProperty("text", spin1_int)
def spin2_update(spin2_int):
print("Spin 2 updated")
label_spin2 = win.findChild(QObject, "label_spin2")
label_spin2.setProperty("text", spin2_int)
def spin_sum(spin1_int, spin2_int):
my_sum = spin1_int + spin2_int
label_result = win.findChild(QObject, "label_result")
label_result.setProperty("text", my_sum)
if __name__ == "__main__":
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load('main.qml')
win = engine.rootObjects()[0]
spin1 = win.findChild(QObject, "spin1")
spin1.sig_spin1.connect(spin1_update)
spin2 = win.findChild(QObject, "spin2")
spin2.sig_spin2.connect(spin2_update)
#win.exportSignals.connect()
win.show()
sys.exit(app.exec_())
更新。为了完整起见,一个工作示例: main.py:
import sys
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, QCoreApplication, QObject, QUrl
from PyQt5.QtQml import QQmlEngine, QQmlApplicationEngine
from PyQt5.QtWidgets import QApplication
class GuiInteraction(QObject):
def __init__(self, parent=None):
super().__init__(parent)
@pyqtSlot(int, int, result=int)
def get_sum(self, spin1, spin2):
print("Spin1 from python: ", spin1)
print("Spin2 from the same python slot: ", spin2)
my_sum = spin1 + spin2
print(my_sum)
print()
return my_sum
if __name__ == "__main__":
app = QApplication(sys.argv)
guiInteraction = GuiInteraction()
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("guiInteraction", guiInteraction)
engine.load('main.qml')
win = engine.rootObjects()[0]
win.show()
sys.exit(app.exec_())
还有main.qml:
import QtQuick 2.6
import QtQuick.Controls 2.0
ApplicationWindow{
visible:true
width:200
height:300
id:window
title: "Signal/Slot Test"
Rectangle{
Column {
spacing: 20
width: parent.width
SpinBox {
id: spin1
value: 50
width: 120
editable: true
Component.onCompleted: {
console.log("Spin1: " + spin1.value)
}
onValueChanged: {
console.log("Spin1: " + spin1.value)
label_result.text = guiInteraction.get_sum(spin1.value, spin2.value)
}
}
SpinBox {
id: spin2
value: 50
width: 120
editable: true
Component.onCompleted: {
console.log("Spin2: " + spin2.value)
}
onValueChanged: {
console.log("Spin2: " + spin2.value)
label_result.text = guiInteraction.get_sum(spin1.value, spin2.value)
}
}
Label {
id: label_result
objectName: "label_result"
text: "Nothing yet."
}
}
}
}
【问题讨论】:
-
为什么要用Python来设置标签的值?与 C++ 一样,您可以从 C++ 设置值,但不建议您这样做,我怀疑在 PyQt 中这样做是一种好风格。
-
也许我误解了这应该如何工作。我不知道 C++,但知道一些 Python。所以很自然地,我想从用户可以在 qml gui 中设置的值在 Python 中执行一些计算,然后将它们发送回 gui。这完全超出了 PyQt 的范围吗?我认为这是一个非常自然的用例。
-
我的意思是 Kevin Krammer 在他的回答中所描述的。您应该使用属性绑定来获取 QML 端的值。因此,不要使用 Python 写入 QML 端,而是使用 QML 从 Python 端读取。