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


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

    安装PyQt6:

    pip install pyqt6
    
    • 1

    使用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
    
    • 1

    Working directory:

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

    pyuic:
    Program:

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

    Arguments:

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

    Working directory:

    $FileDir$
    
    • 1

    配置好以后,在配置好的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())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

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

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

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

    选择文件夹:

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

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

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

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

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

        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'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注意这种多线程的方法,需要把耗时的任务写在界面类外,如果写在界面类里作为成员方法,即使使用了多线程还是会卡死,因为这么做还是占用了主界面的那个线程。通过在类里的方法,把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())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

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

  • 相关阅读:
    Mendix 开发实践指南|Mendix的核心概念
    Python字符串匹配神器TheFuzz库的实战详解
    【牛客】WY49数对,JZ65不用加减乘除做加法
    Ansible 自动化运维企业实战(一)
    梓航DIY无限建站-3.5.8(企业官网 应用首页 PC建站 14套模板切换,自由组合页面,无限多开)
    Read Uncommitted
    #795 Div.2 E. Number of Groups set *
    vue项目打包优化
    【Java】Java加密API
    基于android的购物APP系统设计与实现
  • 原文地址:https://blog.csdn.net/qq_43199509/article/details/128198947