Python 內建介面開發框架 Tkinter入門篇 丁

ENG八戒發表於2023-02-16

如需要轉載,請宣告原文連結 微信公眾號「ENG八戒」https://mp.weixin.qq.com/s/X5cqennLrq7i1pzBAAqQ2w

本文大概 2562 個字,閱讀需花 15 分鐘
內容不多,但也花了一些精力
如要交流,歡迎關注我然後評論區留言
謝謝你的點贊收藏分享

​這篇文章屬於系列文章《Python 內建介面開發框架 Tkinter入門篇》的第四篇,也是最後一篇,上接《Python 內建介面開發框架 Tkinter入門篇 丙》,歡迎關注我的微信公眾號「ENG八戒」檢視這個系列相關文章,也可以翻到文章底部檢視整個系列的文章集合。

實現一個簡單的記事本應用

前面說了這麼多,用句流行語來概括就是 「散裝知識點」。為了串聯起來有個全面的體會,下面讓我們一起來實現一個簡單的記事本程式吧!

產品定義

作為一個產品的開發來看的話,我們需要清楚地知道自己到底想要的產品是長什麼樣子,然後才是實現的過程。

我們打算做一個基本的記事本,它可以點選按鍵開啟 TXT 格式的文字檔案,把檔案內容讀取出來顯示在編輯區,然後在編輯區修改了檔案內容後,又可以點選其它按鍵把編輯區的內容另存為其它文字檔案。

按照上面的功能需求定義,就可以給記事本定個草圖啦,長這樣

可以看到,它需要先有個主視窗

import tkinter as tk

window = tk.Tk()
window.mainloop()

然後,應該有個標題欄,上面顯示有軟體名稱 「記事本」

import tkinter as tk

window = tk.Tk()
window.title("記事本")
window.mainloop()

從草圖來看,它還需要功能按鈕區域和文字編輯區,可以使用 grid 佈局管理器來劃分割槽域。總體可以劃分為 1 行 2 列,第 1 列是功能按鈕區域,第 2 列是文字編輯區;第 1 行第 1 列也就是功能按鈕區域,又可以劃分為 2 行 1 列,第 1 行是按鈕開啟,第 2 行是按鈕另存。

好了,這就是我們這個產品的初步定義。

UI實現

對介面佈局做好劃分之後,就開始新增控制元件程式碼了

import tkinter as tk

window = tk.Tk()
window.title("記事本")

btn_frame = tk.Frame(
    master=window,
    bd=2
    )
btn_open = tk.Button(
    master=btn_frame,
    text="開啟"
    )
btn_save_as = tk.Button(
    master=btn_frame,
    text="另存"
    )

btn_open.grid(row=0, column=0)
btn_save_as.grid(row=1, column=0)
btn_frame.grid(row=0, column=0)

txt_edit = tk.Text(master=window)
txt_edit.grid(row=0, column=1)

window.mainloop()

顯示是這樣

看起來已經和草圖很接近了,不過按鈕的佈局還是需要調整,位置應該處於所屬列的頂部,而且按鈕太靠邊了。還有,窗體在拉伸之後,控制元件也沒有跟隨變化。這幾個問題怎麼修復呢?

為了將按鈕置頂,可以對控制元件 btn_frame 應用上下拉滿,sticky 設為 "ns"。

而按鈕太靠邊,可以透過修改填充屬性 padding,比如 padx=5, pady=5 讓控制元件的邊框收縮 5 個畫素,保持距離感。

而編輯框控制元件沒有跟隨窗體一起拉伸,是因為控制元件 txt_edit 還需要設定所有邊框靠著邊界,比如 sticky 設為 "nsew" 即可。

看看修改後的程式碼

import tkinter as tk

window = tk.Tk()
window.title("記事本")

window.rowconfigure(
    0,
    minsize=100,
    weight=1
    )
window.columnconfigure(
    1,
    minsize=100,
    weight=1
    )

btn_frame = tk.Frame(
    master=window,
    bd=2
    )
btn_open = tk.Button(
    master=btn_frame,
    text="開啟"
    )
btn_save_as = tk.Button(
    master=btn_frame,
    text="另存"
    )

btn_open.grid(
    row=0,
    column=0,
    sticky="ew",
    padx=5,
    pady=5
    )
btn_save_as.grid(
    row=1,
    column=0,
    sticky="ew",
    padx=5
    )
btn_frame.grid(
    row=0,
    column=0,
    sticky="ns"
    )

txt_edit = tk.Text(master=window)
txt_edit.grid(
    row=0,
    column=1,
    sticky="nsew"
    )

window.mainloop()

跑起來試一下

OK ! UI 介面視覺效果達到預期了。

邏輯功能

下一步就是補充邏輯功能,讓記事本能讀寫文字檔案。

先看怎麼實現開啟邏輯。

理一下思路: 點選按鈕「開啟」,程式就會彈出選取檔案的視窗,選中檔案後點選確定就返回選中的檔案路徑,然後按照檔案路徑把檔案內容讀取出來並且顯示到編輯框中。另外,為了讓使用者知道最終顯示的內容來自哪個檔案,所以可以把檔案路徑新增到視窗的標題欄最前面。看怎麼修改程式碼

...

def open_file():
    file_path = filedialog.askopenfilename(
        filetypes=[
            ("Text files", "*.txt"),
            ("All files", "*.*")
            ]
    )
    if not file_path:
        window.title("無標題 - 記事本")
        return
    window.title(f"{file_path} - 記事本")
    txt_edit.delete("1.0",
                    tk.END)
    with open(
        file_path,
        mode="r",
        encoding="utf-8") as input_file:
        txt_edit.insert(
            tk.END,
            input_file.read()
            )

...

btn_open = tk.Button(
    master=btn_frame,
    text="開啟",
    command=open_file
    )

...

上面程式碼的修改點是新增了一個響應函式 open_file,這個函式用於開啟文字檔案並讀取檔案內容顯示,然後在例項化按鈕控制元件 btn_open 時,把響應函式 open_file 賦值給引數 command 即可。

為了測試記事本的顯示文字內容功能,我們先手動在桌面建立一個文字檔案 test.txt,然後輸入內容並儲存

這是測試文字檔案
...

執行一下程式,然後點選「開啟」按鈕,選中剛剛建立的檔案 test.txt 並開啟

可見讀取文字內容的目標功能基本達成,再看怎麼實現另存邏輯。

理一下思路: 點選按鈕「另存」,程式就會彈出選擇儲存檔案的路徑的視窗,選中路徑後點選確定就返回選中的路徑,然後按照路徑把編輯框中的內容儲存為檔案。另存後,視窗標題欄也需要相應改變。看怎麼修改程式碼

...

def save_as_file():
    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[
            ("Text files", "*.txt"),
            ("All files", "*.*")
            ]
    )
    if not file_path:
        return
    with open(
        file_path,
        mode="w",
        encoding="utf-8") as output_file:
        output_file.write(txt_edit.get("1.0",
                                        tk.END))
    window.title(f"{file_path} - 記事本")

...

btn_save_as = tk.Button(
    master=btn_frame,
    text="另存",
    command=save_as_file
    )

...

上面程式碼的修改點是新增了一個響應函式 save_as_file,這個函式用於選擇另存檔案位置並把編輯框內容寫入指定位置檔案,然後在例項化按鈕控制元件 btn_save_as 時,把響應函式 save_as_file 賦值給引數 command 即可。

為了測試記事本的檔案另存功能,我們先用我們最新修改的記事本程式開啟上面手動建立的文字檔案 test.txt,然後在編輯框把內容修改一下

點選「另存」按鈕,彈出「另存為」檔案視窗,找到儲存位置並輸入新檔名 test_save_as.txt,最後點選「儲存」。

另存完畢後,視窗標題內容變成了新檔案路徑。

好了,一個簡單的記事本程式就這樣完成了。希望上面的內容能開啟你的思路!

打包部署

關於 python 輸出獨立可執行應用的介紹,其實和用什麼 GUI 框架無關,可直接參考一下我的另一篇文章《Python:介面開發,wx入門篇》裡的相關介紹。


由於篇幅受限,系列文章《Python 內建介面開發框架 Tkinter入門篇》分成了下面幾個部分,有興趣的朋友可點選跳轉查閱

《Python 內建介面開發框架 Tkinter入門篇 甲》

《Python 內建介面開發框架 Tkinter入門篇 乙》

《Python 內建介面開發框架 Tkinter入門篇 丙》

《Python 內建介面開發框架 Tkinter入門篇 丁》


如需要完整示例程式碼,可前往 github 倉庫獲取: git@github.com:ifi-leung/python_gui_tkinter.git


這裡預告一下,本公眾號 ENG八戒 的薦書活動馬上來臨,為了鼓勵大家多讀書,所以會有免費送圖書的名額哦!

相關文章