您能帮助我使用正确的语法来连接 DBus 信号吗?
这是我的众多尝试之一,它至少运行并匹配文档中的签名:
from PySide6 import QtDBus
from PySide6.QtCore import Q
from PySide6.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
__slots__ = ["__mainwidget"]
__mainwidget:QWidget
def __init__ (self, *args, **kwargs):
super().__init__(*args, **kwargs)
service = 'org.freedesktop.DBus'
path = '/org/freedesktop/DBus'
iface = 'org.freedesktop.DBus'
conn = QtDBus.QDBusConnection.systemBus()
conn.connect(service, path, iface, "NameOwnerChanged", self, "nochangeslot")
#smp = QtDBus.QDBusInterface(service, path, iface, connection=QtDBus.QDBusConnection.systemBus()
def nochangeslot(self, arg:object) -> None:
print(arg)
pass
但是它不起作用,并且将插槽作为字符串看起来很奇怪......
在输出中我看到:
qt.dbus.integration: Could not connect "org.freedesktop.DBus" to ochangeslot
请考虑这是 PySide6 问题而不是 PyQt5 问题,调用的签名略有不同,并且我的代码不会像 stackoverflow 上的类似主题那样挂起。
预先感谢您的帮助!
该示例有两个问题,第一个问题已在此处得到解答:
因此,您首先只需将以下行添加到示例中:
conn.registerObject('/', self)
第二个问题在 PyQt 中很容易解决(在上面链接的问题中清楚地显示)。然而,PySide 似乎仍在其 dbus API 中使用丑陋且容易出错的 C++ 语法,如果您不是 PyQt/PySide 的长期用户,这可能会使连接信号和插槽变得极其不直观。相比之下,PyQt 发送通用的QDBusMessage,这大大简化了事情,因为不需要事先知道签名的确切形式。为了说明差异,这里有两个基本的工作示例:
PyQt6:
from PyQt6 import QtCore, QtWidgets, QtDBus
class MainWindow(QtWidgets.QMainWindow):
def __init__ (self):
super().__init__()
service = 'org.freedesktop.DBus'
path = '/org/freedesktop/DBus'
iface = 'org.freedesktop.DBus'
conn = QtDBus.QDBusConnection.systemBus()
conn.registerObject('/', self)
conn.connect(service, path, iface, 'NameAcquired', self.nochangeslot)
@QtCore.pyqtSlot(QtDBus.QDBusMessage)
def nochangeslot(self, msg):
print(f'signature: {msg.signature()!r}, '
f'arguments: {msg.arguments()!r}')
app = QtWidgets.QApplication(['Test'])
window = MainWindow()
window.show()
app.exec()
PySide6:
from PySide6 import QtCore, QtWidgets, QtDBus
class MainWindow(QtWidgets.QMainWindow):
def __init__ (self):
super().__init__()
service = 'org.freedesktop.DBus'
path = '/org/freedesktop/DBus'
iface = 'org.freedesktop.DBus'
conn = QtDBus.QDBusConnection.systemBus()
conn.registerObject('/', self)
conn.connect(service, path, iface, 'NameAcquired',
self, QtCore.SLOT('nochangeslot(QString)'))
@QtCore.Slot(str)
def nochangeslot(self, args):
print(f'arguments: {args!r}')
app = QtWidgets.QApplication(['Test'])
window = MainWindow()
window.show()
app.exec()
这是我最初帖子的完整解决方案,我在 QT/PySide 支持下运行了它,他们还承认了hangig bug 和 Python 崩溃:
import sys
from PySide6.QtWidgets import QMainWindow
from PySide6 import QtDBus, QtCore
from PySide6.QtCore import QLibraryInfo, qVersion, Slot
from PySide6.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__ (self, *args, **kwargs):
super().__init__(*args, **kwargs)
service = "org.freedesktop.DBus"
path = "/org/freedesktop/DBus"
iface = "org.freedesktop.DBus"
conn = QtDBus.QDBusConnection.systemBus()
#without this, the conn.connect call hangs, seems to be a bug, is already reported and fixed.
conn.registerObject('/', self)
conn.connect(service, path, iface, "NameOwnerChanged", self, QtCore.SLOT("nameownerchanged(QString, QString, QString)"))
pass
@Slot(str, str, str)
def nameownerchanged(self, arg1:str, arg2:str, arg3:str) -> None:
print(arg1)
print(arg2)
print(arg3)
pass
if __name__ == '__main__':
print('Python {}.{}.{} {}'.format(sys.version_info[0], sys.version_info[1],
sys.version_info[2], sys.platform))
print(QLibraryInfo.build())
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle(qVersion())
window.resize(800, 480)
window.show()
sys.exit(app.exec())