计划
在疫情期间,各个小区居民发挥互助精神,进行物品交换,互通有无。编写一个物品交换软件
我的计划是先完成框架设计,再实现存储物品的功能,再完成GUI,之后进行调试和优化
开发
分析需求
该程序允许添加物品的信息,删除物品的信息,显示物品列表,也允许查找物品的信息
具体设计
本项目使用的编程语言是python3.7,共包含main.py 、settings.py 、stock.py、 frame.py、四个python文件和一个item1.xlsx excel文件
main.py的功能是打开主窗口,settings.py包含对文字大小、窗口大小、标签内容等的设置,stock.py包含Stock类,可以实现物品的增加、减少、检索、遍历,也可以将修改过的数据更新到excel文件中。 frame.py实现GUI
excel文件存储数据,如果在程序运行的时候选择过保存数据,再次打开程序时,数据不会丢失
具体代码
main.py点击查看代码
import warnings
import tkinter as tk
from frame import MyFrame
#物品交换
def exchange_start():
#打开主窗口
init_window = tk.Tk()
window = MyFrame(init_window)
window.set_init_window()
init_window.mainloop()
if __name__ == '__main__':
warnings.filterwarnings("ignore")
exchange_start()
settings.py点击查看代码
#设置
class Settings:
def __init__(self):
#窗口设置#
self.geometry = '1068x681+10+10'
self.bg_color = (230, 230, 230)
self.window_name = 'exchange platform'
self.small_geometry = '600x400'
#标签设置
self.welcome_text = 'Welcome to Goods Exchange Platform'
self.welcome_text_font = ('Times', 30, 'bold italic')
self.botton_text_font = ('Times', 20, 'bold')
self.item_label = 'item:'
self.amount_label = 'amount:'
#表格设置
self.filename = 'data/item1.xlsx'
stock.py点击查看代码
#存储物品
from settings import Settings
import pandas as pd
class Stock:
#初始化
def __init__(self):
self.settings = Settings()
self.data = pd.read_excel(self.settings.filename)
self.lenth = len(self.data)
#更新数据,移除数量为0的物品
def update(self):
self.data = self.data.drop(self.data[self.data['amount'] == 0].index)
#将数据保存到excel文件
def save_data(self):
self.data.to_excel(self.settings.filename, sheet_name='Sheet1', index=False)
#增加物品
def add_item(self, name, amount):
if name in self.data['item'].values: #检查物品是否存在
self.data['amount'][self.data['item'] == name] += amount #增加相应数量
else:
self.data.loc[self.lenth] = [name, amount] #创建新物品
self.lenth += 1
self.update()
#取出物品,并返回是否成功
def withdraw_item(self, name, amount):
if name in self.data['item'].values: #检查物品是否存在
if int(self.data['amount'][self.data['item'] == name]) >= int(amount): #检查数量是否足够
self.data['amount'][self.data['item'] == name] = int(self.data['amount'][self.data['item'] == name]) #更改数据类型
self.data['amount'][self.data['item'] == name] -= int(amount) #减少相应数量
self.update()
return True
return False
#查找物品,返回物品数量
def search_item(self, name):
if name in self.data['item'].values: #检查物品是否存在
return int(self.data['amount'][self.data['item'] == name])
else:
return 0
#返回所有物品信息
def get_data(self):
return self.data
frame.py点击查看代码
#可视化窗口
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from settings import Settings
from stock import Stock
class MyFrame:
#初始化
def __init__(self, init_window):
self.settings = Settings()
self.init_window = init_window
self.data_stock = Stock()
#设置主窗口
def set_init_window (self):
#设置窗口标题、大小、颜色、标签
self.init_window.title(self.settings.window_name)
self.init_window.geometry(self.settings.geometry)
self.init_window.bg_color = self.settings.bg_color
text = tk.Label(self.init_window, text=self.settings.welcome_text, font=self.settings.welcome_text_font)
text.pack()
#设置增加物品、取出物品、查找物品、查看所有物品、保存修改五个按键
button_add = tk.Button(self.init_window, text='Add Items', font=self.settings.botton_text_font,
command=self.click_button_add).pack()
button_withdraw = tk.Button(self.init_window, text='Withdraw Items', font=self.settings.botton_text_font,
command=self.click_button_withdraw).pack()
button_search = tk.Button(self.init_window, text='Search Items', font=self.settings.botton_text_font,
command=self.click_button_search).pack()
button_view_all = tk.Button(self.init_window, text='View All', font=self.settings.botton_text_font,
command=self.click_button_view).pack()
button_save = tk.Button(self.init_window, text='Save', font=self.settings.botton_text_font,
command=self.click_button_save).pack()
#增加物品事件
def click_button_add(self):
#执行增加物品并关闭窗口
def add_item(name, amount, window):
self.data_stock.add_item(name, amount)
messagebox.showinfo(message=f"you have added {amount} {name}")
window.destroy()
#新窗口设置
add_window = tk.Toplevel()
add_window.title("Add Items")
add_window.geometry(self.settings.small_geometry)
#创建物品名称、物品数量的输入框和其标签
label1 = tk.Label(add_window, text=self.settings.item_label).pack()
entry1 = tk.Entry(add_window)
entry1.pack()
label2 = tk.Label(add_window, text=self.settings.amount_label).pack()
entry2 = tk.Entry(add_window)
entry2.pack()
#设置OK按键
button_ok = tk.Button(add_window, text='OK', command=lambda:add_item(entry1.get(), entry2.get(), add_window))
button_ok.pack()
#打开窗口
add_window.mainloop()
#取出物品事件
def click_button_withdraw(self):
#执行取出物品并关闭窗口
def withdraw_item(name, amount, window):
flag = self.data_stock.withdraw_item(name, amount)
if flag:
messagebox.showinfo(message=f"You have withdrawn {amount} {name}")
else:
messagebox.showwarning(message=f"Sorry, the {name} is not enough")
window.destroy()
#设置新窗口
withdraw_window = tk.Toplevel()
withdraw_window.title('Withdraw Items')
withdraw_window.geometry(self.settings.small_geometry)
#创建物品名称、物品数量的输入口及其标签
label1 = tk.Label(withdraw_window, text=self.settings.item_label).pack()
entry1 = tk.Entry(withdraw_window)
entry1.pack()
label2 = tk.Label(withdraw_window, text=self.settings.amount_label).pack()
entry2 = tk.Entry(withdraw_window)
entry2.pack()
#设置OK按键
button_ok = tk.Button(withdraw_window, text='OK', command=lambda: withdraw_item(entry1.get(), entry2.get(),
withdraw_window))
button_ok.pack()
#打开窗口
withdraw_window.mainloop()
#查找物品事件
def click_button_search(self):
#完成信息查找并关闭窗口
def search_item(name, window):
amount = self.data_stock.search_item(name)
if amount > 0:
messagebox.showinfo(message=f'There are {amount} {name}')
else:
messagebox.showinfo(message=f'Sorry, there is no {name}')
window.destroy()
#设置新窗口
search_window = tk.Toplevel()
search_window.title("Search")
search_window.geometry(self.settings.small_geometry)
#设置物品名称的输入框及其标签
label1 = tk.Label(search_window, text=self.settings.item_label).pack()
entry1 = tk.Entry(search_window)
entry1.pack()
#设置OK按键
button_ok = tk.Button(search_window, text='OK',
command=lambda: search_item(entry1.get(), search_window))
button_ok.pack()
#打开窗口
search_window.mainloop()
#查看所有物品事件
def click_button_view(self):
#设置新窗口
view_window = tk.Toplevel()
view_window.title('View All')
view_window.geometry(self.settings.small_geometry)
#将物品信息从dataframe数据转化为treeview数据
cols = list(self.data_stock.get_data())
tree = ttk.Treeview(view_window)
tree.pack()
tree['columns'] = cols
for i in cols:
tree.column(i, anchor='w')
tree.heading(i, text=i, anchor='w')
for index, row in self.data_stock.get_data().iterrows():
tree.insert('', 0, text=index, value=list(row))
#创建滚动轴
scroll_bar = tk.Scrollbar(view_window, orient='vertical', command=tree.yview)
scroll_bar.place(relx=0.971, rely=0.028, relwidth=0.024, relheight=0.958)
tree.configure(yscrollcommand=scroll_bar.set)
#打开窗口
view_window.mainloop()
#保存数据事件
def click_button_save(self):
self.data_stock.save_data()
messagebox.showinfo(message="The changes have been saved")
https://github.com/yyyllljjj/2022-homework-
测试
经过调试,功能基本可以实现,以下是功能的测试的截图
记录用时
过程 | 用时 |
---|---|
确定方案 | 0.5h |
编码 | 3h |
调试 | 6h |
优化 | 1h |
事后总结
预期功能基本可以实现。用时比预期长,因为python库的安装过程出现了一些问题,还有对GUI不太熟练。
改进计划
1.改进排版,使窗口更美观
2.增加更多物品信息,如物主信息、发布时间等
3.实现线上交互
4.增加登录账号的功能