用 Python 開發(fā)名片管理系統(tǒng)

簡(jiǎn)介

這是一個(gè)用 Python 開發(fā)的可視化的名片管理系統(tǒng),主要實(shí)現(xiàn)名片的添加、刪除、修改三大功能。效果圖如下所示


首頁(yè)
添加頁(yè)面

思路分析

界面實(shí)現(xiàn):使用 Tkinter 庫(kù)進(jìn)行 GUI 界面設(shè)計(jì)開發(fā)。tkinter 是 python 內(nèi)置的一套用于開發(fā) GUI 程序的包。

數(shù)據(jù)存儲(chǔ):1.0版本的數(shù)據(jù)在內(nèi)存中以列表形式存儲(chǔ),序列化到本地時(shí)使用文件存儲(chǔ)方案

# 所有數(shù)據(jù)集合
self.all_items = []

代碼結(jié)構(gòu):項(xiàng)目有三個(gè)窗口,分別是主界面、添加界面,修改界面,每一個(gè)界面使用一個(gè)類進(jìn)行組織,并提供一個(gè) show 方法,用于顯示窗口,因?yàn)樘砑雍托薷慕缑婵梢怨?,所以只需定義兩個(gè)界面類即可。

  • 主界面:MainFrame
  • 添加/修改界面:InputFrame
    代碼結(jié)構(gòu)如下所示


    類結(jié)構(gòu)

    程序啟動(dòng)時(shí),新建主界面的實(shí)例對(duì)象,然后調(diào)用 show 方法即可運(yùn)行程序。


    image.png

開發(fā)環(huán)境

  • 開發(fā)工具:Pycharm
  • 輔助包:tkinter

代碼實(shí)現(xiàn)

from tkinter import *
from tkinter import messagebox

# 定義一個(gè)主窗口界面類,其父類為 object
class MainFrame(object):
    # 初始化主窗口
    def __init__(self):
        # 初始化所有數(shù)據(jù)集合列表
        self.all_items = []
        # 使用Tk()函數(shù)創(chuàng)建頂級(jí)窗口(主窗口)
        self.root = Tk()
        # 窗口自定義名稱為“名片管理系統(tǒng)”
        self.root.title("名片管理系統(tǒng)")
        # 設(shè)置主窗口大小
        self.root.wm_minsize(width=400, height=300)

    # 定義 show 方法:顯示主窗口布局
    def show(self):
        # 顯示頂部區(qū)域信息
        self.addTopFrame()
        # 初始化信息列表區(qū)域
        self.initContent()
        # 從本地文件加載以存儲(chǔ)的信息
        self.loadData()
        # 顯示出所有的名片信息
        self.showAllItem()
        # 開啟主界面,進(jìn)入主循環(huán)
        self.root.mainloop()

    # 定義 showAllItem 方法,顯示所有列表信息
    def showAllItem(self):
        # 遍歷循環(huán)所有的列表信息
        for data in self.all_items:
            # 添加信息到列表界面
            self.showItem(data)

    # 定義 save_2_file 方法,將已經(jīng)添加的名片信息存儲(chǔ)到本地文件中
    def save_2_file(self):
        # 打開文件
        f = open("contacts.data", "w")
        # 將已經(jīng)添加的信息以字符串形式寫入次文件
        f.write(str(self.all_items))
        # 關(guān)閉文件
        f.close()

    # 定義一個(gè)loadData方法,加載本地存儲(chǔ)文件中的所有數(shù)據(jù)
    def loadData(self):
        # 通過"try...except"異常點(diǎn)檢驗(yàn)方法,檢查存儲(chǔ)名片信息的本地文件的存在性
        try:
            # 打開存儲(chǔ)名片信息的本地文件
            f = open("contacts.data")
            # 讀取本地文件中的所有數(shù)據(jù)
            self.all_items = eval(f.read())
            """eval 相關(guān)知識(shí)點(diǎn)以及用法
            功能:將字符串str當(dāng)成有效的表達(dá)式來求值并返回計(jì)算結(jié)果。
          語(yǔ)法: eval(source[, globals[, locals]]) -> value
            參數(shù):source:一個(gè)Python表達(dá)式或函數(shù)compile()返回的代碼對(duì)象
                  globals:可選。必須是dictionary
                  locals:可選。任意map對(duì)象"""
            f.close()
        except Exception:
            pass

    # 添加主窗口布局需要的控件
    def addTopFrame(self):
        # 添加一個(gè)框架將首頁(yè)的題目和添加按鈕都放在一起
        topFrame = Frame(self.root)
        # 在次框架中添加一個(gè)標(biāo)簽,其題目:名片信息
        titlelable = Label(topFrame, text="名片信息")
        # 顯示框架,并設(shè)定向左排列,x和y軸的寬度均為5個(gè)像素
        titlelable.pack(side=LEFT, padx=5, pady=6)

        # 定義一個(gè)添加按鈕,其中command點(diǎn)擊事件通過lambda函數(shù)實(shí)現(xiàn):調(diào)用showInputFrame
        addButton = Button(topFrame, text="添加", command=lambda : self.showInputFrame("添加",None))
        # 顯示按鈕,并設(shè)定向左排列,x和y軸的寬度均為默認(rèn)像素
        addButton.pack(side=RIGHT)

        # 設(shè)置此框架的背景顏色為藍(lán)色
        topFrame.config(bg="#3f51b5")
        # 橫向填充
        topFrame.pack(fill=X)

    # 顯示添加頁(yè)面
    def showInputFrame(self,title,dict):
        # 定義 inputFrame 實(shí)例,即創(chuàng)建一個(gè)添加界面
        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):
        # 獲取原始數(shù)據(jù)列表的索引
        index = self.all_items.index(origin_data)
        # 將需要修改的內(nèi)容從數(shù)據(jù)列表中移除
        self.all_items.remove(origin_data)
        # 添加修改后的名片信息到數(shù)據(jù)列表
        self.all_items.insert(index,new_data)
        # 將修改后的信息保存到本地文件夾
        self.save_2_file()

        # 為了讓修改后的信息整體生效,先將主界面上的所有信息都刪除
        self.remove_allItem()
        # 然后在主界面上重新顯示所有信息
        self.showAllItem()

    # 清空主界面上的每一行數(shù)據(jù):
    def remove_allItem(self):
        # 通過for循環(huán)將主界面上的名片信息都逐一刪除
        for child_item in self.item_container.winfo_children():
            child_item.destroy()

    # 在主界面上顯示一行信息
    def showItem(self, dict):
        # 初始化主框架
        item_frame = Frame(self.item_container)

        # 添加姓名信息標(biāo)簽
        name_label = Label(item_frame, text=dict['name'])
        name_label.pack(side=LEFT, padx=5, pady=5)

        # 添加性別信息標(biāo)簽
        sex_label = Label(item_frame, text=dict['sex'])
        sex_label.pack(side=LEFT)

        # 添加手機(jī)號(hào)信息標(biāo)簽
        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)

        # 將整個(gè)框架整體封裝
        item_frame.pack()

    # 刪除信息
    def delete_item(self, data,item_frame):
        # 從數(shù)據(jù)列表中刪除數(shù)據(jù)
        self.all_items.remove(data)
        # 將刪除后的信息存儲(chǔ)到本地文件
        self.save_2_file()
        # 在主界面中將刪除的這條信息移除
        item_frame.pack_forget()


# 定義了一個(gè)添加界面類,其父類為 object
class InputFrame(object):
    def __init__(self, mainFrame,title,dict):
        self.mainFrame = mainFrame
        self.data = dict
        # 初始化添加窗口
        self.inputRootFrame = Tk()
        # 設(shè)置這一窗口的題目
        self.inputRootFrame.title(title)
        # 設(shè)置窗口大小
        self.inputRootFrame.wm_minsize(width=200, height=250)


    def show(self):
        # 添加界面的展示信息
        self.addInputFrame()
        # 由于添加和編輯用了同一個(gè)界面,所以根據(jù)界面不同,按鈕的文本需要改變
        if self.data == None:
            self.addButtonFrame('保存')
        else:
            self.addButtonFrame('確定修改')

        self.inputRootFrame.mainloop()

    # 添加界面布局信息展示
    def addInputFrame(self):
        # 初始化姓名框架以及界面
        fmname = Frame(self.inputRootFrame)
        # 添加姓名標(biāo)簽
        self.namelable = Label(fmname, text="姓名:")
        # 設(shè)置姓名標(biāo)簽的位置以及大小
        self.namelable.pack(side=LEFT, padx=5, pady=10)
        # 添加姓名輸入框
        self.nameInput = Entry(fmname, width=50, textvariable=StringVar())
        # 設(shè)置姓名輸入框的位置
        self.nameInput.pack(side=LEFT)
        # 將以前的姓名自動(dòng)填寫進(jìn)來,便于用戶核對(duì)方便修改
        if self.data != None:
            self.nameInput.insert(0, self.data['name'])
            self.nameInput['state'] = DISABLED
        fmname.pack()

        # 初始化性別框架以及信息
        fmSex = Frame(self.inputRootFrame)
        # 添加性別標(biāo)簽
        self.sexlable = Label(fmSex, text="性別:")
        # 設(shè)置性別標(biāo)簽的位置
        self.sexlable.pack(side=LEFT, padx=5, pady=10)

        # 添加性別輸入框
        self.sexInput = Entry(fmSex, width=50, textvariable=StringVar())
        # 設(shè)置性別輸入框的位置
        self.sexInput.pack(side=LEFT)
        # 將以前的性別自動(dòng)填寫進(jìn)來,便于用戶核對(duì)方便修改
        if self.data != None:
            self.sexInput.insert(0, self.data['sex'])
        fmSex.pack()

        # 初始化手機(jī)號(hào)的框架以及顯示內(nèi)容
        fmMob = Frame(self.inputRootFrame)
        # 添加手機(jī)號(hào)標(biāo)簽
        moblelable = Label(fmMob, text="手機(jī)號(hào):")
        # 設(shè)置手機(jī)號(hào)標(biāo)簽的位置
        moblelable.pack(side=LEFT, padx=5, pady=10)
        # 添加手機(jī)號(hào)輸入框
        self.mobleInput = Entry(fmMob, width=50, textvariable=StringVar())
        # 設(shè)置手機(jī)號(hào)輸入框的位置
        self.mobleInput.pack(side=LEFT)
        # 將以前的手機(jī)號(hào)自動(dòng)填寫進(jìn)來,便于用戶核對(duì)方便修改
        if self.data != None:
            self.mobleInput.insert(0, self.data['mobile'])
        fmMob.pack()

    # 添加界面的按鈕設(shè)置
    def addButtonFrame(self,title):
        # 初始化框架
        fmButton = Frame(self.inputRootFrame)
        # 設(shè)置框架位置
        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)

    # 名片信息存儲(chǔ)
    def saveInput(self):
        # 獲取輸入的姓名
        name = self.nameInput.get()
        # 獲取輸入的性別
        sex = self.sexInput.get()
        # 獲取輸入的手機(jī)號(hào)
        mobile = self.mobleInput.get()

        # 確保輸入的姓名不為空
        if name == None or name == '':
            messagebox.showinfo("提示","請(qǐng)輸入姓名!")
            return
        # 確保輸入的性別不為空
        if sex == None or sex == '':
            messagebox.showinfo("提示","請(qǐng)輸入性別!")
            return
        # 確保輸入的性別為“男” 或者 “女”
        if sex != '男' and sex != '女':
            messagebox.showinfo("提示","請(qǐng)選擇男或者女!")
            return

        # 確保輸入的手機(jī)號(hào)不為空
        if mobile == None or mobile == '':
            messagebox.showinfo("提示","請(qǐng)輸入手機(jī)號(hào)!")
            return

        # 將輸入的整條名片信息以字典的形式存儲(chǔ)
        info = {'name': name, 'sex': sex, 'mobile': mobile}
        # 如果在添加頁(yè)面添加數(shù)據(jù)成功后,就把數(shù)據(jù)更新到主界面
        if self.data == None:
            self.mainFrame.addItem(info)
        else:
            self.mainFrame.updateItem(self.data,info)
        # 返回主界面
        self.inputRootFrame.destroy()

    # 點(diǎn)擊修改頁(yè)面上的“取消”按鈕,就返回到主界面上
    def cancelInput(self):
        self.inputRootFrame.destroy()


# 程序入口
if __name__ == '__main__':
    # 創(chuàng)建一個(gè) main frame 對(duì)象,即創(chuàng)建一個(gè)主窗口實(shí)例
    mainFrame = MainFrame()
    # 調(diào)用主窗口的show()方法顯示主窗口
    mainFrame.show()

總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容