簡介
這是一個用 Python 開發的可視化的名片管理系統,主要實現名片的添加、刪除、修改三大功能。效果圖如下所示
首頁
添加頁面
思路分析
界面實現:使用 Tkinter 庫進行 GUI 界面設計開發。tkinter 是 python 內置的一套用于開發 GUI 程序的包。
數據存儲:1.0版本的數據在內存中以列表形式存儲,序列化到本地時使用文件存儲方案
# 所有數據集合
self.all_items = []
代碼結構:項目有三個窗口,分別是主界面、添加界面,修改界面,每一個界面使用一個類進行組織,并提供一個 show 方法,用于顯示窗口,因為添加和修改界面可以公用,所以只需定義兩個界面類即可。
- 主界面:MainFrame
-
添加/修改界面:InputFrame
代碼結構如下所示
類結構
程序啟動時,新建主界面的實例對象,然后調用 show 方法即可運行程序。
image.png
開發環境
- 開發工具:Pycharm
- 輔助包:tkinter
代碼實現
from tkinter import *
from tkinter import messagebox
# 定義一個主窗口界面類,其父類為 object
class MainFrame(object):
# 初始化主窗口
def __init__(self):
# 初始化所有數據集合列表
self.all_items = []
# 使用Tk()函數創建頂級窗口(主窗口)
self.root = Tk()
# 窗口自定義名稱為“名片管理系統”
self.root.title("名片管理系統")
# 設置主窗口大小
self.root.wm_minsize(width=400, height=300)
# 定義 show 方法:顯示主窗口布局
def show(self):
# 顯示頂部區域信息
self.addTopFrame()
# 初始化信息列表區域
self.initContent()
# 從本地文件加載以存儲的信息
self.loadData()
# 顯示出所有的名片信息
self.showAllItem()
# 開啟主界面,進入主循環
self.root.mainloop()
# 定義 showAllItem 方法,顯示所有列表信息
def showAllItem(self):
# 遍歷循環所有的列表信息
for data in self.all_items:
# 添加信息到列表界面
self.showItem(data)
# 定義 save_2_file 方法,將已經添加的名片信息存儲到本地文件中
def save_2_file(self):
# 打開文件
f = open("contacts.data", "w")
# 將已經添加的信息以字符串形式寫入次文件
f.write(str(self.all_items))
# 關閉文件
f.close()
# 定義一個loadData方法,加載本地存儲文件中的所有數據
def loadData(self):
# 通過"try...except"異常點檢驗方法,檢查存儲名片信息的本地文件的存在性
try:
# 打開存儲名片信息的本地文件
f = open("contacts.data")
# 讀取本地文件中的所有數據
self.all_items = eval(f.read())
"""eval 相關知識點以及用法
功能:將字符串str當成有效的表達式來求值并返回計算結果。
語法: eval(source[, globals[, locals]]) -> value
參數:source:一個Python表達式或函數compile()返回的代碼對象
globals:可選。必須是dictionary
locals:可選。任意map對象"""
f.close()
except Exception:
pass
# 添加主窗口布局需要的控件
def addTopFrame(self):
# 添加一個框架將首頁的題目和添加按鈕都放在一起
topFrame = Frame(self.root)
# 在次框架中添加一個標簽,其題目:名片信息
titlelable = Label(topFrame, text="名片信息")
# 顯示框架,并設定向左排列,x和y軸的寬度均為5個像素
titlelable.pack(side=LEFT, padx=5, pady=6)
# 定義一個添加按鈕,其中command點擊事件通過lambda函數實現:調用showInputFrame
addButton = Button(topFrame, text="添加", command=lambda : self.showInputFrame("添加",None))
# 顯示按鈕,并設定向左排列,x和y軸的寬度均為默認像素
addButton.pack(side=RIGHT)
# 設置此框架的背景顏色為藍色
topFrame.config(bg="#3f51b5")
# 橫向填充
topFrame.pack(fill=X)
# 顯示添加頁面
def showInputFrame(self,title,dict):
# 定義 inputFrame 實例,即創建一個添加界面
self.inputFrame = InputFrame(self,title,dict)
# 顯示添加界面
self.inputFrame.show()
# 顯示列表信息
def initContent(self):
# 初始化列表框架
self.item_container = Frame(self.root)
# 將這一框架整體整合
self.item_container.pack()
# 添加名片信息
def addItem(self, dict):
# 添加新信息到 all_items 列表
self.all_items.append(dict)
# 顯示名片信息
self.showItem(dict)
# 將信息保存到本地文件夾
self.save_2_file()
# 修改信息
def updateItem(self, origin_data,new_data):
# 獲取原始數據列表的索引
index = self.all_items.index(origin_data)
# 將需要修改的內容從數據列表中移除
self.all_items.remove(origin_data)
# 添加修改后的名片信息到數據列表
self.all_items.insert(index,new_data)
# 將修改后的信息保存到本地文件夾
self.save_2_file()
# 為了讓修改后的信息整體生效,先將主界面上的所有信息都刪除
self.remove_allItem()
# 然后在主界面上重新顯示所有信息
self.showAllItem()
# 清空主界面上的每一行數據:
def remove_allItem(self):
# 通過for循環將主界面上的名片信息都逐一刪除
for child_item in self.item_container.winfo_children():
child_item.destroy()
# 在主界面上顯示一行信息
def showItem(self, dict):
# 初始化主框架
item_frame = Frame(self.item_container)
# 添加姓名信息標簽
name_label = Label(item_frame, text=dict['name'])
name_label.pack(side=LEFT, padx=5, pady=5)
# 添加性別信息標簽
sex_label = Label(item_frame, text=dict['sex'])
sex_label.pack(side=LEFT)
# 添加手機號信息標簽
mob_label = Label(item_frame, text=dict['mobile'])
mob_label.pack(side=LEFT)
# 添加刪除按鈕
delete_button = Button(item_frame, text="刪除", command=lambda: self.delete_item(dict,item_frame))
# delete_button = Button(f2, text="刪除", command=lambda dict : self.all_items.remove(dict))
delete_button.pack(side=LEFT)
# 添加修改按鈕
update_button = Button(item_frame, text="修改",command=lambda : self.showInputFrame("修改",dict))
update_button.pack(side=LEFT)
# 將整個框架整體封裝
item_frame.pack()
# 刪除信息
def delete_item(self, data,item_frame):
# 從數據列表中刪除數據
self.all_items.remove(data)
# 將刪除后的信息存儲到本地文件
self.save_2_file()
# 在主界面中將刪除的這條信息移除
item_frame.pack_forget()
# 定義了一個添加界面類,其父類為 object
class InputFrame(object):
def __init__(self, mainFrame,title,dict):
self.mainFrame = mainFrame
self.data = dict
# 初始化添加窗口
self.inputRootFrame = Tk()
# 設置這一窗口的題目
self.inputRootFrame.title(title)
# 設置窗口大小
self.inputRootFrame.wm_minsize(width=200, height=250)
def show(self):
# 添加界面的展示信息
self.addInputFrame()
# 由于添加和編輯用了同一個界面,所以根據界面不同,按鈕的文本需要改變
if self.data == None:
self.addButtonFrame('保存')
else:
self.addButtonFrame('確定修改')
self.inputRootFrame.mainloop()
# 添加界面布局信息展示
def addInputFrame(self):
# 初始化姓名框架以及界面
fmname = Frame(self.inputRootFrame)
# 添加姓名標簽
self.namelable = Label(fmname, text="姓名:")
# 設置姓名標簽的位置以及大小
self.namelable.pack(side=LEFT, padx=5, pady=10)
# 添加姓名輸入框
self.nameInput = Entry(fmname, width=50, textvariable=StringVar())
# 設置姓名輸入框的位置
self.nameInput.pack(side=LEFT)
# 將以前的姓名自動填寫進來,便于用戶核對方便修改
if self.data != None:
self.nameInput.insert(0, self.data['name'])
self.nameInput['state'] = DISABLED
fmname.pack()
# 初始化性別框架以及信息
fmSex = Frame(self.inputRootFrame)
# 添加性別標簽
self.sexlable = Label(fmSex, text="性別:")
# 設置性別標簽的位置
self.sexlable.pack(side=LEFT, padx=5, pady=10)
# 添加性別輸入框
self.sexInput = Entry(fmSex, width=50, textvariable=StringVar())
# 設置性別輸入框的位置
self.sexInput.pack(side=LEFT)
# 將以前的性別自動填寫進來,便于用戶核對方便修改
if self.data != None:
self.sexInput.insert(0, self.data['sex'])
fmSex.pack()
# 初始化手機號的框架以及顯示內容
fmMob = Frame(self.inputRootFrame)
# 添加手機號標簽
moblelable = Label(fmMob, text="手機號:")
# 設置手機號標簽的位置
moblelable.pack(side=LEFT, padx=5, pady=10)
# 添加手機號輸入框
self.mobleInput = Entry(fmMob, width=50, textvariable=StringVar())
# 設置手機號輸入框的位置
self.mobleInput.pack(side=LEFT)
# 將以前的手機號自動填寫進來,便于用戶核對方便修改
if self.data != None:
self.mobleInput.insert(0, self.data['mobile'])
fmMob.pack()
# 添加界面的按鈕設置
def addButtonFrame(self,title):
# 初始化框架
fmButton = Frame(self.inputRootFrame)
# 設置框架位置
fmButton.pack(side=BOTTOM, anchor=W, fill=X)
# 添加保存按鈕
confrmButton = Button(fmButton, text=title, command=self.saveInput)
confrmButton.pack(side=RIGHT, fill=BOTH)
# 添加取消按鈕
cencelButton = Button(fmButton, text="取消", command=self.cancelInput)
cencelButton.pack(side=RIGHT)
# 名片信息存儲
def saveInput(self):
# 獲取輸入的姓名
name = self.nameInput.get()
# 獲取輸入的性別
sex = self.sexInput.get()
# 獲取輸入的手機號
mobile = self.mobleInput.get()
# 確保輸入的姓名不為空
if name == None or name == '':
messagebox.showinfo("提示","請輸入姓名!")
return
# 確保輸入的性別不為空
if sex == None or sex == '':
messagebox.showinfo("提示","請輸入性別!")
return
# 確保輸入的性別為“男” 或者 “女”
if sex != '男' and sex != '女':
messagebox.showinfo("提示","請選擇男或者女!")
return
# 確保輸入的手機號不為空
if mobile == None or mobile == '':
messagebox.showinfo("提示","請輸入手機號!")
return
# 將輸入的整條名片信息以字典的形式存儲
info = {'name': name, 'sex': sex, 'mobile': mobile}
# 如果在添加頁面添加數據成功后,就把數據更新到主界面
if self.data == None:
self.mainFrame.addItem(info)
else:
self.mainFrame.updateItem(self.data,info)
# 返回主界面
self.inputRootFrame.destroy()
# 點擊修改頁面上的“取消”按鈕,就返回到主界面上
def cancelInput(self):
self.inputRootFrame.destroy()
# 程序入口
if __name__ == '__main__':
# 創建一個 main frame 對象,即創建一個主窗口實例
mainFrame = MainFrame()
# 調用主窗口的show()方法顯示主窗口
mainFrame.show()