Python 之 Qt Designer工具安装配置及打包

工具相关安装配置

一、pyqt5、pyqt5-tool、paramiko、pyInstaller安装

直接在线安装:

pip3 install PyQt5

pip3 install PyQt5-tools

pip3 install paramiko

pip3 install pyinstaller

镜像安装:(比直接在线安装快)

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5-tools

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple paramiko

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller

配置环境变量:(正常情况安装后自动配置,无需手动配置)

控制面板 – 环境变量:

QT_QPA_PLATFORM_PLUGIN_PATH

C:\Python36\Lib\site-packages\PyQt5\Qt\plugins

二、pyqt5、pyqt5-tool、paramiko、pyInstaller安装

安装好pyqt5和pyqt5-tool后,还需要对pycharm进行配置,添加扩展工具(External Tools)
打开File(文件) – Settings(设置) – Tools (工具)– External Tools(外部工具)添加如下几个扩展工具:

1.QT Designed

用途:设计UI界面

name:QT Designed 

tool settings:

Program: C:\Python36\Lib\site-pcakages\pyqt5-tools\designer.exe

woreking directory :$FileDir$

2.PyUIC

用途:将qt designed设计的ui文件,转换成py文件

name:PyUIC

tool settings:

Program:C:\Python36\Scripts\pyuic5.exe

Arguments: $FileName$ -o $FileNameWithoutExtension$.py

working directory: $FileDir$

3.PyInstall

用途:打包py文件为exe可执行文件

name: PyInstall

tool settings:

Program:C:\Python36\Scripts\pyinstaller.exe

Arguments: -F -w  $FileNameWithoutExtension$.py

working directory:$FileDir$

4.Pyrcc

用途:将ico图片放在qrc文件中,再将qrc文件转换成py文件,用于小工具的图标
qrc文件格式大致如下:

<RCC>

    <qresource prefix="/">

        <file>python.ico</file>

        <file>1.jpg</file>

    </qresource>

</RCC>

name: pyrcc

tool setting:

program: C:\Python36\Scripts\pyrcc5.exe

Arguments: $FileName$ -o $FileNameWithoutExtension$.py

working directory: $FileDir$

配置完后,进入External Tools检查确认。

三、Qt Designer工具主界面

工具->External Tools->Qt Designer

利用Qt Designer封装控件

在PyCharm创建项目:文件-新建项目-创建

打开Qt Designer:工具->External Tools->Qt Designer

创建模板:选择Widget模板->创建

从Widget Box工具箱中拖拽2个TextLabel、1个line Edit、1个Text Browser以及2个Push Button。拖完后如下:

双击可以修改控件名称,也可以在属性编辑器中修改text;对象名称(objectname)同样需要修改,为了方便后续操作。

对象名称:

控件名称:

点击:窗体预览。字体大小、控件位置都可以调整。

保存文件,countImgs.ui,进入PyCharm,将.ui文件转换成.py文件。

方法一:右键External Tools–PyUIC或者tools–External Tools–PyUIC

方法二:直接使用命令行转换成.py文件。调用格式为pyuic5 -o {输出文件名} {输入designer设计好的.ui后缀界面文件}。

pyuic5 -o countImgs.py countImgs.ui

转换后的.py文件内容如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'countImgs.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(337, 421)
        self.label1 = QtWidgets.QLabel(Form)
        self.label1.setGeometry(QtCore.QRect(40, 30, 54, 12))
        self.label1.setObjectName("label1")
        self.label2 = QtWidgets.QLabel(Form)
        self.label2.setGeometry(QtCore.QRect(40, 90, 54, 12))
        self.label2.setObjectName("label2")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(40, 50, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.textBrowser = QtWidgets.QTextBrowser(Form)
        self.textBrowser.setGeometry(QtCore.QRect(40, 110, 256, 192))
        self.textBrowser.setObjectName("textBrowser")
        self.pushButton1 = QtWidgets.QPushButton(Form)
        self.pushButton1.setGeometry(QtCore.QRect(40, 340, 75, 23))
        self.pushButton1.setObjectName("pushButton1")
        self.pushButton2 = QtWidgets.QPushButton(Form)
        self.pushButton2.setGeometry(QtCore.QRect(220, 340, 75, 23))
        self.pushButton2.setObjectName("pushButton2")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "统计不重复标签"))
        self.label1.setText(_translate("Form", "路径:"))
        self.label2.setText(_translate("Form", "结果:"))
        self.pushButton1.setText(_translate("Form", "打印"))
        self.pushButton2.setText(_translate("Form", "退出"))

界面与业务逻辑

这一步主要实现业务逻辑,也就是点击“打印”和“退出”按钮后程序要执行的操作。为了后续维护方便,采用界面与业务逻辑相分离来实现。也就是通过创建主程序调用界面文件方式实现。这有2个好处。第1就是实现逻辑清晰。第2就是后续如果界面或者逻辑需要变更,好维护。新建countImgs_main.py文件程序,调用countImgs.py文件。

import sys
# PyQt5中使用的基本控件都在PyQt5.QtWidgets模块中
from PyQt5.QtWidgets import QApplication, QMainWindow
# 导入designer工具生成的login模块
from countImgs import Ui_Form

class MyMainForm(QMainWindow, Ui_Form):
    def __init__(self, parent=None):
        super(MyMainForm, self).__init__(parent)
        self.setupUi(self)

if __name__ == "__main__":
    # 固定的,PyQt5程序都需要QApplication对象。sys.argv是命令行参数列表,确保程序可以双击运行
    app = QApplication(sys.argv)
    # 初始化
    myWin = MyMainForm()
    # 将窗口控件显示在屏幕上
    myWin.show()
    # 程序运行,sys.exit方法确保程序完整退出。
    sys.exit(app.exec_())

运行结果:

到这里,界面实现和业务主程序已经写好了。但是现在具体业务功能逻辑还未实现。需要对登录和退出的按钮点击执行相对应的操作。

添加信号和槽,实现业务逻辑

实现部分见代码注释。这里主要添加如下两行命令配置信号和槽的关系。信号和槽的创建和原理下文描述。这里可以参照添加即可。

登录按钮:self.login_Button.clicked.connect(self.display)

退出按钮:self.cancel_Button.clicked.connect(self.close)

首先将功能函数.py文件放入utils文件夹下,并且文件中的函数必须是封装好的:

运行结果:测试结果不在控件中显示。

解决方法:Print重定向到组件。

运行展示:

相关完整代码:

countImg_main.py

import sys
# PyQt5中使用的基本控件都在PyQt5.QtWidgets模块中
from PyQt5.QtWidgets import QApplication, QMainWindow
# 导入designer工具生成的login模块
from countImgs import Ui_Form
from utils.ReoeatFrames import RepeatFrames
from PyQt5 import QtCore, QtGui
#第一段:print重定向到组件   重定向1
class EmittingStr(QtCore.QObject):
    textWritten = QtCore.pyqtSignal(str)  # 定义一个发送str的信号
    def write(self, text):
        self.textWritten.emit(str(text))

class MyMainForm(QMainWindow, Ui_Form):
    def __init__(self, parent=None):
        super(MyMainForm, self).__init__(parent)
        self.setupUi(self)
        # 第二段:print重定向到组件   重定向2
        sys.stdout = EmittingStr(textWritten=self.outputWritten)
        sys.stderr = EmittingStr(textWritten=self.outputWritten)
        # 添加登录按钮信号和槽。注意display函数不加小括号()
        self.pushButton1.clicked.connect(self.display)
        # 添加退出按钮信号和槽。调用close函数
        self.pushButton2.clicked.connect(self.close)
    # 第三段:print重定向到组件   重定向3  用到的控件textBrowser
    def outputWritten(self, text):
        cursor = self.textBrowser.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.textBrowser.setTextCursor(cursor)
        self.textBrowser.ensureCursorVisible()

    def display(self):
        # 初始化textBrowser
        self.textBrowser.clear()
        # 输入路径参数
        path1 = self.lineEdit.text()
        path2 = path1 + '/'
        #调用函数
        RepeatFrames(path2)


if __name__ == "__main__":
    # 固定的,PyQt5程序都需要QApplication对象。sys.argv是命令行参数列表,确保程序可以双击运行
    app = QApplication(sys.argv)
    # 初始化
    myWin = MyMainForm()
    # 将窗口控件显示在屏幕上
    myWin.show()
    # 程序运行,sys.exit方法确保程序完整退出。
    sys.exit(app.exec_())

RepeatFrames.py
import os
from unicodedata import name
import xml.etree.ElementTree as ET
import glob
import pandas as pd
import numpy as np

def RepeatFrames(indir):
    os.chdir(indir)
    annotations = os.listdir('.')
    annotations = glob.glob(str(annotations) + '*.xml')
    bndbox_xml = []  #存放重复节点
    for i, file in enumerate(annotations):
        in_file = open(file, encoding='utf-8')
        tree = ET.parse(in_file)
        root = tree.getroot()
        listobj = []
        for obj in root.iter('object'):
            name = obj.find('name').text
            listname1 = {}
            for bndbox in obj.iter('bndbox'):
                listname1['name'] = name
                for xmin in bndbox.iter('xmin'):
                    xmin=xmin.text
                    listname1['xmin'] = xmin
                for ymin in bndbox.iter('ymin'):
                    ymin = ymin.text
                    listname1['ymin'] = ymin
                for xmax in bndbox.iter('xmax'):
                    xmax = xmax.text
                    listname1['xmax'] = xmax
                for ymax in bndbox.iter('ymax'):
                    ymax = ymax.text
                    listname1['ymax'] = ymax
                listobj.append(listname1)
        n = len(listobj)
        for i in range(n):
            for j in range(i + 1, n):
                if listobj[i] == listobj[j]:
                    listobj[j]['name'] = '重复标签(不统计)'
                    listobj[i]['name'] = '重复标签(不统计)'
            name_cf = listobj[i]['name']
            bndbox_xml.append(name_cf)
    count_dict = {}
    for num in bndbox_xml:
        if num in count_dict:
            count_dict[num] += 1
        else:
            count_dict[num] = 1
    key1 = 0
    print("统计*不重复*标签数量:")
    for key in count_dict.keys():
        key1 = count_dict[key] + key1
        print(key + ':' + str(count_dict[key])+'个 ', '\n')
    print("标签总数量:", key1, '个 ')
    #判断是否有重复标签
    element = '重复标签(不统计)'
    if element in bndbox_xml:
        print("有效标签数:", key1 - count_dict['重复标签(不统计)'], '个 ')
    else:
        print("有效标签数:", key1 - 0, '个 ')

    print("标签种类数:", len(count_dict)-1, '个 ')



其他说明:控件自适应。后续完善。

作者:qq_34157747

物联沃分享整理
物联沃-IOTWORD物联网 » Python 之 Qt Designer工具安装配置及打包

发表回复