PyQt 如何通过连续点击托盘图标显示隐藏主窗口并且在主窗口隐藏时调整界面到托盘图标附近

不废话直接看代码

python 复制代码
# -*- coding=utf-8 -*-
# ==========================================
#       author: Ruben
#         mail: 773849069@qq.com
#         time: 2023/12/8
# ==========================================
u"""
一个托盘图标的小部件
"""
from Qt import QtWidgets, QtGui, QtCore


# --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*


class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
    """拓展托盘图标,可移动界面至托盘图标附近"""
    clicked = QtCore.Signal()  # 单击
    double_clicked = QtCore.Signal()  # 双击
    right_clicked = QtCore.Signal()  # 右键

    def __init__(self, *args, **kwargs):
        super(SystemTrayIcon, self).__init__(*args, **kwargs)
        self.activated.connect(self.__activated)

    def __activated(self, reason):
        if reason == self.Trigger:
            self.clicked.emit()
        elif reason == self.DoubleClick:
            self.double_clicked.emit()
        elif reason == self.Context:
            self.right_clicked.emit()

    @staticmethod
    def available_geometry(pos):
        """
        传入控件位置返回控件所在的屏幕的可用大小

        Args:
            pos: QtCore.QPoint

        Returns:
            QtCore.QRect
        """
        desktop = QtWidgets.QApplication.instance().desktop()
        return desktop.availableGeometry(pos)

    def move_widget_to_system_tray_icon(self, widget, margin=10):
        """
        将界面移动到托盘图标附近

        Args:
            widget: QWidget
            margin: 10px

        Returns:
            QtCore.QPoint
        """
        center = self.geometry().center()
        tray_x = center.x()
        tray_y = center.y()
        screen_geometry = self.available_geometry(center)

        # 托盘图标和屏幕边缘的距离
        top = abs(tray_y - screen_geometry.top())
        bottom = abs(screen_geometry.bottom() - tray_y)
        left = abs(tray_x - screen_geometry.left())
        right = abs(screen_geometry.right() - tray_x)

        # 获得屏幕边缘的最小距离
        v = min(top, bottom)  # 纵向
        h = min(left, right)  # 横向

        if h < v:  # 纵向菜单栏
            if right > left:  # 左
                x = screen_geometry.left() + margin
                y = tray_y - widget.height()
            else:  # 右
                x = screen_geometry.right() - widget.width() - margin
                y = tray_y - widget.height()
        else:  # 横向菜单栏
            if top < bottom:  # 上
                x = screen_geometry.right() - widget.width() - right
                y = screen_geometry.top() + margin
            else:  # 下
                x = screen_geometry.right() - widget.width() - right
                y = screen_geometry.bottom() - widget.height() - 30 - margin

        widget.move(x, y)


class Application(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        """初始化主应用程序窗口"""
        super(Application, self).__init__(*args, **kwargs)
        self._initialise_tray()
        self.setWindowIcon(self.tray_icon())
        self.setWindowTitle("托盘图标演示主界面")

    def tray_icon(self):
        """使用Qt内置的图标"""
        icon = self.style().standardIcon(QtWidgets.QStyle.SP_TrashIcon)
        return icon

    def _initialise_tray(self):
        u"""初始化并添加应用程序图标到系统托盘"""
        self.tray_menu = self._create_tray_menu()
        self.tray = SystemTrayIcon(self.tray_icon(), self)
        self.tray.setContextMenu(self.tray_menu)
        self.tray.clicked.connect(self.show_main_widget)
        self.tray.show()

    def _create_tray_menu(self):
        """创建菜单并连接信号"""
        menu = QtWidgets.QMenu()
        action = menu.addAction("显示主界面")
        action.triggered.connect(self.show_main_widget)
        action = menu.addAction("退出")
        action.triggered.connect(QtWidgets.QApplication.quit)
        return menu

    def focus(self):
        u"""显示窗口并放到最上边"""
        self.activateWindow()
        self.showNormal()
        self.raise_()

    def show_main_widget(self):
        """显示主界面"""
        if self.isMinimized():
            # 在最小化状态时,显示界面
            self.focus()
        elif self.isHidden():
            # 隐藏的状态给它显示并移动到托盘图标附近
            self.tray.move_widget_to_system_tray_icon(self)
            self.focus()
        else:
            # 已显示的给它最小化
            self.showMinimized()


if __name__ == '__main__':
    _app = QtWidgets.QApplication([])
    _app.setQuitOnLastWindowClosed(False)
    _win = Application()
    _win.resize(300, 100)
    _win.show()
    _app.exec_()
相关推荐
m0_594526301 分钟前
Python批量合并多个PDF
java·python·pdf
工业互联网专业15 分钟前
Python毕业设计选题:基于Hadoop的租房数据分析系统的设计与实现
vue.js·hadoop·python·flask·毕业设计·源码·课程设计
钱钱钱端22 分钟前
【压力测试】如何确定系统最大并发用户数?
自动化测试·软件测试·python·职场和发展·压力测试·postman
慕卿扬23 分钟前
基于python的机器学习(二)—— 使用Scikit-learn库
笔记·python·学习·机器学习·scikit-learn
Json____29 分钟前
python的安装环境Miniconda(Conda 命令管理依赖配置)
开发语言·python·conda·miniconda
小袁在上班1 小时前
Python 单元测试中的 Mocking 与 Stubbing:提高测试效率的关键技术
python·单元测试·log4j
白狐欧莱雅1 小时前
使用python中的pygame简单实现飞机大战游戏
经验分享·python·游戏·pygame
阿_旭1 小时前
基于YOLO11/v10/v8/v5深度学习的维修工具检测识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
人工智能·python·深度学习·qt·ai
阿_旭1 小时前
基于YOLO11/v10/v8/v5深度学习的煤矿传送带异物检测系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
人工智能·python·深度学习·目标检测·yolo11
测试19981 小时前
外包干了2年,快要废了。。。
自动化测试·软件测试·python·面试·职场和发展·单元测试·压力测试