2021年8月30日 星期一

Python 內建 GUI 模組 tkinter 測試 (七) : Entry 元件

今天繼續測試 tkinter 的 Entry 元件, 本系列之前的文章參考 :   

Entry 元件用來輸入單行文字, 亦即換行字元在此元件中是無效的. 其語法如下 :

Entry(父容器, **參數列)   

參考 :


Entry 元件常用參數如下表 : 


 Entry 元件常用屬性 說明
 textvariable 動態綁定文字欄位內容的類別變數物件名稱
 show 輸入資料時顯示的固定字元, 例如用於密碼欄位
 width 寬度 (單位=字元數)
 height 高度 (單位=字元數)
 bg/background 背景色, 可用標準顏色名稱字串例如 'blue' 或 "#0000ff"
 fg/foreground 前景色 (文字顏色), 可用標準顏色名稱字串例如 'blue' 或 "#0000ff"
 font 設定字型與尺寸 (px), 粗體 (bold) 或斜體 (italic), 底線或刪除線等 
 padx 元件與容器的水平間距 (px)
 pady 元件與容器的垂直間距 (px)
 state 設定按鈕狀態=tk.NORMAL (預設可用)/tk.DISABLED (不可用)


對於 Entry 元件而言, 最重要的參數是動態綁定其內容值的 textvariable, 可透過 StringVar, IntVar, DoubleVar, BoolVar 這四種類別變數的 set() 與 get() 來存取其內容. 例如下面這個 tk 的四則運算器範例 : 


測試 1 : 四則運算器 (tk) [看原始碼]

import tkinter as tk
from tkinter import ttk

def add():
    c.set(a.get() + b.get())
def sub():
    c.set(a.get() - b.get())
def mul():
    c.set(a.get() * b.get())
def div():
    if b.get() != 0:                    //取得類別變數 (除數) 之值
        c.set(a.get() / b.get())     //除數不為 0 才除
    else:
        c.set(float("inf"))           //除以 0 顯示為無窮大

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("500x200")
a=tk.DoubleVar()
b=tk.DoubleVar()
c=tk.DoubleVar()
tk.Entry(win, width=10, textvariable=a).grid(row=0, column=0)    //輸入運算元 a
tk.Label(text="+", width=5).grid(row=0, column=1)
tk.Entry(win, width=10, textvariable=b).grid(row=0, column=2)    //輸入運算元 b
tk.Button(win, text="=", width=5, command=add).grid(row=0, column=3)    //加法按鈕
tk.Entry(win, width=10, textvariable=c).grid(row=0, column=4)     //儲存運算結果 c
tk.Label(win, text="-", width=5).grid(row=1, column=1)
tk.Button(win, text="=", width=5, command=sub).grid(row=1, column=3)    //減法按鈕
tk.Label(win, text="*", width=5).grid(row=2, column=1)
tk.Button(win, text="=", width=5, command=mul).grid(row=2, column=3)    //乘法按鈕
tk.Label(win, text="/", width=5).grid(row=3, column=1)
tk.Button(win, text="=", width=5, command=div).grid(row=3, column=3)      //除法按鈕
win.mainloop()

此例定義了 a, b, c 三個 DoubleVar 類別變數分別與三個 Entry 元件綁定, 並使用 grid 排版來放置 Label, Entry, 以及 Button 元件, 當按下 +, -, *, / 相對應的 = 按鈕就會在第三個 Entry 元件上顯示四則運算之值, 其中除法需要特別處理除數為 0 的情況, 結果如下 : 





下面是上例的 ttk 版本, 只是將建立元件的 tk 改成 ttk 而已 : 


測試 2 : 四則運算器 (ttk) [看原始碼]

import tkinter as tk
from tkinter import ttk

def add():
    c.set(a.get() + b.get())
def sub():
    c.set(a.get() - b.get())
def mul():
    c.set(a.get() * b.get())
def div():
    if b.get() != 0:
        c.set(a.get() / b.get())
    else:
        c.set(float("inf"))

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("500x200")
a=tk.DoubleVar()
b=tk.DoubleVar()
c=tk.DoubleVar()
ttk.Entry(win, width=10, textvariable=a).grid(row=0, column=0)
ttk.Label(text="+", width=5).grid(row=0, column=1)
ttk.Entry(win, width=10, textvariable=b).grid(row=0, column=2)
ttk.Button(text="=", width=5, command=add).grid(row=0, column=3)
ttk.Entry(win, width=10, textvariable=c).grid(row=0, column=4)
ttk.Label(text="-", width=5).grid(row=1, column=1)
ttk.Button(text="=", width=5, command=sub).grid(row=1, column=3)
ttk.Label(text="*", width=5).grid(row=2, column=1)
ttk.Button(text="=", width=5, command=mul).grid(row=2, column=3)
ttk.Label(text="/", width=5).grid(row=3, column=1)
ttk.Button(text="=", width=5, command=div).grid(row=3, column=3)
win.mainloop()

結果如下 : 





下面是模擬登入頁面的範例 : 


測試 3 : tk 模擬登入頁面 [看原始碼]

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as msgbox

def clear():
    account.set("")
    pwd.set("")
def login():
    if account.get() == "admin" and pwd.get() == "admin":
        msgbox.showinfo("Info", "登入成功")
    else:
        msgbox.showinfo("Info", "帳號或密碼錯誤")

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("300x150")

account=tk.StringVar()
pwd=tk.StringVar()
tk.Label(win, text="帳號").grid(row=0, column=0)
tk.Entry(win, textvariable=account).grid(row=0, column=1)
tk.Label(win, text="密碼").grid(row=1, column=0)
tk.Entry(win, textvariable=pwd).grid(row=1, column=1)
tk.Button(text="清除", command=clear).grid(row=2, column=0)
tk.Button(text="登入", command=login).grid(row=2, column=1)
win.mainloop()

此例中的兩個 Entry 用來收集使用者輸入之帳號密碼, 用 textvariable 參數分別綁定到 account 與 pwd 這兩個 StringVar 類別變數, 當按下登入鈕時呼叫類別變數的 get() 方法取得輸入值, 經比對帳密都是 admin 就以 messagebox 訊息盒顯示登入成功. 按下清除鈕則呼叫類別變數的 set() 方法將其內容清空, 結果如下 : 




一般來說, 密碼欄位通常會用 * 字元顯示, 這可以透過 show 參數來設定. 另外如登入按鈕所示 grid 版面管理員預設是置中對齊, 這可以用 sticky 參數設為 tk.E, tk.W, tk.S, 或 tk.N 來對齊 (也可以用 + 來複合), 例如 : 


測試 4 : tk 模擬登入頁面 (使用 show 密碼參數) [看原始碼]

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as msgbox

def clear():
    account.set("")
    pwd.set("")
def login():
    if account.get() == "admin" and pwd.get() == "admin":
        msgbox.showinfo("Info", "登入成功")
    else:
        msgbox.showinfo("Info", "帳號或密碼錯誤")

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("300x150")

account=tk.StringVar()
pwd=tk.StringVar()
tk.Label(win, width=5, text="帳號").grid(row=0, column=0)
tk.Entry(win, textvariable=account).grid(row=0, column=1)
tk.Label(win, width=5, text="密碼").grid(row=1, column=0)
tk.Entry(win, show="*", textvariable=pwd).grid(row=1, column=1)
tk.Button(text="清除", command=clear).grid(row=2, column=0, sticky=tk.W)
tk.Button(text="登入", command=login).grid(row=2, column=1, sticky=tk.W)
win.mainloop()

此例將 Label 的寬度設為 5 個字元較能看出按鈕的 sticky 效果, 結果如下 : 




下面是上面範例的 ttk 版本 :


測試 5 : ttk 模擬登入頁面 [看原始碼]

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as msgbox

def clear():
    account.set("")
    pwd.set("")
def login():
    if account.get() == "admin" and pwd.get() == "admin":
        msgbox.showinfo("Info", "登入成功")
    else:
        msgbox.showinfo("Info", "帳號或密碼錯誤")

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("350x150")

account=tk.StringVar()
pwd=tk.StringVar()
ttk.Label(win, text="帳號").grid(row=0, column=0)
ttk.Entry(win, textvariable=account).grid(row=0, column=1)
ttk.Label(win, text="密碼").grid(row=1, column=0)
ttk.Entry(win, show="*", textvariable=pwd).grid(row=1, column=1)
ttk.Button(text="清除", command=clear).grid(row=2, column=0, sticky=tk.W)
ttk.Button(text="登入", command=login).grid(row=2, column=1, sticky=tk.W)
win.mainloop()

由於 ttk 按鈕預設寬度較大, 故視窗寬度放寬為 350px, 結果如下 : 




下面這個範例是做華氏與攝式溫度互轉 :


測試 6 : 華氏與攝氏溫度互轉 [看原始碼]

import tkinter as tk
from tkinter import ttk

def f2c():
    c.set((f.get() - 32) * 5/9)
def c2f():
    f.set(c.get() * 9/5 + 32)

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("500x150")

f=tk.DoubleVar()
c=tk.DoubleVar()
tk.Label(win, text="華氏溫度").grid(row=0, column=0)
tk.Label(win, text="攝氏溫度").grid(row=0, column=2)
tk.Entry(win, textvariable=f).grid(row=1, rowspan=2, column=0)
tk.Button(win, text="=>", command=f2c).grid(row=1, column=1)
tk.Entry(win, textvariable=c).grid(row=1, rowspan=2, column=2)
tk.Button(win, text="<=", command=c2f).grid(row=2, column=1)
win.mainloop()

此例使用兩個 Entry 元件來輸入華氏與攝氏溫度, 他們用 textvariable 參數分別與兩個 DoubleVar 類別變數綁定, 以便能在程式中動態更改其內容. 另外還有兩個用 command 參數指定事件處理函式的方向按鈕用來互轉溫度, 結果如下 : 




下面是計算 BMI 的範例 : 


測試 7 : 計算 BMI (身高體重指數) [看原始碼]

import tkinter as tk
from tkinter import ttk

def calculate_bmi():
    h=float(height.get()) / 100
    w=float(weight.get())
    bmi=w / h ** 2
    if bmi < 18.5:
        comment="體重過輕"
    elif bmi >= 18.5 and bmi < 24:
        comment="體重適當"
    else:
        comment="體重過重"    
    msg=f"BMI 指數={bmi:.2f}, {comment}"
    result.set(msg)

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")                           
win.geometry("350x150")

height=tk.DoubleVar()
weight=tk.DoubleVar()
result=tk.StringVar()
tk.Label(win, text="身高 (公分)").grid(row=0, column=0)
tk.Label(win, text="體重 (公斤)").grid(row=1, column=0)
tk.Entry(win, textvariable=height).grid(row=0, column=1)
tk.Entry(win, textvariable=weight).grid(row=1, column=1)
tk.Button(text="計算 BMI", command=calculate_bmi).grid(row=2, column=1)
tk.Label(win, textvariable=result).grid(row=3, columnspan=2, column=0)
win.mainloop()

此例使用兩個 Entry 元件取得使用者輸入的身高與體重, 分別綁定到 height 與 weight 這兩個 DoubleVar 變數類別物件, 當按下按鈕時呼叫 calculate_bmi() 來計算 BMI 數值並判斷體重是否過重, 最後將結果透過綁定到 Label 元件的 StringVar 變數類別物件動態更新 Label 的內容 :




參考 :


2 則留言 :

東海林將司 提到...

可以在Entry上面顯示預設的字串

result=tk.StringVar(win, value="default text")

小狐狸事務所 提到...

thank you!