入门 PyQt6 看过来(项目)27 在线购物-商品选购
商品选购页面包含商品选购标题,商品搜索框和搜索按钮,用户信息,商品列表展示以及商品图片展示。如下图所示:
1 页面设计
我们根据上图展示在QTDesigner里设计如下:
商品选购、商品名称、用户、图片等文字用QLabel标签。查询和选购以及打印用QPushButton按钮。列表采用QTableView列表视图。
其中他们的属性名字命名如下:
2 功能实现
2.1 查询功能
点击商品查询,输入内容或者空的时候,会在列表里展示查询到的商品信息。
def query(self):global commodityspnm=self.lePNm.text()book=openpyxl.load_workbook(r'data/netshop.xlsx')sheet=book['商品表']commoditys=[]list_key=['商品号','商品名称','类别编号','价格','库存量']list_val=[]r=0#读取“商品名称”列的全部数据,与用户输入的关键词逐一对比for cell_pname in tuple(sheet.columns)[2][1:]:r+=1#符合条件的关键词在于商品名称中if pnm in cell_pname.value:commodity=[cell.value for cell in tuple(sheet.rows)[r]]#填写list_val[],并与list_key[]合并成一个字典记录list_val.append(commodity[0]) #商品号list_val.append(commodity[1]) #商品名称list_val.append(commodity[2]) #类别编号list_val.append(commodity[3]) #价格list_val.append(commodity[4]) #库存#合成为字典dict_com=dict(zip(list_key, list_val))commoditys.append(dict_com)list_val=[]#清除模型里的旧数据self.im.clear()#重新生成表头self.initTableHeader()r=0#遍历商品信息列表,将查询到的记录逐条加载进模型for k, dict_com in enumerate(commoditys):self.im.setItem(r,0,QStandardItem(str(dict_com['商品号'])))self.im.setItem(r,1,QStandardItem(str(dict_com['类别编号'])))self.im.setItem(r,2,QStandardItem(str(dict_com['商品名称'])))self.im.setItem(r,3,QStandardItem(str(dict_com['价格'])))self.im.setItem(r,4,QStandardItem(str(dict_com['库存量'])))r+=1
槽函数绑定信号:
self.pbQue.clicked.connect(self.query)
此时列表信息就会展示出来,如下图:
2.2 图片展示
当我们点击列表商品行的时候,右侧出现图片显示:
此时我们用showImg函数实现:
def showImg(self):#获取当前行数据row=self.tbvCom.currentIndex().row()index=self.tbvCom.model().index(row,0)pid=self.tbvCom.model().data(index)image=QPixmap(r'image/goods/'+pid+'.jpg')self.lbImg.setPixmap(image)
2.3 选购
选购会思考是否下单过而未结算以及下单过已结算和未下单的情况,分别列出来,做成分支处理。下过单未结算,就是已选购,不需要重复选购,下单过结算了,可以重新下单。未下单的可以直接下单。
def preShop(self):book=openpyxl.load_workbook(r'data/netshop.xlsx')sheet1=book['订单项表']sheet2=book['订单表']#首先判断该用户在此前有没有选购(尚未结算)过商品#1 找出订单项表中所有状态不为“结算”的记录,将它们对应的订单号放入一个集合r=0set_oid=set()for cell_stat in tuple(sheet1.columns)[3][1:]:r += 1if cell_stat.value != '结算':orderitem=[cell.value for cell in tuple(sheet1.rows)[r]]set_oid.add(orderitem[0])#2 读取订单表的订单号、用户账号列,合成为字典list_oid=[cell.value for cell in tuple(sheet2.columns)[0][1:]]list_uid=[cell.value for cell in tuple(sheet2.columns)[1][1:]]dict_ouid=dict(zip(list_oid,list_uid))#3 用第一步得到的订单号集合到第2步得到的字典中去对比oid =0exist = Falsefor id in enumerate(set_oid):for key_oid, val_uid in dict_ouid.items():if (id[1] == key_oid) and (appvar.getID() ==val_uid):exist=Trueoid=id[1]breakrow =self.tbvCom.currentIndex().row()index=self.tbvCom.model().index(row,0)#若没有比中,说明时初次选购if exist ==False:#读取订单项表的订单号列,生成预备订单号(当前已有订单号最大值+1)list_oid=[cell.value for cell in tuple(sheet1.columns)[0][1:]]if list_oid == []:old=1else:old=max(list_oid)+1pid=eval(self.tbvCom.model().data(index))#写入预备订单项s1r=str(sheet1.max_row+1)sheet1['A'+s1r].alignment=Alignment(horizontal='center')sheet1['B'+s1r].alignment=Alignment(horizontal='center')sheet1['C'+s1r].alignment=Alignment(horizontal='center')sheet1['A' +s1r]=oidsheet1['B'+s1r]=pidsheet1['C'+s1r]=1sheet1['D'+s1r]='选购'#写入预备订单s2r=str(sheet2.max_row +1)sheet2['A'+s2r].alignment=Alignment(horizontal='center')sheet2['A'+s2r]=oidsheet2['B'+s2r]=appvar.getID()#若比中,说明该用户此前已选/订购过商品else:pid=eval(self.tbvCom.model().data(index))#添加此次选购的订单项#确定插入记录的行号s1r=str(sheet1.max_row+1)sheet1['A' + s1r].alignment = Alignment(horizontal='center')sheet1['B' + s1r].alignment = Alignment(horizontal='center')sheet1['C' + s1r].alignment = Alignment(horizontal='center')sheet1['A' + s1r] = oidsheet1['B' + s1r] = pidsheet1['C' + s1r] = 1sheet1['D' + s1r] = '选购'book.save(r'data/netshop.xlsx')book.close()msgbox=QMessageBox.information(self, '提示', '已选购。')print(msgbox)
2.4 打印
点击打印按钮实现打印预览功能,效果如下:
# 点击打印def printTable(self):#创建打印预览对话框dlg=QPrintPreviewDialog()dlg.paintRequested.connect(self.handlePrint)dlg.exec()# 执行打印函数def handlePrint(self,printer):doc=QTextDocument()cur=QTextCursor(doc)#设定标题文字格式、写标题fmt_textchar=QTextCharFormat()fmt_textchar.setFontFamily('微软雅黑')fmt_textchar.setFontPointSize(10)fmt_textblock=QTextBlockFormat()fmt_textblock.setAlignment(Qt.AlignmentFlag.AlignHCenter)cur.setBlockFormat(fmt_textblock)cur.insertText("商品名称中包含 '"+ self.lePNm.text()+"'", fmt_textchar)#设定表格式fmt_table=QTextTableFormat()fmt_table.setBorder(1)fmt_table.setBorderStyle(QTextTableFormat.BorderStyle.BorderStyle_Solid)fmt_table.setCellSpacing(0)fmt_table.setTopMargin(0)fmt_table.setCellPadding(4)fmt_table.setAlignment(Qt.AlignmentFlag.AlignHCenter)cur.insertTable(self.im.rowCount()+1, self.im.columnCount(),fmt_table)#写表头for i in range(0, self.im.columnCount()):header=self.im.headerData(i, Qt.Orientation.Horizontal)cur.insertText(header)cur.movePosition(QTextCursor.MoveOperation.NextCell)#写表记录for row in range(0,self.im.rowCount()):for col in range(0, self.im.columnCount()):index=self.im.index(row, col)cur.insertText(str(index.data()))cur.movePosition(QTextCursor.MoveOperation.NextCell)doc.print(printer)
3 完整代码
完整代码如下,大家可以参考使用:
UI页面代码:
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QMainWindowclass Ui_MainWindow(QMainWindow):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(812, 452)self.centralwidget = QtWidgets.QWidget(parent=MainWindow)self.centralwidget.setObjectName("centralwidget")self.lbTitle = QtWidgets.QLabel(parent=self.centralwidget)self.lbTitle.setGeometry(QtCore.QRect(340, 30, 111, 31))font = QtGui.QFont()font.setPointSize(18)self.lbTitle.setFont(font)self.lbTitle.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)self.lbTitle.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)self.lbTitle.setObjectName("lbTitle")self.tbvCom = QtWidgets.QTableView(parent=self.centralwidget)self.tbvCom.setGeometry(QtCore.QRect(20, 120, 601, 261))font = QtGui.QFont()font.setPointSize(12)self.tbvCom.setFont(font)self.tbvCom.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection)self.tbvCom.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)self.tbvCom.setObjectName("tbvCom")self.tbvCom.horizontalHeader().setDefaultSectionSize(120)self.tbvCom.horizontalHeader().setMinimumSectionSize(25)self.tbvCom.horizontalHeader().setStretchLastSection(True)self.tbvCom.verticalHeader().setVisible(False)self.lbName = QtWidgets.QLabel(parent=self.centralwidget)self.lbName.setGeometry(QtCore.QRect(20, 90, 71, 16))font = QtGui.QFont()font.setPointSize(12)self.lbName.setFont(font)self.lbName.setObjectName("lbName")self.lePNm = QtWidgets.QLineEdit(parent=self.centralwidget)self.lePNm.setGeometry(QtCore.QRect(100, 90, 121, 21))self.lePNm.setObjectName("lePNm")self.pbQue = QtWidgets.QPushButton(parent=self.centralwidget)self.pbQue.setGeometry(QtCore.QRect(230, 90, 75, 24))font = QtGui.QFont()font.setPointSize(12)self.pbQue.setFont(font)self.pbQue.setObjectName("pbQue")self.lbUsr = QtWidgets.QLabel(parent=self.centralwidget)self.lbUsr.setGeometry(QtCore.QRect(400, 90, 191, 21))font = QtGui.QFont()font.setPointSize(14)self.lbUsr.setFont(font)self.lbUsr.setText("")self.lbUsr.setObjectName("lbUsr")self.lbUserName = QtWidgets.QLabel(parent=self.centralwidget)self.lbUserName.setGeometry(QtCore.QRect(350, 90, 41, 20))font = QtGui.QFont()font.setPointSize(12)self.lbUserName.setFont(font)self.lbUserName.setObjectName("lbUserName")self.pbPrint = QtWidgets.QPushButton(parent=self.centralwidget)self.pbPrint.setGeometry(QtCore.QRect(534, 380, 81, 31))font = QtGui.QFont()font.setPointSize(12)self.pbPrint.setFont(font)self.pbPrint.setObjectName("pbPrint")self.lbPic = QtWidgets.QLabel(parent=self.centralwidget)self.lbPic.setGeometry(QtCore.QRect(690, 120, 54, 16))font = QtGui.QFont()font.setPointSize(12)self.lbPic.setFont(font)self.lbPic.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)self.lbPic.setObjectName("lbPic")self.lbImg = QtWidgets.QLabel(parent=self.centralwidget)self.lbImg.setGeometry(QtCore.QRect(653, 160, 141, 131))self.lbImg.setText("")self.lbImg.setScaledContents(True)self.lbImg.setObjectName("lbImg")self.pbPre = QtWidgets.QPushButton(parent=self.centralwidget)self.pbPre.setGeometry(QtCore.QRect(690, 320, 75, 24))font = QtGui.QFont()font.setPointSize(12)self.pbPre.setFont(font)self.pbPre.setObjectName("pbPre")MainWindow.setCentralWidget(self.centralwidget)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "商品选购"))self.lbTitle.setText(_translate("MainWindow", "商品选购"))self.lbName.setText(_translate("MainWindow", "商品名称"))self.pbQue.setText(_translate("MainWindow", "查询"))self.lbUserName.setText(_translate("MainWindow", "用户:"))self.pbPrint.setText(_translate("MainWindow", "打印..."))self.lbPic.setText(_translate("MainWindow", "图片"))self.pbPre.setText(_translate("MainWindow", "选购"))
功能实现逻辑代码:
# -*- coding:utf-8 -*-
"""
------------------------------------------------
File Name: PreShop.py
Description:
Author: lzq
date:2024-08-07 09:10
------------------------------------------------
"""
import sysimport openpyxl as openpyxl
import printer
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIcon, QPixmap, QStandardItemModel, QStandardItem, QTextDocument, QTextCursor, QTextCharFormat, \QTextBlockFormat, QTextTableFormat
from PyQt6.QtPrintSupport import QPrintPreviewDialog
from PyQt6.QtWidgets import QMessageBox, QApplication
from openpyxl.styles import Alignmentfrom pyqt6Learn.myNetShop import appvar
from pyqt6Learn.myNetShop.ui.PreShop_ui import Ui_MainWindow#存放查询到的商品数据(字典列表)
commoditys=[]
class PreWindow(Ui_MainWindow):def __init__(self):super(PreWindow,self).__init__()self.setupUi(self)self.initUi()def initUi(self):self.setWindowIcon(QIcon('image/netshop.png'))self.setWindowFlag(Qt.WindowType.MSWindowsFixedSizeDialogHint)self.lePNm.returnPressed.connect(self.query)self.pbQue.clicked.connect(self.query)self.tbvCom.clicked.connect(self.showImg)self.pbPrint.clicked.connect(self.printTable)self.pbPre.clicked.connect(self.preShop)#获取当前登录用户账号self.lbUsr.setText(appvar.getID())#生成商品信息表头self.initTableHeader()# 购物车图片self.pbPre.setIcon(QIcon(QPixmap(r'image/cart.png')))def initTableHeader(self):#创建模型self.im=QStandardItemModel()self.im.setHorizontalHeaderItem(0,QStandardItem('商品号'))self.im.setHorizontalHeaderItem(1,QStandardItem('商品名称'))self.im.setHorizontalHeaderItem(2,QStandardItem('类别'))self.im.setHorizontalHeaderItem(3,QStandardItem('价格'))self.im.setHorizontalHeaderItem(4,QStandardItem('库存量'))self.tbvCom.setModel(self.im)#设置表格各列的宽度self.tbvCom.setColumnWidth(0,70)self.tbvCom.setColumnWidth(1,300)self.tbvCom.setColumnWidth(2,60)self.tbvCom.setColumnWidth(3,70)self.tbvCom.setColumnWidth(4,40)def query(self):global commodityspnm=self.lePNm.text()book=openpyxl.load_workbook(r'data/netshop.xlsx')sheet=book['商品表']commoditys=[]list_key=['商品号','商品名称','类别编号','价格','库存量']list_val=[]r=0#读取“商品名称”列的全部数据,与用户输入的关键词逐一对比for cell_pname in tuple(sheet.columns)[2][1:]:r+=1#符合条件的关键词在于商品名称中if pnm in cell_pname.value:commodity=[cell.value for cell in tuple(sheet.rows)[r]]#填写list_val[],并与list_key[]合并成一个字典记录list_val.append(commodity[0]) #商品号list_val.append(commodity[1]) #商品名称list_val.append(commodity[2]) #类别编号list_val.append(commodity[3]) #价格list_val.append(commodity[4]) #库存#合成为字典dict_com=dict(zip(list_key, list_val))commoditys.append(dict_com)list_val=[]#清除模型里的旧数据self.im.clear()#重新生成表头self.initTableHeader()r=0#遍历商品信息列表,将查询到的记录逐条加载进模型for k, dict_com in enumerate(commoditys):self.im.setItem(r,0,QStandardItem(str(dict_com['商品号'])))self.im.setItem(r,1,QStandardItem(str(dict_com['类别编号'])))self.im.setItem(r,2,QStandardItem(str(dict_com['商品名称'])))self.im.setItem(r,3,QStandardItem(str(dict_com['价格'])))self.im.setItem(r,4,QStandardItem(str(dict_com['库存量'])))r+=1def showImg(self):print("展示图片")row=self.tbvCom.currentIndex().row()index=self.tbvCom.model().index(row,0)pid=self.tbvCom.model().data(index)image=QPixmap(r'image/goods/'+pid+'.jpg')self.lbImg.setPixmap(image)def printTable(self):#创建打印预览对话框dlg=QPrintPreviewDialog()dlg.paintRequested.connect(self.handlePrint)dlg.exec()def handlePrint(self,printer):doc=QTextDocument()cur=QTextCursor(doc)#设定标题文字格式、写标题fmt_textchar=QTextCharFormat()fmt_textchar.setFontFamily('微软雅黑')fmt_textchar.setFontPointSize(10)fmt_textblock=QTextBlockFormat()fmt_textblock.setAlignment(Qt.AlignmentFlag.AlignHCenter)cur.setBlockFormat(fmt_textblock)cur.insertText("商品名称中包含 '"+ self.lePNm.text()+"'", fmt_textchar)#设定表格式fmt_table=QTextTableFormat()fmt_table.setBorder(1)fmt_table.setBorderStyle(QTextTableFormat.BorderStyle.BorderStyle_Solid)fmt_table.setCellSpacing(0)fmt_table.setTopMargin(0)fmt_table.setCellPadding(4)fmt_table.setAlignment(Qt.AlignmentFlag.AlignHCenter)cur.insertTable(self.im.rowCount()+1, self.im.columnCount(),fmt_table)#写表头for i in range(0, self.im.columnCount()):header=self.im.headerData(i, Qt.Orientation.Horizontal)cur.insertText(header)cur.movePosition(QTextCursor.MoveOperation.NextCell)#写表记录for row in range(0,self.im.rowCount()):for col in range(0, self.im.columnCount()):index=self.im.index(row, col)cur.insertText(str(index.data()))cur.movePosition(QTextCursor.MoveOperation.NextCell)doc.print(printer)#选购功能函数def preShop(self):book=openpyxl.load_workbook(r'data/netshop.xlsx')sheet1=book['订单项表']sheet2=book['订单表']#首先判断该用户在此前有没有选购(尚未结算)过商品#1 找出订单项表中所有状态不为“结算”的记录,将它们对应的订单号放入一个集合r=0set_oid=set()for cell_stat in tuple(sheet1.columns)[3][1:]:r += 1if cell_stat.value != '结算':orderitem=[cell.value for cell in tuple(sheet1.rows)[r]]set_oid.add(orderitem[0])#2 读取订单表的订单号、用户账号列,合成为字典list_oid=[cell.value for cell in tuple(sheet2.columns)[0][1:]]list_uid=[cell.value for cell in tuple(sheet2.columns)[1][1:]]dict_ouid=dict(zip(list_oid,list_uid))#3 用第一步得到的订单号集合到第2步得到的字典中去对比oid =0exist = Falsefor id in enumerate(set_oid):for key_oid, val_uid in dict_ouid.items():if (id[1] == key_oid) and (appvar.getID() ==val_uid):exist=Trueoid=id[1]breakrow =self.tbvCom.currentIndex().row()index=self.tbvCom.model().index(row,0)#若没有比中,说明时初次选购if exist ==False:#读取订单项表的订单号列,生成预备订单号(当前已有订单号最大值+1)list_oid=[cell.value for cell in tuple(sheet1.columns)[0][1:]]if list_oid == []:old=1else:old=max(list_oid)+1pid=eval(self.tbvCom.model().data(index))#写入预备订单项s1r=str(sheet1.max_row+1)sheet1['A'+s1r].alignment=Alignment(horizontal='center')sheet1['B'+s1r].alignment=Alignment(horizontal='center')sheet1['C'+s1r].alignment=Alignment(horizontal='center')sheet1['A' +s1r]=oidsheet1['B'+s1r]=pidsheet1['C'+s1r]=1sheet1['D'+s1r]='选购'#写入预备订单s2r=str(sheet2.max_row +1)sheet2['A'+s2r].alignment=Alignment(horizontal='center')sheet2['A'+s2r]=oidsheet2['B'+s2r]=appvar.getID()#若比中,说明该用户此前已选/订购过商品else:pid=eval(self.tbvCom.model().data(index))#添加此次选购的订单项#确定插入记录的行号s1r=str(sheet1.max_row+1)sheet1['A' + s1r].alignment = Alignment(horizontal='center')sheet1['B' + s1r].alignment = Alignment(horizontal='center')sheet1['C' + s1r].alignment = Alignment(horizontal='center')sheet1['A' + s1r] = oidsheet1['B' + s1r] = pidsheet1['C' + s1r] = 1sheet1['D' + s1r] = '选购'book.save(r'data/netshop.xlsx')book.close()msgbox=QMessageBox.information(self, '提示', '已选购。')print(msgbox)