python PyQt6 常用操作以及常见问题解决
创始人
2024-03-21 22:40:13
0

因为需求需要写一个简单的Python GUI界面,期间遇到了一些问题,在这里记录下

安装PyQt6:

pip install pyqt6

使用QTDesigner绘制界面:
我使用Anaconda下载的pyqt6里已经自带了两种工具,下面只需要把工具导入到pycharm中,在settings-External Tools中导入QTDesinger和pyuic两个工具:
在这里插入图片描述

其中的参数配置我是这样的,A是我的用户名:
在这里插入图片描述
QTDesinger
Program:

C:\Users\A\.conda\envs\python37\Lib\site-packages\qt6_applications\Qt\bin\designer.exe

Working directory:

C:\Users\A\.conda\envs\python37\Lib\site-packages\qt6_applications\Qt\bin

pyuic:
Program:

C:\Users\A\.conda\envs\python37\python.exe

Arguments:

-m PyQt6.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py

Working directory:

$FileDir$

配置好以后,在配置好的tools里就可以找到刚刚配置的工具
在这里插入图片描述
在里面拖动好边框以及按钮后,保存会生成ui文件。在ui文件上右键选择工具pyuic,即可在对应的文件夹下生产对应的py文件
在这里插入图片描述
在生成的界面下添加调用的代码来生成显示

from PyQt6 import QtCore, QtWidgets
import sys
if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)MainWindow = QtWidgets.QMainWindow()ui = Ui_Form()#这个是生成的界面窗口类名ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec())

把按钮和函数链接起来,实现点击按钮触发对应函数self.inforFileSelect:

self.pushButton.clicked.connect(self.inforFileSelect)

实现选择文件的功能,并把选择的文件名写到界面上:

def inforFileSelect(self):# 选择文件result = QtWidgets.QFileDialog.getOpenFileName()self.lineEdit.setText(result[0])

选择文件夹:

def saveDirSelect(self):# 选择保存文件夹result = QtWidgets.QFileDialog.getExistingDirectory()self.lineEdit_3.setText(result)

在写好界面运行后我发现存在两个问题,一个是发现变更标签上的文字不会实时更新,另一个是发现界面常常出现无响应的情况。

解决方法:
用 QtWidgets.QApplication.processEvents()实时刷新变更的文字:

def changeLabel(self, text="hi"):self.label.setText(text)QtWidgets.QApplication.processEvents()

通过多线程的方法来解决界面无响应的情况:

    def processFiles_clicked(self):if self.running_status == 'stop':self.running_status = 'running'from threading import Threadinfor_xml = self.lineEdit.text()scheme_xml = self.lineEdit_2.text()save_dir = self.lineEdit_3.text()thread = Thread(target=process_file, args=(infor_xml, scheme_xml, save_dir, self))thread.start()else:self.changeLabel("正在生成中,别急!")def process_file(infor_xml, scheme_xml, save_dir, Ui_Form):try:Ui_Form.changeLabel("正在读取用户表,请稍后")infor_dict = getUserInfor(infor_xml)Ui_Form.changeLabel("正在读取排班表,请稍后")infor_dict, data_loc, name_list = getSchemeInfor(infor_dict, scheme_xml)for each_date in data_loc:current_date = str(each_date.month) + "." + str(each_date.day)Ui_Form.changeLabel("正在生成" + current_date + "的排表文件")saveInfor(each_date, infor_dict, save_dir, name_list)Ui_Form.changeLabel("生成完成!")Ui_Form.running_status = 'stop'except Exception as e:Ui_Form.changeLabel("出错了,这是报错信息:" + str(e))Ui_Form.running_status = 'stop'

注意这种多线程的方法,需要把耗时的任务写在界面类外,如果写在界面类里作为成员方法,即使使用了多线程还是会卡死,因为这么做还是占用了主界面的那个线程。通过在类里的方法,把self传给外面的函数,让外面的函数可以通过self直接调用对象的方法,来达到更改标签和参数传递的效果。
其实如果用多进程也可以解决卡死的问题,但是多进程的话,不能再把实例self传给外面函数了,这么做的话在启动多进程的时候会复制一遍内容导致不断套娃耗尽资源,因此多进程需要通过其他方式来解决信息传递的问题。
最后附上完成的代码:

from PyQt6 import QtCore, QtWidgets
from SchemeLoader import getSchemeInfor
from UserLoader import getUserInfor
from InforSaver import saveInfordef process_file(infor_xml, scheme_xml, save_dir, Ui_Form):try:Ui_Form.changeLabel("正在读取用户表,请稍后")infor_dict = getUserInfor(infor_xml)Ui_Form.changeLabel("正在读取排班表,请稍后")infor_dict, data_loc, name_list = getSchemeInfor(infor_dict, scheme_xml)for each_date in data_loc:current_date = str(each_date.month) + "." + str(each_date.day)Ui_Form.changeLabel("正在生成" + current_date + "的排表文件")saveInfor(each_date, infor_dict, save_dir, name_list)Ui_Form.changeLabel("生成完成!")Ui_Form.running_status = 'stop'except Exception as e:Ui_Form.changeLabel("出错了,这是报错信息:" + str(e))Ui_Form.running_status = 'stop'class Ui_Form(object):# 设置一个变量监控运行状态running_status = "stop"def setupUi(self, Form):Form.setObjectName("Form")Form.resize(471, 704)self.pushButton = QtWidgets.QPushButton(Form)self.pushButton.setGeometry(QtCore.QRect(170, 100, 121, 41))self.pushButton.setObjectName("选择人员信息表")self.label = QtWidgets.QLabel(Form)self.label.setGeometry(QtCore.QRect(80, 550, 321, 81))self.label.setAutoFillBackground(True)self.label.setObjectName("label")self.lineEdit = QtWidgets.QLineEdit(Form)self.lineEdit.setGeometry(QtCore.QRect(70, 30, 341, 51))self.lineEdit.setObjectName("lineEdit")self.lineEdit_2 = QtWidgets.QLineEdit(Form)self.lineEdit_2.setGeometry(QtCore.QRect(70, 190, 341, 51))self.lineEdit_2.setObjectName("lineEdit_2")self.pushButton_4 = QtWidgets.QPushButton(Form)self.pushButton_4.setGeometry(QtCore.QRect(170, 480, 121, 41))self.pushButton_4.setObjectName("pushButton_4")self.lineEdit_3 = QtWidgets.QLineEdit(Form)self.lineEdit_3.setGeometry(QtCore.QRect(70, 340, 341, 51))self.lineEdit_3.setObjectName("lineEdit_3")self.pushButton_2 = QtWidgets.QPushButton(Form)self.pushButton_2.setGeometry(QtCore.QRect(170, 260, 121, 41))self.pushButton_2.setObjectName("pushButton_2")self.pushButton_3 = QtWidgets.QPushButton(Form)self.pushButton_3.setGeometry(QtCore.QRect(170, 410, 121, 41))self.pushButton_3.setObjectName("pushButton_3")self.retranslateUi(Form)QtCore.QMetaObject.connectSlotsByName(Form)def inforFileSelect(self):# 选择文件result = QtWidgets.QFileDialog.getOpenFileName()self.lineEdit.setText(result[0])def schemeFileSelect(self):# 选择文件result = QtWidgets.QFileDialog.getOpenFileName()self.lineEdit_2.setText(result[0])def saveDirSelect(self):# 选择保存文件夹result = QtWidgets.QFileDialog.getExistingDirectory()self.lineEdit_3.setText(result)def changeLabel(self, text="hi"):self.label.setText(text)QtWidgets.QApplication.processEvents()def processFiles_clicked(self):if self.running_status == 'stop':self.running_status = 'running'from threading import Threadinfor_xml = self.lineEdit.text()scheme_xml = self.lineEdit_2.text()save_dir = self.lineEdit_3.text()thread = Thread(target=process_file, args=(infor_xml, scheme_xml, save_dir, self))thread.start()else:self.changeLabel("正在生成中,别急!")def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "表格信息整合工具"))self.pushButton.setText(_translate("Form", "选择人员信息表"))self.pushButton.clicked.connect(self.inforFileSelect)self.label.setText(_translate("Form", ""))self.pushButton_2.setText(_translate("Form", "选择排班表"))self.pushButton_2.clicked.connect(self.schemeFileSelect)self.pushButton_3.setText(_translate("Form", "选择保存文件夹"))self.pushButton_3.clicked.connect(self.saveDirSelect)self.pushButton_4.setText(_translate("Form", "导出明细表"))self.pushButton_4.clicked.connect(self.processFiles_clicked)if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)MainWindow = QtWidgets.QMainWindow()ui = Ui_Form()ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec())

界面效果:
在这里插入图片描述

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...