这个程序主要完成几个目的:

1. 主窗口控件最小化等操作后正常可用(点击按钮会在textBrowser中加入一行hello world);

雷电python最小化命令 python程序最小化托盘_python

2. 点击右上角x键可以显示提示信息且按钮功能正常(退出程序或者最小化到托盘);

雷电python最小化命令 python程序最小化托盘_pyqt_02

3. 最小化到托盘后实现两个功能(左键单击显示或隐藏主界面,右键显示显示选线可以关闭或者显示主界面,);

 

1. 首先用designer新建了一个demo,这个demo上只有两个控件,一个是textBrowser,一个是pushButton,直接从designer侧边拖就行了。

有空还可以设置下图标之类的。

总之整体界面长这样。

雷电python最小化命令 python程序最小化托盘_qt_03

然后将这个界面换成py文件。

2. 新建一个主函数文件,随笔起个名字就叫demo.py吧

主要功能就是把这个设计的界面启动起来

#coding = 'utf-8'
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import Ui_untitled
import time
 
# 函数功能:在textBrowser中添加hello world字段
# 输入参数:ui对象
# 输出参数:
def buttonClicked(girl):
    girl.textBrowser.append("hello world")
 
if __name__ == '__main__':
    # 创建一个应用对象
    app = QtWidgets.QApplication(sys.argv)
    # 创建QT主窗口对象
    MainWindow = QtWidgets.QMainWindow()
    # 创建UI对象
    ui = Ui_untitled.Ui_MainWindow()
    # 调用setupUi方法,将设计好的界面-->主窗口上
    ui.setupUi(MainWindow)
 
    ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
 
    # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
    MainWindow.show()
    # 
    sys.exit(app.exec_())

然后这个自动生成ui的py文件长这样

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'c:\My_World\gitee_code\qt_toolkit\hello_world\untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect(160, 110, 256, 192))
        self.textBrowser.setObjectName("textBrowser")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(570, 190, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

3. 添加托盘图标功能

这个具体可以看这个

主要就是我们要新建一个类,专门搞这个托盘功能的。

class TrayIcon(QtWidgets.QSystemTrayIcon):
    def __init__(self,MainWindow,parent=None):
        super(TrayIcon, self).__init__(parent)
        self.ui = MainWindow
        self.createMenu()
    
    def createMenu(self):
        self.menu = QtWidgets.QMenu()
        self.showAction1 = QtWidgets.QAction("启动", self, triggered=self.show_window)
        self.showAction2 = QtWidgets.QAction("显示通知", self,triggered=self.showMsg)
        self.quitAction = QtWidgets.QAction("退出", self, triggered=self.quit)

        self.menu.addAction(self.showAction1)
        self.menu.addAction(self.showAction2)
        self.menu.addAction(self.quitAction)
        self.setContextMenu(self.menu)

        #设置图标
        self.setIcon(QtGui.QIcon("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"))
        self.icon = self.MessageIcon()

        #把鼠标点击图标的信号和槽连接
        self.activated.connect(self.onIconClicked)

    def showMsg(self):
        self.showMessage("Message", "skr at here", self.icon)

    def show_window(self):
        #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
        self.ui.showNormal()
        self.ui.activateWindow()
        
 
    def quit(self):
        QtWidgets.qApp.quit()

    #鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击
    def onIconClicked(self, reason):
        if reason == 2 or reason == 3:
            # self.showMessage("Message", "skr at here", self.icon)
            if self.ui.isMinimized() or not self.ui.isVisible():
                #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
                self.ui.showNormal()
                self.ui.activateWindow()
                self.ui.setWindowFlags(QtCore.Qt.Window)
                self.ui.show()
            else:
                #若不是最小化,则最小化
                self.ui.showMinimized()
                self.ui.setWindowFlags(QtCore.Qt.SplashScreen)
                self.ui.show()
                # self.ui.show()

这个类实现了托盘的几个功能,首先是初始化时创建一个托盘的按钮和图标,并且createMenu方法中创建了三个右键的功能菜单。

4. 右上角关闭按钮的提示功能和最小化到托盘中的功能。需要重写下closeEvent方法,所以这里创建一个新类。

class Dialog(QtWidgets.QMainWindow):
    def __init__(self,MainWindow,parent=None):
        super(Dialog, self).__init__(parent)
    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question, self.tr("提示"), self.tr("汝妻子我养之,汝勿虑之。\n 汝特么确定要退出吗?"), QtWidgets.QMessageBox.NoButton, self)
        yr_btn = reply.addButton(self.tr("是的我要退出"), QtWidgets.QMessageBox.YesRole)
        reply.addButton(self.tr("最小化到托盘"), QtWidgets.QMessageBox.NoRole)
        reply.exec_()
        if reply.clickedButton() == yr_btn:
            event.accept()
            QtWidgets.qApp.quit()
            # sys.exit(app.exec_())
        else:
            event.ignore()
            # 最小化到托盘
            MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            MainWindow.showMinimized()

        # 默认直接调用QMessageBox.question 弹出询问的方法
        # reply = QtWidgets.QMessageBox.question(self,
        #                                        '本程序',
        #                                        "是否要退出程序?",
        #                                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
        # if reply == QtWidgets.QMessageBox.Yes:
        #     event.accept()
        # elif reply == QtWidgets.QMessageBox.No:
        #     event.ignore()
        #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
        #     MainWindow.showMinimized()
        # else:
        #     # 最小化到托盘
        #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
        #     MainWindow.showMinimized()

类中有两种办法显示这个提示功能,第二种方法被注释了。

详见:

这个类完成了两个功能,一个是将关闭按钮加入了提示功能,一个是在提示信息中加入最小化到托盘的功能。

5. 写一个main。

if __name__ == '__main__':
    # 创建一个应用对象
    app = QtWidgets.QApplication(sys.argv)
    # 创建QT主窗口对象
    MainWindow = QtWidgets.QMainWindow()
    # 创建UI对象
    ui = Ui_untitled.Ui_MainWindow()
    MainWindow = Dialog(MainWindow)
    # 调用setupUi方法,将设计好的界面-->主窗口上
    ui.setupUi(MainWindow)

    MainWindow.setWindowFlags(QtCore.Qt.Window)
    # MainWindow.setWindowFlags(QtCore.Qt.WindowTitleHint)
    
    ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
    # min_tray(ui)
    # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
    MainWindow.show()

    ti = TrayIcon(MainWindow)
    ti.show()
    
    # 结束程序
    sys.exit(app.exec_())

这个main函数需要一步一步解释了,大部分的解释我都写成了注释在代码中,不过还是有几行要解释下。

MainWindow = QtWidgets.QMainWindow()
MainWindow = Dialog(MainWindow)

之所以MainWindow会在创建对象时又作为参数传入,是因为想要这个最小化到托盘的功能,所以首先用QtWidgets.QMainWindow()创建一个主窗口对象,将这个对象作为参数再传入到我们重写方法(提示信息和最小化到托盘功能)的类中,这个类又是继承QtWidgets.QMainWindow()这个类的,所以最终的MainWindow对象是重写了方法的QtWidgets.QMainWindow()类对象。

我不擅长面向对象,一般都是写面向过程解决,这个方法有点笨,大家应该有更好的办法解决。

 

所以整个代码就是这个样子的

首先是demo.py文件

#coding = 'utf-8'
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import Ui_untitled
import time

# 函数功能:在textBrowser中添加hello world字段
# 输入参数:ui对象
# 输出参数:
def buttonClicked(girl):
    girl.textBrowser.append("hello world")

class TrayIcon(QtWidgets.QSystemTrayIcon):
    def __init__(self,MainWindow,parent=None):
        super(TrayIcon, self).__init__(parent)
        self.ui = MainWindow
        self.createMenu()
    
    def createMenu(self):
        self.menu = QtWidgets.QMenu()
        self.showAction1 = QtWidgets.QAction("启动", self, triggered=self.show_window)
        self.showAction2 = QtWidgets.QAction("显示通知", self,triggered=self.showMsg)
        self.quitAction = QtWidgets.QAction("退出", self, triggered=self.quit)

        self.menu.addAction(self.showAction1)
        self.menu.addAction(self.showAction2)
        self.menu.addAction(self.quitAction)
        self.setContextMenu(self.menu)

        #设置图标
        self.setIcon(QtGui.QIcon("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"))
        self.icon = self.MessageIcon()

        #把鼠标点击图标的信号和槽连接
        self.activated.connect(self.onIconClicked)

    def showMsg(self):
        self.showMessage("Message", "skr at here", self.icon)

    def show_window(self):
        #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
        self.ui.showNormal()
        self.ui.activateWindow()
        
 
    def quit(self):
        QtWidgets.qApp.quit()

    #鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击
    def onIconClicked(self, reason):
        if reason == 2 or reason == 3:
            # self.showMessage("Message", "skr at here", self.icon)
            if self.ui.isMinimized() or not self.ui.isVisible():
                #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
                self.ui.showNormal()
                self.ui.activateWindow()
                self.ui.setWindowFlags(QtCore.Qt.Window)
                self.ui.show()
            else:
                #若不是最小化,则最小化
                self.ui.showMinimized()
                self.ui.setWindowFlags(QtCore.Qt.SplashScreen)
                self.ui.show()
                # self.ui.show()

class Dialog(QtWidgets.QMainWindow):
    def __init__(self,MainWindow,parent=None):
        super(Dialog, self).__init__(parent)
    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question, self.tr("提示"), self.tr("汝妻子我养之,汝勿虑之。\n 汝特么确定要退出吗?"), QtWidgets.QMessageBox.NoButton, self)
        yr_btn = reply.addButton(self.tr("是的我要退出"), QtWidgets.QMessageBox.YesRole)
        reply.addButton(self.tr("最小化到托盘"), QtWidgets.QMessageBox.NoRole)
        reply.exec_()
        if reply.clickedButton() == yr_btn:
            event.accept()
            QtWidgets.qApp.quit()
            # sys.exit(app.exec_())
        else:
            event.ignore()
            # 最小化到托盘
            MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            MainWindow.showMinimized()

        # 默认直接调用QMessageBox.question 弹出询问的方法
        # reply = QtWidgets.QMessageBox.question(self,
        #                                        '本程序',
        #                                        "是否要退出程序?",
        #                                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
        # if reply == QtWidgets.QMessageBox.Yes:
        #     event.accept()
        # elif reply == QtWidgets.QMessageBox.No:
        #     event.ignore()
        #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
        #     MainWindow.showMinimized()
        # else:
        #     # 最小化到托盘
        #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
        #     MainWindow.showMinimized()
            
            



if __name__ == '__main__':
    # 创建一个应用对象
    app = QtWidgets.QApplication(sys.argv)
    # 创建QT主窗口对象
    MainWindow = QtWidgets.QMainWindow()
    # 创建UI对象
    ui = Ui_untitled.Ui_MainWindow()
    MainWindow = Dialog(MainWindow)
    # 调用setupUi方法,将设计好的界面-->主窗口上
    ui.setupUi(MainWindow)

    MainWindow.setWindowFlags(QtCore.Qt.Window)
    # MainWindow.setWindowFlags(QtCore.Qt.WindowTitleHint)
    
    ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
    # min_tray(ui)
    # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
    MainWindow.show()

    ti = TrayIcon(MainWindow)
    ti.show()
    
    # 结束程序
    sys.exit(app.exec_())

然后是这个自动生成的ui的py文件

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'c:\My_World\gitee_code\qt_toolkit\hello_world\untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect(160, 110, 256, 192))
        self.textBrowser.setObjectName("textBrowser")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(570, 190, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

运行这个demo.py文件,就可以完成之前设计的功能。