pyqt5入门练习-扫描条形码(一)

问题

使用pyqt5, Qt Designer, PyUIC, pycharm, ZBar练习python GUI开发, 扫描条形码案例
最近学习做python GUI开发, 为了完成老师布置的任务, 做一个配合ZBar扫描条形码的小程序, 不打算过多深究二维码什么的
我能找到的教程就是http://code.py40.com/pyqt5/这个网站, 但是这个教材没有使用qt designer, 前期给了我很大的困惑
先上一张图, 看看效果


图1 成品

简单得不能再简单了, 但第一次写有点磕磕绊绊的

  • 工具:pycharm + qt Designer + pyUIC + ZBar
  • qt Designer的主要功能就是把图形界面做出来
  • pyUIC的主要功能就是把图形界面翻译成.py文件
  • ZBar的功能是扫描图片上的条形码

主要实现的功能有: 用外部程序ZBar扫描图片、用xlwt库导出数据到excel, pyinstaller打包python文件, 其它的就是pyqt5的一些操作比如选择文件、换ico图标之类的

工具的安装

安装pyqt5 pip install pyqt5
安装pyqt5-tools pip install pyqt5-tools
完成了之后qt designer就安装在你的python根目录下的\Lib\site-packages\pyqt5_tools\Qt\bin\下
配置pycharm File->settings->Tools->External Tools->+


配置qt designer


图2 配置qt designer

配置pyUIC


图3 配置pyUIC

参数:-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py


工具的位置:


图4 工具的位置

安装ZBar
https://sourceforge.net/projects/zbar/files/zbar/0.10/zbar-0.10-setup.exe/download
安装到你项目的目录中, 进入ZBar/bin/目录, 在此处打开控制台, 准备一张条形码图片(ZBar/example目录中有一张条形码)
执行命令zbarimg.exe ../examples/barcode.png


图5 执行命令

扫描出来就证明成功了, bin/下的另一个zbarcam.exe是用来扫视频中的条形码的

运行第一个Helloworld

pycharm new一个python项目出来
Tools->External Tools->Qt Designer
创建一个Main Window模板(我第一次创建了个对话框, 怎么也运行不了, 血的代价)
左边工具栏Display Widgets拖一个Label到窗口中间, 安静地敲下Helloworld


图6

右击HelloWorld->change styleSheet


图7

这是你熟悉的css, 我们看到字有点超出边界了, 这里有个小技巧
右击Helloword->Layout->Adjust Size
这时候Helloworld饱满了
Ctrl+S保存到项目文件夹
左键选中helloworld.ui(一定要选中) 寻找工具pyUIC 点击 自动生成了helloworld.py文件
在项目目录中新建main.py文件作为主入口, 与图形界面的代码分离(试过就知道很方便), 并敲下如下代码:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
import helloworld

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = QMainWindow()
    ui = helloworld.Ui_MainWindow()
    ui.setupUi(mw)
    mw.show()
    # 逻辑代码
    
    sys.exit(app.exec_())

运行main.py


图8

界面制作

Tools->External Tools->Qt Desginer
创建一个Main Window 先把界面摆好
Buttons->Push Button拖出两个按钮
Item Widgets->Table Widget拖出两个表格框
Display Widgets->Label拖出标签


图9

文件数:0是两个不同标签
接下来开始为每个组件命名, 要做到见名知意
选中导入按钮命名为importBtn


图10

依次地


图10

保存到项目目录为barcode.ui->左键点击选中->Tools->External Tools->pyUIC
得到barcode.py 图形界面的代码

触发按钮

首先在main.py文件中进口barcode.py模块, 更改barcode模块生成ui对象
有两个对象ui对象和MainWindow对象
通过ui对象可以管理按钮、标签等组件, 通过MainWindow可以进行关闭窗口等操作
通过点击按钮 触发事件
先写最简单的退出按钮

# main.py
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
import barcode

def exitEvent(mw):
    mw.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = QMainWindow()
    ui = barcode.Ui_MainWindow()
    ui.setupUi(mw)
    mw.show()
    # 逻辑代码
    ui.exitBtn.clicked.connect(lambda: exitEvent(mw))
    sys.exit(app.exec_())

ui.exitBtn.clicked.connect(lambda: exitEvent(mw))这里使用lambda表达式主要是为了解决传参问题,还有一种partial传参方式没lambda好用。把mw主窗口对象传递到exitEvent()函数中, 对mw对象进行操作, 实现操作的模块化, 比如加个退出的确认框呀什么的
运行main.py 点击退出按钮 退出界面

选择文件

打开barcode.ui 双击第一个表格框 写出各个字段




图组11

然后点击保存, 直接用pyUIC转换成barcode.py文件, 这就是分离的好处, 只管界面, 不管逻辑。
我们可以通过观察barcode.py学习这个表格是怎么注入数据的, 如这一段

# def setupUi()
item = QtWidgets.QTableWidgetItem()
self.fileList.setItem(0, 0, item)
# 在(0,0)位置处生成一个单元格
# def retranslateUi()
item = self.fileList.item(0, 0)
item.setText(_translate("MainWindow", "1"))
# 在(0,0)处注入1这个字符

可以看到setupUi()方法专注于创建, 而retranslateUi()方法专注于注入数据, 就像盖楼一样, 我们先把框架搭好, 然后再在里面添砖加瓦

from PyQt5 import QtCore, QtGui
import barcode
import sys
import time
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox, QTableWidgetItem
# 文件集合, 保存选择的文件的绝对路径, 确保元素不重复
fileSet = set()

# method
def importEvent(mw, ui):
    files = QFileDialog.getOpenFileNames(mw, '打开文件', './', ("Images (*.png *.jpg *.bmp *.gif *.raw *.tif *.xpm)"))
    for i in files[0]:
        fileSet.add(i)
    ui.totalFileNum.setText(str(len(fileSet)))  # 文件总数
    ui.fileList.clearContents()
    ui.fileList.setRowCount(0)
    for file in fileSet:
        row = ui.fileList.rowCount()  
        ui.fileList.insertRow(row)
        # 文件名
        fileNameItem = QTableWidgetItem(os.path.basename(file))
        fileNameItem.setTextAlignment(QtCore.Qt.AlignCenter)
        # 文件大小
        fileSizeItem = QTableWidgetItem(str("%.2f" % (os.path.getsize(file) / 1024)) + "KB")
        fileSizeItem.setTextAlignment(QtCore.Qt.AlignCenter)
        # 文件绝对路径
        filePathItem = QTableWidgetItem(file)
        filePathItem.setTextAlignment(QtCore.Qt.AlignCenter)
        # 文件创建时间
        createTimeItem = QTableWidgetItem(timeStampToStrTime(os.path.getctime(file)))
        createTimeItem.setTextAlignment(QtCore.Qt.AlignCenter)
        # 文件修改时间
        modifyTimeItem = QTableWidgetItem(timeStampToStrTime(os.path.getmtime(file)))
        modifyTimeItem.setTextAlignment(QtCore.Qt.AlignCenter)
        ui.fileList.setItem(row, 0, fileNameItem)
        ui.fileList.setItem(row, 1, fileSizeItem)
        ui.fileList.setItem(row, 2, filePathItem)
        ui.fileList.setItem(row, 3, createTimeItem)
        ui.fileList.setItem(row, 4, modifyTimeItem)

def exitEvent(mw):
    """退出事件"""
    mw.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = QMainWindow()
    ui = barcode.Ui_MainWindow()
    ui.setupUi(mw)
    mw.show()
    # 主体代码

    # 字段显示宽度
    ui.fileList.setColumnWidth(0, 150)
    ui.fileList.setColumnWidth(1, 150)
    ui.fileList.setColumnWidth(2, 500)
    ui.fileList.setColumnWidth(3, 200)
    ui.fileList.setColumnWidth(4, 200)
    ui.resultList.setColumnWidth(0, 150)
    ui.resultList.setColumnWidth(1, 150)
    ui.resultList.setColumnWidth(2, 400)
    ui.resultList.setColumnWidth(3, 400)

    # 按钮
    ui.importBtn.clicked.connect(lambda: importEvent(mw, ui))  # 导入按钮
    ui.exitBtn.clicked.connect(lambda: exitEvent(mw))  # 退出按钮
    sys.exit(app.exec_())
  • 这里用到文件选择器, 要用QFileDialog.getOpenFileNames(), 按住Ctrl可以选择多个文件。 别用getOpenfileName()这个一次只能选择一个文件。

  • 返回的files是一个元组, ([文件1绝对路径, 文件2绝对路径, ...], 文件类型)
    files[0]返回的是选中的文件的绝对路径, 有了绝对路径就好办事了, 文件名、大小、创建时间等属性可以由os.path得到

  • 创建一个集合fileSet用于保存文件的绝对路径, 这样就不怕选择了重复的文件

  • ("Images (*.png *.jpg *.bmp *.gif *.raw *.tif *.xpm)")是对文件类型的限制, 去掉这个参数就是可以添加任何文件
    每次新加入文件就把原来的表格内容清空同时行号置0

ui.fileList.clearContents()
ui.fileList.setRowCount(0)

运行main.py


图12

pyqt5入门练习-扫描条形码(二)

posted @ 2020-05-19 01:03  FuKai  阅读(1635)  评论(0编辑  收藏  举报