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

六、扫描事件

打开barcode.ui 双击第二个表格 依次写出各个字段



# main.py
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)"))
    if !files:
        return
    for i in files[0]:
        fileSet.add(i)
    ui.totalFile.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(timeToStrTime(os.path.getctime(file)))
        createTimeItem.setTextAlignment(QtCore.Qt.AlignCenter)
        # 文件修改时间
        modifyTimeItem = QTableWidgetItem(timeToStrTime(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 timeToStrTime(timestamp):
    """将时间戳转化为格式时间字符串"""
    timeStruct = time.localtime(timestamp)
    return time.strftime('%Y-%m-%d %H:%M', timeStruct)

def startScan(mw, ui):
    if len(fileSet) == 0:
        QMessageBox.information(mw, '提示', '你没有选择任何条形码图片文件!', QMessageBox.Ok, QMessageBox.Ok)
        return
    successCount = 0  # 成功检测数
    failCount = 0  # 失败检测数
    cmd = ".\ZBar\bin\zbarimg.exe " 
    ui.resultList.clearContents()
    ui.resultList.setRowCount(0)
    for file in fileSet:
        array = execCmd(cmd + file) # 执行命令.zbarimg.exe imgPath
        row = ui.resultList.rowCount()
        ui.resultList.insertRow(row)
        fileNameItem = QTableWidgetItem(os.path.basename(file))
        fileNameItem.setTextAlignment(QtCore.Qt.AlignCenter)
        if len(array) == 0:
            # 设置失败红色字体
            statusItem = QTableWidgetItem("扫描失败")
            statusItem.setTextAlignment(QtCore.Qt.AlignCenter)
            brush = QtGui.QBrush(QtGui.QColor(234, 31, 42))
            brush.setStyle(QtCore.Qt.NoBrush)
            statusItem.setForeground(brush)

            typeItem = QTableWidgetItem("请调整图片清晰度")
            typeItem.setTextAlignment(QtCore.Qt.AlignCenter)
            brush = QtGui.QBrush(QtGui.QColor(234, 31, 42))
            brush.setStyle(QtCore.Qt.NoBrush)
            typeItem.setForeground(brush)

            valueItem = QTableWidgetItem("请调整图片清晰度")
            valueItem.setTextAlignment(QtCore.Qt.AlignCenter)
            brush = QtGui.QBrush(QtGui.QColor(234, 31, 42))
            brush.setStyle(QtCore.Qt.NoBrush)
            valueItem.setForeground(brush)
            failCount += 1
        else:
            # 设置成功绿色字体
            statusItem = QTableWidgetItem("扫描成功")
            statusItem.setTextAlignment(QtCore.Qt.AlignCenter)
            brush = QtGui.QBrush(QtGui.QColor(35, 177, 32))
            brush.setStyle(QtCore.Qt.NoBrush)
            statusItem.setForeground(brush)

            result = array[0].split(":") # 分离字符串得到条形码格式和内容
            codebarType = result[0]  # 条形码格式
            codebarValue = result[1].strip() # 条形码内容, 去掉两端的空格、制表符trim()函数
            typeItem = QTableWidgetItem(codebarType)
            typeItem.setTextAlignment(QtCore.Qt.AlignCenter)

            valueItem = QTableWidgetItem(codebarValue)
            valueItem.setTextAlignment(QtCore.Qt.AlignCenter)
            successCount += 1
        ui.resultList.setItem(row, 0, fileNameItem)
        ui.resultList.setItem(row, 1, statusItem)
        ui.resultList.setItem(row, 2, typeItem)
        ui.resultList.setItem(row, 3, valueItem)
        ui.successScanNum.setText(str(successCount)) # 设置成功扫描的文件数
        ui.failScanNum.setText(str(failCount))

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

def execCmd(cmd):
    """执行控制台命令"""
    result = os.popen(cmd)
    text = result.readlines()
    result.close()
    return text

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.scanBtn.clicked.connect(lambda: startScan(mw, ui))  # 扫描按钮
    ui.importBtn.clicked.connect(lambda: importEvent(mw, ui))  # 导入按钮
    ui.exitBtn.clicked.connect(lambda: exitEvent(mw))  # 退出按钮
    sys.exit(app.exec_())

通过execCmd()方法执行控制台指令, cmd = ".\ZBar\bin\zbarimg.exe "即执行main.py运行的当前目路下的ZBar/bin/zbarimg.exe程序, 只要后面追加一个图片的绝对路径就可以实现扫描操作, 要注意的是zbarimg.exe与图片绝对路径之间有个空格。execCmd()通过执行命令得到结果, 通过把结果加载到内存中, 然后再分离各个字符串, 得到扫描结果return的text是一个列表, 里面要么只有1个元素就是扫描结果, 要么就没有元素未扫描出结果, 很简单的就可以判定
运行main.py

七、导出到excel

使用xlwt模块pip install xlwt

# main.py
def exportEvent(mw, ui):
    """保存到excel"""
    if len(fileSet) == 0:
        QMessageBox.information(mw, '提示', '你没有选择任何条形码图片文件!', QMessageBox.Ok, QMessageBox.Ok)
        return
    # 创建一个workbook 设置编码
    workbook = xlwt.Workbook(encoding='utf-8')
    # 创建一个worksheet
    worksheet = workbook.add_sheet('sheet1')
    # 样式
    t = xlwt.Font()
    t.colour_index = 10  # 红色字体
    redColorFont = xlwt.XFStyle()
    redColorFont.font = t

    t = xlwt.Font()
    t.colour_index = 57  # 绿色字体
    greenColorFont = xlwt.XFStyle()
    greenColorFont.font = t

    # 参数对应 行, 列, 值
    worksheet.write(0, 0, label='文件名')
    worksheet.col(0).width = 256 * 20
    worksheet.write(0, 1, label='扫描状态')
    worksheet.write(0, 2, label='格式')
    worksheet.write(0, 3, label='值')
    worksheet.col(3).width = 256 * 20
    worksheet.write(0, 4, label='文件路径')
    worksheet.col(4).width = 256 * 80

    cmd = ".\ZBar\bin\zbarimg.exe "
    row = 1
    for file in fileSet:
        worksheet.write(row, 0, label=os.path.basename(file))
        array = execCmd(cmd + file)
        if len(array) == 0:
            worksheet.write(row, 1, u'扫描失败', redColorFont)
        else:
            worksheet.write(row, 1, u'扫描成功', greenColorFont)
            result = array[0].split(":")
            worksheet.write(row, 2, label=result[0])
            worksheet.write(row, 3, label=result[1].strip())
        worksheet.write(row, 4, label=file)
        row += 1
    # 保存
    workbook.save('.\data.xls')

八、pyinstaller打包

使用pyinstaller把.py文件打包成.exe文件, 其中有很多坑, 比如图片资源没法打包, 路径问题等
进入main.py文件所在目录
由于没法直接打包图片, 所以需要将图片解码成.py文件然后再当成模块在python中使用
准备一个图标图标
先在qt designer中设置windowIcon

然后保存, 使用pyUIC转化一下barcode.ui文件
窗口的图标就设置好了
打包图片资源:

  1. 创建resource.qrc文件
  2. 输入以下内容(要保证图片和.qrc文件在同一目录)
<RCC>
  <qresource prefix="/" >
    <file>favicon.png</file>
  </qresource>
</RCC>
  1. pyrcc5 -o resource.py resource.qrc转换得到resource.py模块
  2. 在barcode.py文件中引入resource.py模块
  3. 修改用到的图片路径, 在前面加引号:

即使pycharm提示没使用也没关系, 打包后可以自动引用,虽然pycharm运行的时候窗口没有显示图标,但打包后就可以看到
将favicon.png复制一份, 改后缀为ico文件
打包:
pyinstaller -w main.py -i favicon.ico -n "barcodeKing"
-w窗口运行伴随控制台, 方便调试
-i参数是设置.exe文件的图标
-F参数, 把文件打包成单个.exe文件, 不推荐, 因为ZBar是外部程序, 不能被打包进.exe, 会造成路径问题闪退
-n为.exe文件命名



打包成功
进入dist->barcodeKing, 把ZBar目录复制到与barcodeKing.exe同级的目录下



运行良好

九、小结

没有很深入的研究, 只是pyqt5入门的操作, 写得不清楚也请见谅, 我是很水的
源码在这里https://github.com/CaseyFu/python/tree/master/src/GUI/barcode
如果你也是为了完成任务可以交我这个/doge哈哈哈哈

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

原文地址:https://www.cnblogs.com/xfk1999/p/python-pyqt5-barcode-two.html