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())

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

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...