Pyqt5编程踩坑日记

Pyqt5编程踩坑日记

近期从python2.7转到python3.6,之前一直采用的tkinter也有了更为强大的替代者——Pyqt5,初涉Pyqt5,采坑总是避免不了的,于是乎便记录下来。。。

一、Pyqt5下使用subprocess模块后打包exe的问题

Pyqt5下对subprocess模块进行了使用,在Pycharm上可以正常运行并调试,但是,一旦用Pyinstaller -w打包为exe后,程序边运行不了了,而经过Pyinstaller -c打包的exe便可以正常运行,这时我们在调用subprocess模块时就需要将控制台窗口隐藏,代码如下:

    hide = subprocess.STARTUPINFO()
    hide.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    res = subprocess.check_output(command, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
                                          universal_newlines=True, startupinfo=hide)

通过这样的方式就可以用Pyinstaller -w打包为exe啦~

然鹅~。。在多线程高并发的时候,以上处理遇到个致命的问题,直接卡死了Windows操作系统(低并发的时候未出现),至于原因至今尚未找到。。。。于是又找到了下面这种解决方案(参考链接),代码如下:

    DETACHED_PROCESS = 0x00000008
    command = f"ping -n 3 -w 10 {ip}"
    res = subprocess.check_output(command, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
                                          universal_newlines=True, creationflags=DETACHED_PROCESS)

二、Pyqt5下打包exe成功后打开exe报错的问题

Pyqt5通过Pyinstaller -w打包为exe后,弹窗报错,无法打开
Pyqt5编程踩坑日记_第1张图片
再次通过Pyinstaller -c打包为exe后,查看报错信息如下:
Pyqt5编程踩坑日记_第2张图片
这是由于导入时出现问题,只需在导入时加入以下代码即可:

import sys
import os

if hasattr(sys, 'frozen'):
    os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMessageBox

再次用Pyinstaller -w打包为exe后,可即可正常打开。

三、多界面时,子界面闪退

  1. 在子界面加入:
dialog.exec()

子界面调用如下:

    # 菜单栏上触发弹出窗口界面
    self.action_menu_setting.triggered.connect(self.show_dialog)
    
    def show_dialog(self):
        setting_dialog = SettingDialog()
        setting_dialog.show()
        setting_dialog.exec()

但是,这样的话多次通过菜单栏上触发弹出窗口界面,则会生成多个弹出窗口。若是要始终只有一个弹出窗口,则只需要把 dialog 临时变量,改为实例化变量即可:

    # 菜单栏上触发弹出窗口界面
    self.action_menu_setting.triggered.connect(self.show_dialog)
    
    def show_dialog(self):
        self.setting_dialog = SettingDialog()
        self.setting_dialog.show()

若是要做成模态框,则如下改动即可:

    # 菜单栏上触发弹出窗口界面
    self.action_menu_setting.triggered.connect(self.show_dialog)
    
    def show_dialog(self):
        self.setting_dialog = SettingDialog()
        self.setting_dialog.exec()

四、解决鼠标悬停菜单栏后状态栏信息清空问题

在利用状态栏(showMessage())展示文本信息时,有这样一个问题:当鼠标悬停划过菜单栏时,状态栏的文本信息会被清空。
可以尝试通过重写父类event函数解决:

class Main:
    # ...
    # 其他代码逻辑...

    def set_status_message (self, status_message):
        self.statusbar = QtWidgets.QStatusBar(self.main_window) # self.main_window为主窗口
        self.status_message = status_message
        self.statusbar.showMessage(self.status_message)

    # 此覆盖父类函数: 覆盖方法; 为了克服 将鼠标放置于菜单栏上 状态栏信息就消失的问题;
    def event(self, QEvent):
        if QEvent.type() == QEvent.StatusTip:
            if QEvent.tip() == "":
                QEvent = QStatusTipEvent(self.status_message)  # 此处为要始终显示的内容
        return super().event(QEvent)
        

未完待续…

你可能感兴趣的:(Python)