1

I'm trying to create a launcher (like Albert or Spotlight). To do so, I need to connect a shortcut to the show() function of my window. I'm using the keyboard library for this.

This is where I am:

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()

But when calling the shortcut, I'm getting the following Qt error:

QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread

Does someone have an idea of what may cause this?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Munshine
  • 402
  • 3
  • 14
  • 1
    Possible duplicate of or helpful: [Cannot send posted events for objects in another thread](https://stackoverflow.com/questions/21508401/cannot-send-posted-events-for-objects-in-another-thread) – chickity china chinese chicken Oct 18 '18 at 18:18

1 Answers1

1

The message indicates the problem is that the callback is called from another thread and in Qt the GUI can not be updated from another thread, a possible solution is to create a class that provides a signal that connects to the show, and that signal is issued as a callback.

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()

Or a better option for these cases use QMetaObject::invokeMethod() with Qt::QueuedConnection since show() is a slot as I show below:

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()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241