Similar article on Qt/C++
One of the first articles on working with Qt has an article on working with QSystemTrayIcon . Now came the turn of the same material, but in Python using PyQt5 library.
This article will discuss how to write a simple application to PyQt5, which will be minimized to the system tray when you click a menu item in the system tray icon, or by pressing the close button.
Project structure in this case is minimal. There is only one file, which will be run. That is main .py file.
The application itself will be as follows.
If the checkbox is checked, the application will minimize to the system tray, otherwise the application will be terminated. In addition, it is possible to fold the application to the system tray using the context menu of the application icon in the system tray.
When the application is minimized to the system tray on the close button of the application window, it will display a message about it.
main .py
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout, QWidget, QCheckBox, QSystemTrayIcon, \ QSpacerItem, QSizePolicy, QMenu, QAction, QStyle, qApp from PyQt5.QtCore import QSize class MainWindow(QMainWindow): """ Сheckbox and system tray icons. Will initialize in the constructor. """ check_box = None tray_icon = None # Override the class constructor def __init__(self): # Be sure to call the super class method QMainWindow.__init__(self) self.setMinimumSize(QSize(480, 80)) # Set sizes self.setWindowTitle("System Tray Application") # Set a title central_widget = QWidget(self) # Create a central widget self.setCentralWidget(central_widget) # Set the central widget grid_layout = QGridLayout(self) # Create a QGridLayout central_widget.setLayout(grid_layout) # Set the layout into the central widget grid_layout.addWidget(QLabel("Application, which can minimize to Tray", self), 0, 0) # Add a checkbox, which will depend on the behavior of the program when the window is closed self.check_box = QCheckBox('Minimize to Tray') grid_layout.addWidget(self.check_box, 1, 0) grid_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding), 2, 0) # Init QSystemTrayIcon self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setIcon(self.style().standardIcon(QStyle.SP_ComputerIcon)) ''' Define and add steps to work with the system tray icon show - show window hide - hide window exit - exit from application ''' show_action = QAction("Show", self) quit_action = QAction("Exit", self) hide_action = QAction("Hide", self) show_action.triggered.connect(self.show) hide_action.triggered.connect(self.hide) quit_action.triggered.connect(qApp.quit) tray_menu = QMenu() tray_menu.addAction(show_action) tray_menu.addAction(hide_action) tray_menu.addAction(quit_action) self.tray_icon.setContextMenu(tray_menu) self.tray_icon.show() # Override closeEvent, to intercept the window closing event # The window will be closed only if there is no check mark in the check box def closeEvent(self, event): if self.check_box.isChecked(): event.ignore() self.hide() self.tray_icon.showMessage( "Tray Program", "Application was minimized to Tray", QSystemTrayIcon.Information, 2000 ) if __name__ == "__main__": import sys app = QApplication(sys.argv) mw = MainWindow() mw.show() sys.exit(app.exec())
Congratulations on the article, it was a great help.
No problem. If you need help with another questions with PyQt5. Then you can ask me on the forum in this site .
В консоль выдается предупреждение. Почему и как исправить? Может ошибка в коде или QGridLayout как-нибудь не так добавляется?
Если не ошибаюсь, можно просто удалить вот эту строку
Добрый вечер Евгений и форумчане! Не подскажите почему в при запуске данного кода в PyCharm выдаётся сообщение: "ModuleNotFoundError: No module named 'PyQt5'"?
PyQt5 установлен
Решение проблемы нашел в интернете)) Лечится так: File - Settings - Project:{name_my_project} - Project Interpreter - устанавливаем нужную нам версию интерпретатора(python 3.6.2 например) - Install(плюсик сбоку) - Available Packages - набираем в поиске PyQt5 - нажимаем Install Package
Хорошо, что нашли решение. Получается что через виртуальную среду проекта настроили, если правильно понимаю
для питона можно использовать виртуальную среду, в которой будут установлены требуемые версии пакетов. Это позволяет держать на одной системе для каждого проекта свой набор пакетов с требуемыми версиями.
Спасибо за подсказку, запомню на будущее.
Добрый день, Евгений,
Подскажите, почему может не гореть чекбокс?
С уважением,
Сергей
Добрый день. Вы полностью скопировали код?
Евгений,
Разобрался, спасибо. вместо check_box я писал kek_box, вот и не работало.
Спасибо, статья полезная. Непонятен один момент, как повесить действие на двойное нажатие?
У TrayIcon есть триггер Activated, но он срабатывает при одинарном нажатии.
У Activated есть Activation reason, среди которых есть QSystemTrayIcon::DoubleClick. Но как это использовать?
Пробовал по-разному, в том числе и:
Работать не хочет
Передавать значение не нужно, вам нужно событие обрабатывать в self.myfunc
Попробуйте подключить слот так
Спасибо за ответ.
Нет, еслли передавать без уточенения, тоесть как вы сказали, тогда триггер срабатывает на любые нажатия. На одинарное нажатие, на одинарное нажатие правой кнопкой тоже (таким образом чтобы вызвать меню - надо нажать правой кнопкой, сработает триггер на функцию, нажать правой кнопкой ещё раз - и только тогда появится меню).
Нужно как то уточнить, чтобы сигнал activated появлялся только при даблклике. Я вотт вычитал что для этого надо передавать Activation reason, о никак не пойму как.
А надо это, для того чтобы двойным щелчком по иконке в трее открывалось окно
Ваша функция должна принимать аргумент, событие, которое вы потом через if else прогоните и определитесь, какое именно событие прилетело.
Спасибо. Вот теперь это работает
Thank you... Thank you.... comrade