앱을 사용하다가 tray icon 으로 축소를 하면 좀더 편하겠다는 생각이 들었습니다.

1) 코드 생성

사용한 ChatGPT 프롬프트는 다음과 같습니다.

pyqt5 로 Hello 라는 버튼을 표시해주세요.
축소 아이콘을 클릭하면 누르면 tray 로 축소하고
종료 아이콘을 클릭하면 앱을 종료하시겠습니까? 라고 묻고 Yes 선택 시 앱을 종료하고 다른 것을 선택하면 tray 로 축소하도록 해주세요.

 

생성된 코드는 다음과 같으며 일부 버그는 수정하였습니다.

아래 코드는 다음과 같이 다운받을 수 있습니다.

git clone git@github.com:jbpark/jbDeskExample.git
cd jbDeskExample/jbDesk/ch1.4

 

tray_icon.py

import sys

from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMenu, QAction, QMessageBox, QSystemTrayIcon


class HelloApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("PyQt5 Tray Example")
        self.setGeometry(100, 100, 300, 200)

        # 버튼 생성
        self.button = QPushButton("Hello", self)
        self.button.setGeometry(100, 80, 100, 40)
        self.button.clicked.connect(self.show_message)

        # 시스템 트레이 아이콘 생성
        self.tray_icon = QSystemTrayIcon(self)
        icon_path = "tray_icon.png"  # 아이콘 경로 확인 (아이콘 파일이 있어야 합니다)
        self.tray_icon.setIcon(QIcon(icon_path))
        self.tray_icon.setToolTip("PyQt5 Tray App")
        self.tray_icon.show()  # 트레이 아이콘 표시

        # 트레이 메뉴 설정
        tray_menu = QMenu()
        restore_action = QAction("열기", self)
        restore_action.triggered.connect(self.show_window)

        quit_action = QAction("종료", self)
        quit_action.triggered.connect(self.exit_app)

        tray_menu.addAction(restore_action)
        tray_menu.addAction(quit_action)

        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.activated.connect(self.tray_icon_clicked)

    def show_message(self):
        QMessageBox.information(self, "Message", "Hello, PyQt5!")

    def closeEvent(self, event):
        """창 닫기 버튼(X) 클릭 시 앱 종료 여부 확인"""
        reply = QMessageBox.question(self, "종료 확인", "앱을 종료하시겠습니까?",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            self.exit_app()
        else:
            event.ignore()  # 창을 최소화하여 숨깁니다
            self.hide()  # 창 숨기기
            self.tray_icon.showMessage(
                "앱이 실행 중", "트레이에서 실행 중입니다.", QSystemTrayIcon.Information, 2000
            )

    def show_window(self):
        """트레이 메뉴에서 '열기' 선택 시 창 복원"""
        self.showNormal()
        self.activateWindow()

    def tray_icon_clicked(self, reason):
        """트레이 아이콘 클릭 시 창을 다시 보이게 함"""
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            self.show_window()

    def exit_app(self):
        """트레이 메뉴에서 '종료' 선택 시 앱 완전히 종료"""
        self.tray_icon.hide()  # 트레이 아이콘 숨기기
        QApplication.quit()  # PyQt5 이벤트 루프 종료
        sys.exit(0)  # 강제 종료


if __name__ == "__main__":
    app = QApplication(sys.argv)

    # 모든 창이 닫혀도 앱이 종료되지 않도록 설정
    app.setQuitOnLastWindowClosed(False)

    # 아이콘 설정
    app.setWindowIcon(QIcon("tray_icon.png"))

    window = HelloApp()
    window.show()
    sys.exit(app.exec_())

 

2) 코드 실행

코드 실행 후 tray 축소 전입니다.

 

축소 아이콘을 클릭하면 아래와 같이 tray icon 으로 표시됩니다.

 

3) JbDesk 에 코드 통합

tray_icon.py 에서 tray 관련 부분만 jbesk.py 에 머지하면 됩니다.

코드는 다음 위치에 있습니다.

git clone git@github.com:jbpark/jbDeskExample.git
cat jbDeskExample/jbDesk/ch1.4/jbesk.py

다음은 코드 통합 후 실행한 모습이며 종료 아이콘 클릭 시 앱을 종료할지 물어봅니다.

Yes 클릭 시 앱이 종료되며 No 선택 시 Tray icon 으로 축소됩니다.

Posted by 제이브레인
,