0

I want to create an application with a system tray icon. This app should detect the hotkey and react to it, even if the app is not focused (icon tray).

Example: I want to show the window, then I press Alt + X. The window is showing.

I tried using some global hotkey libraries but whenever the window is showing by hotkey, it freezes. The Show option in my QMenu still working.

I'm new to programming, thanks!

Here is my code:

from PyQt5.QtCore import QSize, Qt
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit, QVBoxLayout, QHBoxLayout, QWidget, QSystemTrayIcon, QMenu
from PyQt5.QtGui import QIcon, QKeySequence

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('GTyperP5')
        self.setWindowIcon(QIcon('GTyperP5.ico'))
        self.setFixedSize(QSize(192, 64))
        self.setWindowFlag(Qt.WindowMinimizeButtonHint, False)

        self.textInput = QLineEdit()

        self.typeButton = QPushButton('Type')
        self.typeButton.setFixedSize(QSize(50, 25))
        self.typeButton.clicked.connect(self.cut_all)

        self.textInput.returnPressed.connect(self.typeButton.click)

        self.cancelButton = QPushButton('Cancel')
        self.cancelButton.setFixedSize(QSize(50, 25))
        self.cancelButton.clicked.connect(self.hide_window)

        layout = QVBoxLayout()
        layout.addWidget(self.textInput, alignment = Qt.AlignHCenter | Qt.AlignTop)

        layout_ex = QHBoxLayout()
        layout_ex.addWidget(self.cancelButton, alignment = Qt.AlignRight)
        layout_ex.addWidget(self.typeButton, alignment = Qt.AlignLeft)

        layout.addLayout(layout_ex)

        container = QWidget()
        container.setLayout(layout)

        self.setCentralWidget(container)

        self.trayIcon = QSystemTrayIcon(QIcon('GTyperP5.ico'), parent = app)
        self.trayIcon.setToolTip('GTyperP5')

        menu = QMenu()
        showAction = menu.addAction('Show')
        showAction.triggered.connect(self.show_window)

        exitAction = menu.addAction('Exit')
        exitAction.triggered.connect(app.quit)

        self.trayIcon.setContextMenu(menu)
        self.trayIcon.show()
        self.trayIcon.showMessage('GTyperP5 has started!', 'Thank you for using! :D', QIcon('GTyperP5.ico'), msecs = 10000)
        self.trayIcon.activated.connect(self.doubleClick)

    def closeEvent(self, event):
        self.hide_window()
        event.ignore()

    def doubleClick(self, reason):
        if reason == QSystemTrayIcon.DoubleClick:
            self.show_window()

    def cut_all(self):
        clip = QApplication.clipboard()
        clip.clear(mode = clip.Clipboard)
        clip.setText(self.textInput.text(), mode = clip.Clipboard)
        self.textInput.setText('')
        self.hide_window()

    def hide_window(self):
        self.trayIcon.show()
        self.hide()

    def show_window(self):
        self.trayIcon.hide()
        self.show()
        self.raise_()
        self.textInput.setFocus()

app = QApplication([])
window = MainWindow()
window.show()
app.exec()
  • Qt doesn't provide access to global key events, so using external libraries is the only choice. The problem is that those libraries normally use threading, so you cannot directly call UI functions from them (UI elements are not thread safe and must *never* be directly accessed from external threads). Embed the functions of those libraries in a QThread, and use custom signals. If you need further help with that, please [edit] your post and show us your attempts with those libraries. – musicamante Dec 20 '22 at 19:41

0 Answers0