将 QML 信号连接到 PySide2 插槽
Connect QML signal to PySide2 slot
我有一些使用 Qt/C++ 的经验,现在我想切换到 PySide2 + QML。我想将 ui 信号(例如单击按钮)连接到 python 槽
我看过很多例子,但它们都不一样,我想 PyQt/PySide 现在正在改变 quickly
你能给我提供一种将 QML 信号连接到 PySide Slot 的现代而简洁的方法吗?例如单击一个按钮在 python 控制台中打印一些文本。这是我的简单代码示例
main.py
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
def test_slot(string): # pseudo slot
print(string)
if __name__ == "__main__":
app = QGuiApplication()
engine = QQmlApplicationEngine('main.qml')
exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
Button {
anchors.centerIn: parent
text: "Example"
onClicked: test_slot("Test") //pseudo signal
}
}
在这些情况下,最佳做法是创建一个 QObject,将其导出到 QML 并在那里建立连接,就像在 C++ 中一样。
main.py
from PySide2.QtCore import QObject, QUrl, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
class Foo(QObject):
@Slot(str)
def test_slot(self, string):
print(string)
if __name__ == "__main__":
import os
import sys
app = QGuiApplication()
foo = Foo()
engine = QQmlApplicationEngine()
engine.rootContext().setContextProperty("foo", foo)
qml_file = "main.qml"
current_dir = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(current_dir, qml_file)
engine.load(QUrl.fromLocalFile(filename))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
Button {
anchors.centerIn: parent
text: "Example"
onClicked: foo.test_slot("Test")
}
}
注意:所有 C++/QML 良好实践也适用于 Python/QML,只有极少的更改和限制。
eyllanesc的方案是直接同步调用方法test_slot
。当 test_slot
小而快时很好。但是如果包含很多操作,QML GUI会每次都挂起,直到返回test_slot
。
最类似于 Qt 的方式是 slog-signal 元对象连接(参见下面的 #CHANGES
和 //CHANGES
):
main.py
from PySide2.QtCore import QObject, QUrl, Slot, Signal, Qt
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
class Foo(QObject):
@Slot(str)
def test_slot(self, input_string : str):
print(input_string)
if __name__ == "__main__":
import os
import sys
app = QGuiApplication()
foo = Foo()
engine = QQmlApplicationEngine()
#CHANGES: line excluded engine.rootContext().setContextProperty("foo", foo)
qml_file = "main.qml"
current_dir = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(current_dir, qml_file)
engine.load(QUrl.fromLocalFile(filename))
if not engine.rootObjects():
sys.exit(-1)
#CHANGES: connect QML signal to Python slot
engine.rootObjects()[0].test_signal.connect(foo.test_slot, type=Qt.ConnectionType.QueuedConnection)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
//CHANGES: declare signal
signal test_signal(string input_string)
Button {
anchors.centerIn: parent
text: "Example"
//CHANGES: emit signal
onClicked: test_signal("Test string")
}
}
我有一些使用 Qt/C++ 的经验,现在我想切换到 PySide2 + QML。我想将 ui 信号(例如单击按钮)连接到 python 槽
我看过很多例子,但它们都不一样,我想 PyQt/PySide 现在正在改变 quickly
你能给我提供一种将 QML 信号连接到 PySide Slot 的现代而简洁的方法吗?例如单击一个按钮在 python 控制台中打印一些文本。这是我的简单代码示例
main.py
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
def test_slot(string): # pseudo slot
print(string)
if __name__ == "__main__":
app = QGuiApplication()
engine = QQmlApplicationEngine('main.qml')
exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
Button {
anchors.centerIn: parent
text: "Example"
onClicked: test_slot("Test") //pseudo signal
}
}
在这些情况下,最佳做法是创建一个 QObject,将其导出到 QML 并在那里建立连接,就像在 C++ 中一样。
main.py
from PySide2.QtCore import QObject, QUrl, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
class Foo(QObject):
@Slot(str)
def test_slot(self, string):
print(string)
if __name__ == "__main__":
import os
import sys
app = QGuiApplication()
foo = Foo()
engine = QQmlApplicationEngine()
engine.rootContext().setContextProperty("foo", foo)
qml_file = "main.qml"
current_dir = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(current_dir, qml_file)
engine.load(QUrl.fromLocalFile(filename))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
Button {
anchors.centerIn: parent
text: "Example"
onClicked: foo.test_slot("Test")
}
}
注意:所有 C++/QML 良好实践也适用于 Python/QML,只有极少的更改和限制。
eyllanesc的方案是直接同步调用方法test_slot
。当 test_slot
小而快时很好。但是如果包含很多操作,QML GUI会每次都挂起,直到返回test_slot
。
最类似于 Qt 的方式是 slog-signal 元对象连接(参见下面的 #CHANGES
和 //CHANGES
):
main.py
from PySide2.QtCore import QObject, QUrl, Slot, Signal, Qt
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
class Foo(QObject):
@Slot(str)
def test_slot(self, input_string : str):
print(input_string)
if __name__ == "__main__":
import os
import sys
app = QGuiApplication()
foo = Foo()
engine = QQmlApplicationEngine()
#CHANGES: line excluded engine.rootContext().setContextProperty("foo", foo)
qml_file = "main.qml"
current_dir = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(current_dir, qml_file)
engine.load(QUrl.fromLocalFile(filename))
if not engine.rootObjects():
sys.exit(-1)
#CHANGES: connect QML signal to Python slot
engine.rootObjects()[0].test_signal.connect(foo.test_slot, type=Qt.ConnectionType.QueuedConnection)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
//CHANGES: declare signal
signal test_signal(string input_string)
Button {
anchors.centerIn: parent
text: "Example"
//CHANGES: emit signal
onClicked: test_signal("Test string")
}
}