近期从python2.7转到python3.6,之前一直采用的tkinter也有了更为强大的替代者——Pyqt5,初涉Pyqt5,采坑总是避免不了的,于是乎便记录下来。。。
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通过Pyinstaller -w打包为exe后,弹窗报错,无法打开
再次通过Pyinstaller -c打包为exe后,查看报错信息如下:
这是由于导入时出现问题,只需在导入时加入以下代码即可:
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后,可即可正常打开。
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)
未完待续…