尝试显示小部件时出现线程问题
Thread issue when trying to show a widget
我正在尝试创建一个启动器(例如 Albert 或 Spotlight)。为此,我需要将快捷方式连接到 window 的 show() 函数。为此,我正在使用 keyboard 库。
我在这里:
import sys
from PySide import QtGui
import keyboard
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
keyboard.add_hotkey('ctrl+alt+9', window.show, args=[])
sys.exit(app.exec_())
if __name__ == '__main__':
main()
但是在调用快捷方式时,出现以下 Qt 错误:
QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
有人知道这可能是什么原因吗?
消息表明问题是回调是从另一个线程调用的,而在 Qt 中,GUI 不能从另一个线程更新,一个可能的解决方案是创建一个 class 来提供连接信号显示,并且该信号作为回调发出。
import sys
import keyboard
from PySide import QtCore, QtGui
class SignalHelper(QtCore.QObject):
signal = QtCore.Signal()
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
helper = SignalHelper()
helper.signal.connect(window.show)
keyboard.add_hotkey('ctrl+alt+9', helper.signal.emit)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
对于这些情况,更好的选择是将 QMetaObject::invokeMethod()
与 Qt::QueuedConnection
结合使用,因为 show()
是一个插槽,如下所示:
import sys
import keyboard
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
keyboard.add_hotkey('ctrl+alt+9',
QtCore.QMetaObject.invokeMethod,
args=(window, "show", QtCore.Qt.QueuedConnection))
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我正在尝试创建一个启动器(例如 Albert 或 Spotlight)。为此,我需要将快捷方式连接到 window 的 show() 函数。为此,我正在使用 keyboard 库。
我在这里:
import sys
from PySide import QtGui
import keyboard
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
keyboard.add_hotkey('ctrl+alt+9', window.show, args=[])
sys.exit(app.exec_())
if __name__ == '__main__':
main()
但是在调用快捷方式时,出现以下 Qt 错误:
QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
有人知道这可能是什么原因吗?
消息表明问题是回调是从另一个线程调用的,而在 Qt 中,GUI 不能从另一个线程更新,一个可能的解决方案是创建一个 class 来提供连接信号显示,并且该信号作为回调发出。
import sys
import keyboard
from PySide import QtCore, QtGui
class SignalHelper(QtCore.QObject):
signal = QtCore.Signal()
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
helper = SignalHelper()
helper.signal.connect(window.show)
keyboard.add_hotkey('ctrl+alt+9', helper.signal.emit)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
对于这些情况,更好的选择是将 QMetaObject::invokeMethod()
与 Qt::QueuedConnection
结合使用,因为 show()
是一个插槽,如下所示:
import sys
import keyboard
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Example')
def main():
app = QtGui.QApplication(sys.argv)
window = Example()
keyboard.add_hotkey('ctrl+alt+9',
QtCore.QMetaObject.invokeMethod,
args=(window, "show", QtCore.Qt.QueuedConnection))
sys.exit(app.exec_())
if __name__ == '__main__':
main()