python PyQt6 常用操作以及常见问题解决

news2024/12/23 10:18:55

因为需求需要写一个简单的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 Thread
            infor_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 saveInfor


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'


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 Thread
            infor_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.translate
        Form.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 sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_Form()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec())

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计旅游网的设计与实现Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

『Python学习笔记』使用Cython编程语言编译python文件

使用Cython编程语言编译python文件 文章目录一. Cython简介一. Cython编译2.1. 编译过程2.2. 环境安装2.3. disutils库2.4. 引入C源文件三. 总结参考文献一. Cython简介 Cython官网地址:https://cython.org/Cython的下载和安装:https://pypi.org/projec…

嵌入式分享合集117

一、获取STM32代码运行时间的技巧 测试代码的运行时间的两种方法: 使用单片机内部定时器,在待测程序段的开始启动定时器,在待测程序段的结尾关闭定时器。为了测量的准确性,要进行多次测量,并进行平均取值。 借助示波器…

NFV概述

NFV(网络功能虚拟化)是指利用虚拟化技术在标准化的通用IT设备(X86服务器,存储和交换设备)上实现各种网络功能。NFV的目标是取代通信网络中私有、专用和封闭的网元,实现统一通用硬件平台业务逻辑软件的开放架…

争议不断的AI绘画,靠什么成为了顶流?

今年以来,AIGC迅速崛起。所谓AIGC,即AI-Generated Content,指的是利用人工智能来生成内容,被认为是继专业产出内容(PGC)、用户产出内容(UGC)后的新型内容创作方式。不久前掀起热议的…

客户需求太多,如何有效沟通完成项目?

1、向客户明确:工作量、时间与质量的关系 需要想客户明确,某时间内在保障开发质量的前提下,实际的工作量。如果加大工作量,在赶工情况下,开发质量无法保障。如要保障开发质量,开发时间会延长,那…

【电力系统】基于Matlab实现风电光伏概率潮流计算

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

threejs官方demo学习(1):animation

前言 之前的threejs入门视频教学已经学习完了,下面会陆续学习官方demo。官方网址太卡了建议在本地进行搭建,具体见:threejs视频教程学习(1):本地搭建threeJS官网、渲染第一个场景 官方的例子都是html格式…

Qt源码编译aarch等架构可参考

前言: 我的建议是: 编译环境一定要有网络,依赖的包才可以方便安装!!! 一、准备工作 有网但ping不通、或者没有源的 可能需要先配置: 源路径: /etc/apt/source.list 系统默认DNS配置: /etc/r…

iTOP3588开发板编译Android内核方法一

iTOP3588开发板编译Android内核方法一: 在 Android 源码目录下执行如下命令编译 Android 内核: ./build.sh -CKA 编译完成后如下图所示: 编译后会在 rockdev/Image-rk3588_s 目录下生成 boot.img,boot.img 为内核镜像。boot.i…

《操作系统实战 45 讲》系统环境搭建 (Ubuntu + Vmware)

系统环境搭建 1. Ubuntu下载2. Vmware安装 Ubuntu系统2.1 配置电脑2.2 安装系统(Ubuntu16.04)3、配置网络和修改yum源3.1. 编辑 VMware 的网络配置3.2 windows 的网络配置3 .3 虚拟机网络 IP 修改地址配置3.4 修改yum源3.5 安装vm-tools1. Ubuntu下载 清…

【泊车】基于强化学习实现智能泊车附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

仿照string类,实现自定义My_strng类,以及相关操作

代码 #include <iostream> #include <cstring>using namespace std;class My_string { private:char* cstr;int len; public:My_string():cstr(NULL),len(0) //无参构造{}My_string(const char* str) //有参构造{this->len strlen(s…

【C++笔试强训】第二天

选择题 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A %-30.4e B %4.30e C %-30.4f D %-4.30f 对于 %m.nf &#xff0c;double对应%f.要求打印…

爬虫之Scrapy架构

目录 Scrapy架构介绍 Scrapy下载 Scrapy基本使用 Scrapy目录结构 Scrapy解析数据 settings相关配置 基础配置 增加爬虫的爬取效率 去重规则&#xff08;布隆过滤器&#xff09; 持久化方案(数据保存) request和response传递参数 网页解析下一页继续爬取 爬虫和下载…

Java安全之深入了解SQL注入

深入了解Java中的SQL注入 本文以代码实例复现了Java中JDBC及Mybatis框架采用预编译和非预编译时可能存在SQL注入的几种情况&#xff0c;并给予修复建议。 JDBC 首先看第一段代码&#xff0c;使用了远古时期的JDBC并且并没有使用预编译。这种简单的字符串拼接就存在SQL注入 …

信息化带来的制造业生产管理系统究竟有哪些作用呢?

制造业是一个现代国家的经济基础&#xff0c;决定着着国家的兴衰存亡。长期以来人们和国家都对制造业给予高度重视&#xff0c;无论是资金投入还是管理的手段和方法的提高&#xff0c;制造业在生产行业中的优势越来越明显。尤其是随着科学技术的快速发展&#xff0c;制造业的现…

uniapp easycom

easycom 是 uniapp 的一种组件自动引入的规则&#xff0c;使用这种规则可以使满足规则的组件无需注册直接使用。 接下来我们来看一眼效果 这里可以看到我并没有进行组件注册而是直接使用了组件&#xff0c;这样的效果就是通过 easycom 的自定义规则来实现的。 来看一眼我的自…

庐山真面目之——LWIP初探

目录 LWIP简介 网络层协议分层模型介绍 LWIP源代码结构 lwip源码文件说明 lwip的contrib包文件说明 以太网接入MCU方案 LWIP结构框图 LWIP简介 lwIP 是 Light Weight&#xff08;轻型&#xff09;IP 协议&#xff0c;有无操作系统的支持都可以运行。lwIP 实现的重点 是在保…

Android Studio compose的简单使用与案例实现

Compose是Android团队与JetBrain大力推动的新一代UI框架&#xff0c;它能够简化安卓界面的开发&#xff0c;让本来繁琐的xml文件写法变为简便的kt文件写法。 其声明式 UI、更简单的自定义、实时且带交互的预览功能更是让安卓开发锦上添花 android compose框架的使用一.前置知识…