pyqt5学习笔记

软硬件环境

python3 -v
  • pyqt5版本要和qt的版本相同不然使用pyuic5 时候会出错。

因为工作需要制作了一个根据模版音频文件夹整理另外一个有相同编号的杂乱音频文件夹的小工具。

一 界面设计

打开Qt Designer 选择 Main Window 顾名思义就是主窗口。

新建窗体

在窗体部件盒子选择我们需要的控件拖拽到主窗体,下图使用了Lable、lineEdit、pushButton,在qt中所有的控件都是加了Q前缀的。


设计的简易界面

为了便于编码我们可以在对象查看器里对控件进行重命名。

对象查看器

一个简易的界面设计好了,我们将它保存为ui.ui文件,这里要注意一下,Qt Designer设计出来的文件默认为ui文件,里面包含的类css布局设计语言,我们还需要将它转换为.py文件。
如果使用的PyCharm,可以在Tools->External Tools->Pyuic 转换,如下图:

pyuic

没有使用PyCharm的伙伴可以通过终端转换:

pyuic5 -o ui.py ui.ui

生成的代码如下

rom PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(504, 293)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(40, 40, 284, 123))
        self.widget.setObjectName("widget")
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setObjectName("gridLayout")
        self.label_model = QtWidgets.QLabel(self.widget)
        self.label_model.setObjectName("label_model")
        self.gridLayout.addWidget(self.label_model, 0, 0, 1, 1)
        self.lineEdit_model = QtWidgets.QLineEdit(self.widget)
        self.lineEdit_model.setObjectName("lineEdit_model")
        self.gridLayout.addWidget(self.lineEdit_model, 0, 1, 1, 1)
        self.pushButton_begin = QtWidgets.QPushButton(self.widget)
        self.pushButton_begin.setObjectName("pushButton_begin")
        self.gridLayout.addWidget(self.pushButton_begin, 0, 2, 1, 1)
        self.label_res = QtWidgets.QLabel(self.widget)
        self.label_res.setObjectName("label_res")
        self.gridLayout.addWidget(self.label_res, 1, 0, 1, 1)
        self.lineEdit_res = QtWidgets.QLineEdit(self.widget)
        self.lineEdit_res.setObjectName("lineEdit_res")
        self.gridLayout.addWidget(self.lineEdit_res, 1, 1, 1, 1)
        self.label_out = QtWidgets.QLabel(self.widget)
        self.label_out.setObjectName("label_out")
        self.gridLayout.addWidget(self.label_out, 2, 0, 1, 1)
        self.lineEdit_out = QtWidgets.QLineEdit(self.widget)
        self.lineEdit_out.setObjectName("lineEdit_out")
        self.gridLayout.addWidget(self.lineEdit_out, 2, 1, 1, 1)
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 3, 0, 1, 1)
        self.lineEdit_regex = QtWidgets.QLineEdit(self.widget)
        self.lineEdit_regex.setObjectName("lineEdit_regex")
        self.gridLayout.addWidget(self.lineEdit_regex, 3, 1, 1, 1)
        self.label_model.raise_()
        self.pushButton_begin.raise_()
        self.lineEdit_model.raise_()
        self.label_res.raise_()
        self.lineEdit_res.raise_()
        self.label_out.raise_()
        self.lineEdit_out.raise_()
        self.lineEdit_regex.raise_()
        self.label.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 504, 22))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menubar)
        self.menubar.addAction(self.menu.menuAction())

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_model.setText(_translate("MainWindow", "模版路径:"))
        self.pushButton_begin.setText(_translate("MainWindow", "开始"))
        self.label_res.setText(_translate("MainWindow", "资源路径:"))
        self.label_out.setText(_translate("MainWindow", "输出路径:"))
        self.label.setText(_translate("MainWindow", "正则表达式:"))
        self.menu.setTitle(_translate("MainWindow", "菜单"))

为了代码与界面分离,我们可以新建一个文件qui.py导入ui.py:

from  ui import Ui_MainWindow
from PyQt5.QtWidgets import QApplication , QMainWindow

class Mainwindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(Mainwindow, self).__init__()
        self.setupUi(self)

二 业务逻辑

核心业务重要是对文件夹下的所有文件进行遍历:

    # 获取指定路径下所有指定后缀的文件
    # dir 指定路径
    # ext 指定后缀,链表&不需要带点 或者不指定。例子:['xml', 'java']
    def GetFileFromThisRootDir(self, dir, ext = None):
        allfiles = []
        needExtFilter = (ext != None)
        for root,dirs,files in os.walk(dir):
            for filespath in files:
                filepath = os.path.join(root, filespath)
                extension = os.path.splitext(filepath)[1][1:]
                if needExtFilter and extension == ext in ext:
                    allfiles.append(filepath)
        return allfiles

shutil模块提供了复制文件的方法,re 模块提供了正则表达式功能,我们需要导入,完整工具类代码如下:

import os
import re
import shutil

class Ltool(object):
    def __init__(self):
        pass
    # 获取指定路径下所有指定后缀的文件
    # dir 指定路径
    # ext 指定后缀,链表&不需要带点 或者不指定。例子:['xml', 'java']
    def GetFileFromThisRootDir(self, dir, ext = None):
        allfiles = []
        needExtFilter = (ext != None)
        for root,dirs,files in os.walk(dir):
            for filespath in files:
                filepath = os.path.join(root, filespath)
                extension = os.path.splitext(filepath)[1][1:]
                if needExtFilter and extension == ext in ext:
                    allfiles.append(filepath)
        return allfiles

    # 获取指定路径下所有的文件夹
    # dir 指定路径
    def GetDirFromThisRootDir(self, dir):
        alldirs = []
        for root,dirs,files in os.walk(dir):
            alldirs.append(root)
        return alldirs

    # 复制目录
    # dstDir 目标路径
    # srcDir 源路径
    def CopyDirBySrcDirPathToDstDir(self, dstDir, srcDir):
        allDirs = self.GetDirFromThisRootDir(srcDir)
        for d in allDirs:
            newdir = d.replace(srcDir, dstDir)
            if os.path.exists(newdir):
                pass
            else:
                os.mkdir(newdir)
    # 复制文件到目标位置
    def CopyFilesByModelDir(self, modelDir, dstDir, srcDir, regex = r'([0-9]{5})', ext = 'mp3'):
        errorFiles = []
        allFiles = self.GetFileFromThisRootDir(srcDir, ext)
        modelFiles = self.GetFileFromThisRootDir(modelDir, ext)
        self.CopyDirBySrcDirPathToDstDir(dstDir, modelDir)

        #复制符合规则的文件
        for f in allFiles:
            m = re.findall(regex,f)
            if len(m) == 1:
                for demofile in modelFiles:
                    z = re.findall(regex, demofile)
                    if m == z:
                        newfile = demofile.replace(modelDir, dstDir)
                        shutil.copy(f, newfile)
            else:
                errorFiles.append(f)

        for f in errorFiles:
            logging.debug("errorfile", f)

现在可以回过头完善下qui.py:

from  ui import Ui_MainWindow
from PyQt5.QtWidgets import QApplication , QMainWindow
from Ltool import Ltool

class Mainwindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(Mainwindow, self).__init__()
        self.setupUi(self)
        self.ltool = Ltool()
        self.pushButton_begin.clicked.connect(self.beginCopyfun)
    def beginCopyfun(self):
        modelDir = self.lineEdit_model.text()
        dstDir = self.lineEdit_out.text()
        srcDir = self.lineEdit_res.text()
        regex = self.lineEdit_regex.text()
        self.ltool.CopyFilesByModelDir(modelDir, dstDir, srcDir)

main.py

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

import sys
import common
import logging
from qui import *

def initLogConfiguration():
    '''
    初始化日志配置
    '''
    logging.basicConfig(level = logging.DEBUG,
                        filename = common.LOGFILE,
                        filemode = 'a+',
                        format = '%(asctime)s - %(filename)s - line %(lineno)-4d - %(levelname)s - %(message)s',
                        datefmt = '%m-%d %H:%M')

if __name__ == '__main__':
    '''
    主函数
    '''
    initLogConfiguration()
    app = QApplication(sys.argv)
    mainWindow = Mainwindow()
    mainWindow.show()
    sys.exit(app.exec_())

新人学习中,请见谅哈。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容