基于PyQt5实现简易饮品自动售货机

2023-11-07

记录一个最近Python课程的作业,编写一个简易的饮品自动售货机,购物者选择需要的饮品,通过使用购物卡的方式支付,支付成功后从出货口取出饮品。

使用环境:Python3.8.6 + PyQt5 5.15.4

搭建的界面GUI

在这里插入图片描述

使用的核心代码解析

载入商品操作:通过调用Fuc.py文件中的loadTxt()函数载入商品信息 然后对载入信息进行处理,剔除商品数量为0的数据,拼接成我们所需要的格式;设置相关按钮不可选/可选

# Fuc.py
def loadTxt():
    """
    载入本地load.txt文件
    :return: 字典 --> 商品名:[价钱,数量]
    """
    with open("load.txt", 'r', encoding='utf-8') as f:
        lst = f.read().split("\n")  # 读取本地load.txt内容
    dct = {}
    for i in lst[:-1]:  # 解析重组数据
        name, money, num = i.split(",")
        if int(num) != 0:  # 剔除卖完的饮品
            dct[name] = [int(money), int(num)]  # 重组后数据格式: {name:[money,num]}
    return dct

# mainWin.py
def load(self):
    """
        载入商品
        :return: None
        """
    self.load_dct = Fuc.loadTxt()  # 载入商品信息
    items = [key + "  " + str(value[0]) + "元" for key, value in self.load_dct.items()]  # 格式设置
    self.pushButton_load.setEnabled(False)  # 设置 [载入商品]不可选
    self.listWidget.addItems(items)  # 商品框载入商品条目信息
    self.pushButton_card.setEnabled(True)  # 设置 [查询余额]可选

本地load.txt文件格式:商品名称,价格,数量
在这里插入图片描述

插入购物卡:设置相关按钮不可选/可选,出现提示信息

# mainWin.py
def card(self):
    """
    插入购物卡
    :return: None
    """
    self.pushButton_card.setEnabled(False)  # 设置 [插入购物卡]不可选
    self.pushButton_search.setEnabled(True)  # 设置 [查询余额] 可选
    QMessageBox.information(None, "提示", "购物卡加载成功")
    self.cardLoad = 1  # 判断购物卡是否已经插入

查询购物卡余额:读取本地money.txt文件获取购物卡余额

#Fuc.py
def searchMoneyTxt():
    """
    查询余额
    :return: 余额 (int)
    """
    with open("money.txt", 'r') as f:
        return f.read().split(",")

# mainWin.py
def search(self):
    """
    查询余额
    :return:None
    """
    pwd = Fuc.searchMoneyTxt()  # 获取购物卡密码
    text = QInputDialog.getText(self, "输入密码", "请输入密码", QLineEdit.Normal)[0]  # 弹出密码输入框
    if text == pwd[1]:  # 判断密码是否正确
        s = "余额:" + str(pwd[0])
        QMessageBox.information(None, "提示", s)
    else:
        QMessageBox.warning(None, "警告", "密码错误")

本地money.txt文件格式:余额,购物卡密码
在这里插入图片描述

购入:将所选的商品添加至预购框中

# mainWin.py
def shop(self):
    """
    购入
    :return: None
    """
    item_text = self.listWidget.currentItem().text()  # 读取选中的商品
    self.listWidget_2.addItem(item_text)  # 添加至购物框

结算:先判断购物卡是否已经插入,遍历预购框中物品,初步计算购买总值比对余额

# Fuc.py
def writeMoneyTxt(money):
    """
    修改信用卡余额
    :param money: 余额
    :return:None
    """
    with open("money.txt", 'w', encoding='utf-8') as f:
        f.write(str(money)+",123123")

# mainWin.py
def checkoutCard(self):
    """
    结算
    :return:
    """
    if self.cardLoad == 0:  # 判断购物卡是否插入
        QMessageBox.warning(None, "警告", "请插入信用卡")
    else:
        items = [self.listWidget_2.item(i).text() for i in range(self.listWidget_2.count())]  # 读取购物框商品
        # itmes --> ['PEPSI百事可乐  10元', 'PEPSI百事可乐  10元']
        num = 0
        for item in items:
            num += int(item[-3:-1])  # 计算总额

        money = int(Fuc.searchMoneyTxt()[0])  # 读取余额
        if num > money:  # 判断余额是否充足
            QMessageBox.warning(None, "警告", "余额不足")
        else:
            end = money - num
            s = f"购买成功,已经扣除{end}元"
            Fuc.writeMoneyTxt(end)  # 写入结算后余额
            QMessageBox.information(None, "提示", s)
            self.listWidget_2.clear()  # 清除购物框内容

删除预购框中选中项

def delItem(self):
    """
    删除
    :return:None
    """
    selected_index = self.listWidget_2.currentRow()  # 获取当前项的位置
    self.listWidget_2.takeItem(selected_index)  # 删除当前项

其它函数:修改购买相应商品的数量

# Fuc.py
def saveLoadTxt(names):
    """
    修改商品数量
    :param names: 购物的商品名称[list]  示例:['PEPSI百事可乐  10元', '椰树COCONUTPALM  10元']
    :return:None
    """
    dct = loadTxt()  # 读取本地文件 [返回字典]
    for name in names:  # 遍历输入的列表
        newName = name.split("  ")[0]  # 重组数据
        dct[newName][-1] -= 1  # 修改对应数量
    txt = ""
    for key, value in dct.items():
        txt += f"{key},{value[0]},{value[1]}\n"  # 重组内容
    with open("load.txt", 'w', encoding="utf-8") as f:
        f.write(txt)  # 覆写load.txt文件
相关控件样式

在程序中,对按钮、列表框调用QSS代码修改样式,增加了鼠标悬停、点击变色等样式

button_style = 'QPushButton{' \
               'font: 10pt "微软雅黑";' \
               'color: #2f3640;' \
               'background-color: #f5f6fa;' \
               'border-color: #2f3640;' \
               'border-radius: 15px;' \
               'border-style: solid;' \
               'border-width: 2px;' \
               'padding: 5px;}' \
               'QPushButton:hover{' \
               'color: #FFFFFF;' \
               'background-color: #718093;' \
               'border-color: #2f3640;}' \
               'QPushButton:pressed,checked{' \
               'color: #FFFFFF;' \
               'background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #273c75, stop:1 #487eb0);}' \
               'QPushButton:disabled{' \
               'color: #FFFFFF;' \
               'background-color: #dcdde1;' \
               'border-color: #dcdde1;}'
title_style = 'font-family: 等线;font-weight:400;font-size:48px;line-height:14px;text-align:center;color:rgb(0, 0, 84);'
label_style = 'font-family: 等线;font-weight:10;font-size:16px;line-height:14px;text-align:center;color:rgb(0, 0, 84);'

完整代码

mainWin.py

from ui import Ui_Form
from sys import argv, exit
import Fuc
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox, QInputDialog, QLineEdit


class MainWin(QMainWindow, Ui_Form):
    def __init__(self):
        super(MainWin, self).__init__()
        self.setupUi(self)
        self.load_dct = {}
        self.cardLoad = 0  # 初始化购物卡信息
        self.pushButton_shop.setStyleSheet(Fuc.button_style)
        self.pushButton_shop.clicked.connect(self.shop)
        self.pushButton_card.setStyleSheet(Fuc.button_style)
        self.pushButton_card.setEnabled(False)
        self.pushButton_card.clicked.connect(self.card)
        self.pushButton_load.setStyleSheet(Fuc.button_style)
        self.pushButton_load.clicked.connect(self.load)
        self.pushButton_search.setStyleSheet(Fuc.button_style)
        self.pushButton_search.setEnabled(False)
        self.pushButton_search.clicked.connect(self.search)
        self.pushButton_del.setStyleSheet(Fuc.button_style)
        self.pushButton_checkout.setStyleSheet(Fuc.button_style)
        self.pushButton_checkout.clicked.connect(self.checkoutCard)
        self.pushButton_del.clicked.connect(self.delItem)

    def load(self):
        """
        载入商品
        :return: None
        """
        self.load_dct = Fuc.loadTxt()  # 载入商品信息
        items = [key + "  " + str(value[0]) + "元" for key, value in self.load_dct.items()]  # 格式设置
        self.pushButton_load.setEnabled(False)  # 设置 [载入商品]不可选
        self.listWidget.addItems(items)  # 商品框载入商品条目信息
        self.pushButton_card.setEnabled(True)  # 设置 [查询余额]可选

    def card(self):
        """
        插入购物卡
        :return: None
        """
        self.pushButton_card.setEnabled(False)  # 设置 [插入购物卡]不可选
        self.pushButton_search.setEnabled(True)  # 设置 [查询余额] 可选
        QMessageBox.information(None, "提示", "购物卡加载成功")
        self.cardLoad = 1  # 判断购物卡是否已经插入

    def search(self):
        """
        查询余额
        :return:None
        """
        pwd = Fuc.searchMoneyTxt()  # 获取购物卡密码
        text = QInputDialog.getText(self, "输入密码", "请输入密码", QLineEdit.Normal)[0]  # 弹出密码输入框
        if text == pwd[1]:  # 判断密码是否正确
            s = "余额:" + str(pwd[0])
            QMessageBox.information(None, "提示", s)
        else:
            QMessageBox.warning(None, "警告", "密码错误")

    def shop(self):
        """
        购入
        :return: None
        """
        item_text = self.listWidget.currentItem().text()  # 读取选中的商品
        self.listWidget_2.addItem(item_text)  # 添加至购物框

    def checkoutCard(self):
        """
        结算
        :return:
        """
        if self.cardLoad == 0:  # 判断购物卡是否插入
            QMessageBox.warning(None, "警告", "请插入信用卡")
        else:
            items = [self.listWidget_2.item(i).text() for i in range(self.listWidget_2.count())]  # 读取购物框商品
            # itmes --> ['PEPSI百事可乐  10元', 'PEPSI百事可乐  10元']
            print(items)
            num = 0
            for item in items:
                num += int(item[-3:-1])  # 计算总额

            money = int(Fuc.searchMoneyTxt()[0])  # 读取余额
            if num > money:  # 判断余额是否充足
                QMessageBox.warning(None, "警告", "余额不足")
            else:
                end = money - num
                s = f"购买成功,已经扣除{num}元"
                Fuc.writeMoneyTxt(end)  # 写入结算后余额
                Fuc.saveLoadTxt(items)  # 修改商品剩余数量
                QMessageBox.information(None, "提示", s)
                self.listWidget_2.clear()  # 清除购物框内容

    def delItem(self):
        """
        删除
        :return:None
        """
        selected_index = self.listWidget_2.currentRow()  # 获取当前项的位置
        self.listWidget_2.takeItem(selected_index)  # 删除当前项


if __name__ == '__main__':
    app = QApplication(argv)
    MainWindow = MainWin()
    MainWindow.show()
    exit(app.exec_())

Fuc.py

button_style = 'QPushButton{' \
               'font: 10pt "微软雅黑";' \
               'color: #2f3640;' \
               'background-color: #f5f6fa;' \
               'border-color: #2f3640;' \
               'border-radius: 15px;' \
               'border-style: solid;' \
               'border-width: 2px;' \
               'padding: 5px;}' \
               'QPushButton:hover{' \
               'color: #FFFFFF;' \
               'background-color: #718093;' \
               'border-color: #2f3640;}' \
               'QPushButton:pressed,checked{' \
               'color: #FFFFFF;' \
               'background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #273c75, stop:1 #487eb0);}' \
               'QPushButton:disabled{' \
               'color: #FFFFFF;' \
               'background-color: #dcdde1;' \
               'border-color: #dcdde1;}'
title_style = 'font-family: 等线;font-weight:400;font-size:48px;line-height:14px;text-align:center;color:rgb(0, 0, 84);'
label_style = 'font-family: 等线;font-weight:10;font-size:16px;line-height:14px;text-align:center;color:rgb(0, 0, 84);'


def loadTxt():
    """
    载入本地load.txt文件
    :return: 字典 --> 商品名:[价钱,数量]
    """
    with open("load.txt", 'r', encoding='utf-8') as f:
        lst = f.read().split("\n")  # 读取本地load.txt内容
    dct = {}
    for i in lst[:-1]:  # 解析重组数据
        name, money, num = i.split(",")
        if int(num) != 0:  # 剔除卖完的饮品
            dct[name] = [int(money), int(num)]  # 重组后数据格式: {name:[money,num]}
    return dct


def writeMoneyTxt(money):
    """
    修改信用卡余额
    :param money: 余额
    :return:None
    """
    with open("money.txt", 'w', encoding='utf-8') as f:
        f.write(str(money) + ",123123")


def saveLoadTxt(names):
    """
    修改商品数量
    :param names: 购物的商品名称[list]  示例:['PEPSI百事可乐  10元', '椰树COCONUTPALM  10元']
    :return:None
    """
    dct = loadTxt()  # 读取本地文件 [返回字典]
    for name in names:  # 遍历输入的列表
        newName = name.split("  ")[0]  # 重组数据
        dct[newName][-1] -= 1  # 修改对应数量
    txt = ""
    for key, value in dct.items():
        txt += f"{key},{value[0]},{value[1]}\n"  # 重组内容
    with open("load.txt", 'w', encoding="utf-8") as f:
        f.write(txt)  # 覆写load.txt文件


def searchMoneyTxt():
    """
    查询余额
    :return: 余额 (int)
    """
    with open("money.txt", 'r') as f:
        return f.read().split(",")

ui.py

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

# Form implementation generated from reading ui file 'ui.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# 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, QtWidgets
from PyQt5.QtGui import QIcon


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(328, 488)
        self.frame = QtWidgets.QFrame(Form)
        Form.setWindowIcon(QIcon("shop.ico"))
        self.frame.setGeometry(QtCore.QRect(90, 10, 131, 51))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.label = QtWidgets.QLabel(self.frame)
        self.label.setGeometry(QtCore.QRect(0, 0, 151, 51))
        self.label.setStyleSheet("font-family: 等线;font-weight:10;font-size:25px;line-height:14px;text-align:center;color:rgb(0, 0, 84);")
        self.label.setObjectName("label")
        self.pushButton_card = QtWidgets.QPushButton(Form)
        self.pushButton_card.setGeometry(QtCore.QRect(240, 212, 81, 31))
        self.pushButton_card.setObjectName("pushButton_card")
        self.listWidget = QtWidgets.QListWidget(Form)
        self.listWidget.setGeometry(QtCore.QRect(10, 70, 221, 221))
        self.listWidget.setObjectName("listWidget")
        self.pushButton_load = QtWidgets.QPushButton(Form)
        self.pushButton_load.setGeometry(QtCore.QRect(240, 72, 81, 31))
        self.pushButton_load.setObjectName("pushButton_load")
        self.pushButton_shop = QtWidgets.QPushButton(Form)
        self.pushButton_shop.setGeometry(QtCore.QRect(240, 120, 81, 31))
        self.pushButton_shop.setObjectName("pushButton_shop")
        self.listWidget_2 = QtWidgets.QListWidget(Form)
        self.listWidget_2.setGeometry(QtCore.QRect(10, 310, 311, 111))
        self.listWidget_2.setObjectName("listWidget_2")
        self.pushButton_search = QtWidgets.QPushButton(Form)
        self.pushButton_search.setGeometry(QtCore.QRect(240, 260, 81, 31))
        self.pushButton_search.setObjectName("pushButton_search")
        self.pushButton_del = QtWidgets.QPushButton(Form)
        self.pushButton_del.setGeometry(QtCore.QRect(10, 430, 75, 31))
        self.pushButton_del.setObjectName("pushButton_del")
        self.pushButton_checkout = QtWidgets.QPushButton(Form)
        self.pushButton_checkout.setGeometry(QtCore.QRect(110, 430, 75, 31))
        self.pushButton_checkout.setObjectName("pushButton_checkout")

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "自动售卖机"))
        self.label.setText(_translate("Form", "自动售卖机"))
        self.pushButton_card.setText(_translate("Form", "插入购物卡"))
        self.pushButton_load.setText(_translate("Form", "载入商品"))
        self.pushButton_shop.setText(_translate("Form", "购入"))
        self.pushButton_search.setText(_translate("Form", "查询余额"))
        self.pushButton_del.setText(_translate("Form", "删除"))
        self.pushButton_checkout.setText(_translate("Form", "结算"))

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于PyQt5实现简易饮品自动售货机 的相关文章

随机推荐

  • Visual Studio 2015 Tools for Unity与VS2015的bug

    之前使用Unity4 X配合的是Visual Studio 2013 Tools与VS2013的时候 是可以打开项目属性的 更换了Unity5 x配合Visual Studio 2015 Tools for Unity与VS2015的时候
  • 基于springboot开发的学生考勤管理系统【毕业论文,源码】

    基于springboot开发的学生考勤管理系统 如需更多资料请前往文章底部获取联系方式 系统设计主要功能 通过市场调研及咨询研究 了解了学生考勤管理系统及管理者的使用需求 于是制定了管理员 教师和学生等模块 功能结构图如下所示 E R图 考
  • 原子操作 CAS

    参考 https zhuanlan zhihu com p 400817892 https www bilibili com read cv10686883 https blog csdn net www dong article deta
  • nacos默认用户名密码_Nacos 权限控制介绍及实战

    转自 阿里巴巴中间件 作者 朱鹏飞 Nacos权限控制设计方案 方案背景 Nacos 自开源依赖 权限控制一直需求比较强烈 这也反应了用户需求将 Nacos 部署到生产环境的需求 最新发布的 Nacos 1 2 0版本已经支持了服务发现和配
  • 文件夹选择对话框 JS实现的两种方案

    文件夹选择对话框 JS实现的两种方案 browseFolder js 该文件定义了BrowseFolder 函数 它将提供一个文件夹选择对话框 以供用户实现对系统文件夹选择的功能
  • 监听器,过滤器,拦截器

    参考博文 文章目录 作用 三者区别 启动顺序 拦截器 简要说明 实现接口 HandlerInterceptor 自定义拦截器 配置拦截器 过滤器 简要说明 在springboot 启动类添加该注解 ServletComponentScan
  • 在word如何显示左侧的索引目录

    https jingyan baidu com article 2c8c281df82bd80008252a23 html
  • 自动控制原理知识点梳理——6.线性系统的校正方法

    主要内容是书上6 1 6 2 6 3 目录 一 系统的设计与校正问题 1 控制系统的性能指标 2 系统带宽的选择 3 校正方法 4 基本控制规律 1 比例 P 控制规律 2 比例 微分 PD 控制规律 3 积分 I 控制规律 4 比例 积分
  • osgEarth的Rex引擎原理分析(六十)TileNode与DrawTileCommand的关系

    目标 五十五 中的问题131 TileNode与DrawTileCommand的关系 DrawTileCommad的几何图形和瓦片编号从TileNode来 最终绘制是用DrawTileCommand的draw函数来实现的 DrawTileC
  • 服务器显示post是什么意思,post请求 post请求是什么

    在HTTP协议的请求类型中 post请求是一个比较常见的请求类型 也是一个使用比较频繁的请求 那么这一个请求到底是什么意思呢 这就是今天我们所要了解的内容 快来一起看一看吧 post请求 post请求的含义 向指定资源提交数据进行处理请求
  • Golang Channel通道使用简介

    Golang Channel通道使用简介 一 channel简介 chan 是 Golang 中内置的数据类型 不像 Mutex 等需要引入 它是 first class 类型 在 Go 的并发控制中起着相当重要的作用 chan 的思想来自
  • CWnd指针和HWnd

    HWND是Windows系统中对所有窗口的一种标识 即窗口句柄 这是一个SDK概念 CWnd是MFC类库中所有窗口类的基类 微软在MFC中将所有窗口的通用操作都封装到了这个类中 如 ShowWindow等等 同时它也封装了窗口句柄即m hW
  • linux下编译dbus源码,ubuntu安装dbus

    下载地址 编译安装 configure prefix home ubuntu dbus 1 13 18 install make make install 出现如下错误 configure error The pkg config scri
  • qt Graphic View 学习

    是一种基于图形项的 Graphic Item 模型 视图模式 由场景 视图 图形项组成 1 场景 QGraphicScence类 场景不可见 是管理图像项的容器 场景坐标 等价于Qpainter的逻辑坐标 窗口坐标 setwindow 一般
  • 查询及删除重复记录

    查询及删除重复记录的方法大全 1 查找表中多余的重复记录 重复记录是根据单个字段 peopleId 来判断select from peoplewhere peopleId in select peopleId from people gro
  • Notepad++ 代码格式化

    在阅读别人的代码时偶尔会遇到格式很乱 阅读起来很费劲的情况 若手动改 很容易出错且很费时间 这时可以借助一些专业的编辑器来格式化代码 NotePad 是一个轻量级的代码编辑器 占用内存少 运行速度快 但是Notepad 本身是不带这个格式化
  • Unity基础(06)—— 动画(Animation)的录制与播放

    一 录制动画 将物体移动 操作的过程录制下来保存到一个物理文件 在下次使用的时候直接用代码来调用它即可 如让物体TheCh1 绕Y轴转动90度的动画录制 1 在Unity中打开动画视图 2 选择指定物体 为其添加 Animation 组件
  • python3GUI--PyQt5打包心得(详细图文演示)

    文章目录 一 前言 二 准备工作 介绍 1 准备 2 介绍 1 pyinstaller 2 pipenv 三 项目打包 1 准备 2 打包 1 打包参数 2 虚拟环境 三 总结 一 前言 有朋友私信问我 如何把项目打包和如何减小打包后的文件
  • Handsontable 的数据保存(增删改查+导出excel)

    项目用到handsontable 插件 根据官网 API写的handsontable初始化 数据展示 ajax请求 参数封装 Controller参数接受 全局容器 var AllData var updatelist var delids
  • 基于PyQt5实现简易饮品自动售货机

    记录一个最近Python课程的作业 编写一个简易的饮品自动售货机 购物者选择需要的饮品 通过使用购物卡的方式支付 支付成功后从出货口取出饮品 使用环境 Python3 8 6 PyQt5 5 15 4 搭建的界面GUI 使用的核心代码解析