首頁 > 軟體

python Tkinter範例詳解

2023-08-28 18:03:34

簡介

  • tkinter

tkinter(Tk interface)是Python的標準GUl庫,支援跨平臺的GUl程式開發。tkinter適合小型的GUl程式編寫,也特別適合初學者學習GUl程式設計。

  • wxPython

wxPython是比較流行的GUI庫,適合大型應用程式開發,功能強於tkinter,整體設計框架類似於MFC(MicrosoftFoundation Classes微軟基礎類庫).

  • PyQT

Qt是一種開源的GUI庫,適合大型GUI程式開發,PyQt是Qt工具包標準的Python實現。我們也可以使用QtDesginer介面設計器快速開發GUl應用程式.

官網

https://docs.python.org/3/library/tkinter.html

建立一個視窗

from tkinter import *

root = Tk()  # 範例化TK

root.mainloop()  # 進入事件迴圈

第一個GUI帶事件的程式

from tkinter import *
from tkinter import messagebox

root = Tk()

bt = Button(root)
bt['text'] = '點我'
bt.pack()
def dianji(e):
    messagebox.showinfo('message', 'give flower')  # 提示框
bt.bind('<Button-1>', dianji)  # 繫結點選事件
root.mainloop()  # 進入事件迴圈

視窗大小和位置

geometry()尺寸

from tkinter import *
from tkinter import messagebox

root = Tk()

root.title('我的gui程式')

root.geometry('500x300+100+200')
# 500寬度  300高度   距螢幕左側100畫素 頂部200畫素

bt = Button(root)
bt['text'] = '點我'
bt.pack()


def dianji(e):
    print(e)
    messagebox.showinfo('message', 'give flower')  # 提示框


bt.bind('<Button-1>', dianji)  # 繫結點選事件
root.mainloop()  # 進入事件迴圈

視窗放至螢幕中間

from tkinter import *

app = Tk()

app.title('拜液使用者管理')

sw = app.winfo_screenwidth()
# 得到螢幕寬度
sh = app.winfo_screenheight()

# 得到螢幕高度
ww = 610
wh = 400

x = (sw - ww) / 2
y = (sh - wh) / 2
app.geometry("%dx%d+%d+%d" % (ww, wh, x, y))


app.resizable(width=False, height=False)
app.mainloop()

常用元件彙總

元件類關係圖

GUI物件導向寫法

通過類 Application 組織整個 GUI 程式,類 Application繼承了 Frame 及通過繼承擁有了父類別的特性。通過建構函式__init__()初始化視窗中的物件,通過 createWidgets()方法建立視窗中的物件。
Frame 框架是一個 tkinter 元件,表示一個矩形的區域。
Frame 一般作為容器使用,可以放置其他元件,從而實現複雜的佈局。

from tkinter import *
from tkinter import messagebox


class Application(Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()

        self.createWidget()

    def createWidget(self):
        # 建立元件
        self.btn01 = Button(self)
        self.btn01['text'] = '點選送花'
        self.btn01.pack()
        self.btn01['command'] = self.songhua
        # 建立一個退出按鈕
        self.btnQuit = Button(self, text='退出', command=root.destroy)
        self.btnQuit.pack()

    def songhua(self):
        messagebox.showinfo('送花', '送你99朵玫瑰花')

root = Tk()
root.geometry('400x100+200+300')
root.title('一個經典的GUI程式類的測試')
app = Application(master=root)

root.mainloop()

簡單元件

  • Label 標籤

Label(標籤)主要用於顯示文字資訊,也可以顯示影象。
Label(標籤)有這樣一些常見屬性:

  • width,height

用於指定區域大小,如果顯示是文字,則以單個英文字元大小為單位(一個漢字寬度佔 2 個字元位置,高度和英文字元一樣);如果顯示是影象,則以畫素為單位。預設值是根據具體顯示的內容動態調整。

  • font

指定字型和字型大小,如:font =(font_name,size)

  • image

顯示在 Label 上的影象,目前 tkinter 只支援 gif 格式。

  • fg 和 bg

fg(foreground):前景色、bg(background):背景色

  • justify

針對多行文字的對齊,可設定 justify 屬性,可選值"left" “center” “right”

【範例】Label(標籤)的用法

from tkinter import *
class Application(Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 建立元件
        self.label01 = Label(self, text='關關雎鳩', width=10, height=2,
                             bg='black', fg='white')
        self.label01.pack()
        self.label02 = Label(self, text='hebut', width=10, height=2,
                             bg='blue', fg='white', font=('黑體', 30))
        self.label02.pack()
        # 顯示影象
        global photo
        # photo = PhotoImage(file='pic01.gif')
        # self.label03 = Label(self, image=photo)
        # self.label03.pack()
        # 顯示多行文字
        self.label04 = Label(self, text='hebutn關關雎鳩', borderwidth=1, relief='groove', justify='right')
        self.label04.pack()

if __name__ == '__main__':
    root = Tk()
    root.geometry('400x500+200+300')
    app = Application(master=root)
    root.mainloop()

Options 選項詳解

通過學習 Label 元件,我們發現可以通過 Options 設定元件的屬性,從而控制元件的各種狀態。比如:寬度、高度、顏色、位置等等。

我們可以通過三種方式設定 Options 選項,這在各種 GUI 元件中用法都一致。

1.建立物件時,使用可變引數

fred = Button(self, fg="red", bg="blue")

2.建立物件後,使用字典索引方式

fred["fg"] = "red"
fred["bg"] = "blue"

3 建立物件後,使用 config()方法

fred.config(fg="red", bg="blue")

如何檢視元件的 Options 選項:
1.可以通過列印 config()方法的返回值,檢視 Options 選項 print(fred.config())
2.通過在 IDE 中,點選元件物件的構造方法,進入到方法內觀察:

上面程式碼中有:“standard options 標準選項”和“widget-specific options 元件特定選項”。我們將常見的選項彙總如下:

Button

Button(按鈕)用來執行使用者的單擊操作。Button 可以包含文字,也可以包含影象。按鈕被單擊後會自動呼叫對應事件繫結的方法。
【範例】Button 按鈕用法(文字、圖片、事件)

#測試Button元件的基本用法,使用物件導向的方式
from tkinter import *
from tkinter import messagebox


class Application(Frame):
    def __init__(self, master=None):  # super()代表的是父類別的
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 建立元件
        self.btn01 = Button(root, text="登入", width=6, height=3, anchor=CENTER, command=self.login)
        self.btn01.pack()

        global photo
        # photo = PhotoImage(file="pic01.gif")
        # self.btn02 = Button(root,image=photo,command=self.login)
        # self.btn02.pack()
        # self.btn02.config(state="disabled")	#設定按鈕為禁用

    def login(self):
        messagebox.showinfo("學習系統", "登入成功!歡迎開始學習!")

if __name__ == '__main__':
    root = Tk()
    root.geometry("400x400+200+300")
    app = Application(master=root)
    root.mainloop()

Entry 單行文字方塊

Entry 用來接收一行字串的控制元件。如果使用者輸入的文字長度長於 Entry 控制元件的寬度時, 文字會自動向後捲動。如果想輸入多行文字, 需要使用 Text 控制元件。
【範例】Entry 單行文字方塊實現簡單登入介面

# 測試 Entry 元件的基本用法,使用物件導向的方式
from tkinter import *
from tkinter import messagebox


class Application(Frame):
    def __init__(self, master=None):  # super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 建立登入介面的元件
        self.label01 = Label(self, text="使用者名稱")
        self.label01.pack()

        # StringVar 變數繫結到指定的元件。
        # StringVar 變數的值發生變化,元件內容也變化;
        # 元件內容發生變化,StringVar 變數的值也發生變化。 v1 = StringVar()
        v1 = StringVar()
        self.entry01 = Entry(self, textvariable=v1)
        self.entry01.pack()
        v1.set("admin")
        print(v1.get())
        print(self.entry01.get())

        # 建立密碼框
        self.label02 = Label(self, text="密碼")
        self.label02.pack()

        v2 = StringVar()
        self.entry02 = Entry(self, textvariable=v2, show="*")
        self.entry02.pack()

        Button(self, text="登陸", command=self.login).pack()

    def login(self):
        username = self.entry01.get()
        pwd = self.entry02.get()
        print("去資料庫比對使用者名稱和密碼!")
        print("使用者名稱:" + username)
        print("密碼:" + pwd)
        if username == "關關雎鳩" and pwd == "123456":
            messagebox.showinfo("學習系統", "登入成功!歡迎開始學習!")
        else:
            messagebox.showinfo("學習系統", "登入失敗!使用者名稱或密碼錯誤!")

if __name__ == '__main__':
    root = Tk()
    root.geometry("400x130+200+300")
    app = Application(master=root)
    root.mainloop()

Text 多行文字方塊

Text(多行文字方塊)的主要用於顯示多行文字,還可以顯示網頁連結, 圖片, HTML 頁面, 甚至 CSS 樣式表,新增元件等。因此,也常被當做簡單的文書處理器、文字編輯器或者網頁瀏覽器來使用。比如 IDLE 就是 Text 元件構成的。
【範例】Text 多行文字方塊基本用法(文字輸入、元件和影象顯示)

# 測試 Text 多行文字方塊元件的基本用法,使用物件導向的方式
from tkinter import *
import webbrowser


class Application(Frame):
    def __init__(self, master=None):  # super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        self.w1 = Text(root, width=40, height=12, bg="gray")
        # 寬度 20 個字母(10 個漢字),高度一個行高
        self.w1.pack()
        self.w1.insert(1.0, "0123456789nabcdefg")
        self.w1.insert(2.3, "鋤禾日當午,汗滴禾下土。誰知盤中餐,粒粒皆辛苦n")

        Button(self, text="重複插入文字", command=self.insertText).pack(side="left")
        Button(self, text="返回文字", command=self.returnText).pack(side="left")
        Button(self, text="新增圖片", command=self.addImage).pack(side="left")
        Button(self, text="新增元件", command=self.addWidget).pack(side="left")
        Button(self, text="通過 tag 精確控制文字", command=self.testTag).pack(side="left")

    def insertText(self):
        # INSERT 索引表示在遊標處插入
        self.w1.insert(INSERT, '關關雎鳩')

        # END 索引號表示在最後插入
        self.w1.insert(END, '[hebut]')
        self.w1.insert(1.8, "關關雎鳩")

    def returnText(self):
        # Indexes(索引)是用來指向 Text 元件中文字的位置,Text 的元件索引也是對應實際字元之間的位置。
        # 核心:行號以 1 開始 列號以 0 開始
        print(self.w1.get(1.2, 1.6))
        print("所有文字內容:n" + self.w1.get(1.0, END))

    def addImage(self):
        # global photo
        self.photo = PhotoImage(file="pic01.gif")
        self.w1.image_create(END, image=self.photo)

    def addWidget(self):
        b1 = Button(self.w1, text='愛學習')
        # 在text 建立元件的命令
        self.w1.window_create(INSERT, window=b1)

    def testTag(self):
        self.w1.delete(1.0, END)
        self.w1.insert(INSERT, "good good study,day day up!nhebutn關關雎鳩n百度一下")
        self.w1.tag_add("good", 1.0, 1.9)
        self.w1.tag_config("good", background="yellow", foreground="red")
        self.w1.tag_add("baidu", 4.0, 4.4)
        self.w1.tag_config("baidu", underline=True)
        self.w1.tag_bind("baidu", "<Button-1>", self.webshow)

    def webshow(self, event):
        webbrowser.open("http://www.baidu.com")


if __name__ == '__main__':
    root = Tk()
    root.geometry("450x300+200+300")
    app = Application(master=root)
    root.mainloop()

利用 Tags 實現更加強大的文字顯示和控制

Tags 通常用於改變 Text 元件中內容的樣式和功能。你可以修改文字的字型、尺寸和顏色。另外,Tags 還允許你將文字、嵌入的元件和圖片與滑鼠和鍵盤等事件相關聯。
【範例】利用 Tag 屬性實現更復雜文字控制

from tkinter import *
import webbrowser

root= Tk();root.geometry("300x300+400+400")
w1= Text(root,width=40,height=20) #寬度 20 個字母(10 個漢字),高度一個行高
w1.pack()
w1.insert(INSERT,"good goodstudy,day day up!nhebutn關關雎鳩n百度一下")
w1.tag_add("good",1.0,1.9)
w1.tag_config("good",background="yellow",foreground="red")
w1.tag_add("baidu",4.0,4.4)
w1.tag_config("baidu",underline=True)
def webshow(event):
    webbrowser.open("http://www.baidu.com")
    w1.tag_bind("baidu","<Button-1>",webshow)
root.mainloop()

Radiobutton 無線電鈕

Radiobutton 控制元件用於選擇同一組無線電鈕中的一個。Radiobutton 可以顯示文字,也可以顯示影象。
【範例】Radiobutton 基礎用法

測試 Radiobutton 元件的基本用法,使用物件導向的方式

from tkinter import *
from tkinter import messagebox

class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()


    def createWidget(self):
        self.v = StringVar();
        self.v.set("F")
        self.r1 = Radiobutton(self, text="男性", value="M", variable=self.v)
        self.r2 = Radiobutton(self, text="女性", value="F", variable=self.v)
        self.r1.pack(side="left");self.r2.pack(side="left")

        Button(self, text="確定",command=self.confirm).pack(side="left")

    def confirm(self):
        messagebox.showinfo("測試","選擇的性別:"+self.v.get())

        
if __name__ == '__main__':
    root = Tk()
    root.geometry("400x50+200+300")
    app = Application(master=root)
    root.mainloop()

Checkbutton 核取按鈕

Checkbutton 控制元件用於選擇多個按鈕的情況。Checkbutton可以顯示文字,也可以顯示影象。
【範例】Checkbutton 核取按鈕用法

#測試 Checkbutton 元件的基本用法,使用物件導向的方式
from tkinter import *
from tkinter import messagebox

class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        self.codeHobby = IntVar();
        self.videoHobby = IntVar()
        print(self.codeHobby.get()) # 預設值是 0
        self.c1 = Checkbutton(self, text="敲程式碼",variable=self.codeHobby,onvalue=1, offvalue=0)
        self.c2 = Checkbutton(self, text="看視訊", variable=self.videoHobby,onvalue=1, offvalue=0)
        self.c1.pack(side="left")
        self.c2.pack(side="left")

        Button(self, text="確定",command=self.confirm).pack(side="left")

    def confirm(self):
        if self.videoHobby.get() == 1:
            messagebox.showinfo("測試","看視訊,都是正常人有的愛好!你喜歡看什麼型別?")
        if self.codeHobby.get() == 1:
            messagebox.showinfo("測試","抓獲野生程式猿一隻!")

if __name__ == '__main__':
    root = Tk()
    root.geometry("400x50+200+300")
    app = Application(master=root)
    root.mainloop()

canvas 畫布

canvas(畫布)是一個矩形區域,可以放置圖形、影象、元件等。
【範例】canvas 畫布使用基礎範例

# 測試 Canvas 元件的基本用法,使用物件導向的方式
from tkinter import *
from tkinter import messagebox
import random


class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        self.canvas = Canvas(self, width=300, height=370, bg="green")
        self.canvas.pack()
        #畫一條直線
        line = self.canvas.create_line(10, 10, 30, 20, 40, 50)
        #畫一個矩形.
        rect = self.canvas.create_rectangle(50, 50, 100, 100)
        #畫一個橢圓.座標兩雙。為橢圓的邊界矩形左上角和底部右下角
        oval = self.canvas.create_oval(50, 50, 100, 100)
        global photo
        photo = PhotoImage(file="pic01.gif")
        self.canvas.create_image(150,300,image=photo)
        Button(self, text="畫 10 個矩形", command=self.draw50Recg).pack(side="left")

    def draw50Recg(self):
        for i in range(0, 10):
            x1 =random.randrange(int(self.canvas["width"])/2)
            y1 =random.randrange(int(self.canvas["height"])/2)
            x2 = x1 +random.randrange(int(self.canvas["width"])/2)
            y2 = y1 +random.randrange(int(self.canvas["height"])/2)
            self.canvas.create_rectangle(x1, y1, x2, y2)

if __name__ == '__main__':
    root = Tk()
    root.geometry("400x400+200+300")
    app = Application(master=root)
    root.mainloop()

佈局管理器

一個 GUI 應用程式必然有大量的元件,這些元件如何排布?這時候,就需要使用 tkinter 提供的佈局管理器幫助我們組織、管理在父元件中子元件的佈局方式。tkinter 提供了三種管理器:pack、grid、place。
grid 佈局管理器
grid 表格佈局,採用表格結構組織元件。子元件的位置由行和列的單元格來確定,並且可以跨行和跨列,從而實現複雜的佈局。

grid()方法提供的選項

【範例】grid 佈局用法-登入介面設計

# 測試 Grid 佈局管理器的基本用法,使用物件導向的方式
from tkinter import *
from tkinter import messagebox
import random


class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 通過 grid 佈局實現登入介面
        self.label01 = Label(self,text="使用者名稱")
        self.label01.grid(row=0,column=0)
        self.entry01 = Entry(self)
        self.entry01.grid(row=0,column=1)
        Label(self,text="使用者名稱為手機號").grid(row=0,column=2)
        Label(self, text="密碼").grid(row=1, column=0)
        Entry(self, show="*").grid(row=1, column=1)
        Button(self, text="登入").grid(row=2, column=1, sticky=EW)
        Button(self, text="取消").grid(row=2, column=2, sticky=EW)

if __name__ == '__main__':
    root = Tk()
    root.geometry("400x90+200+300")
    app = Application(master=root)
    root.mainloop()

【範例】通過 grid 佈局-實現計算器軟體介面。根據實際簡易計算器的按鍵分佈,設計一個相仿的計算器介面,相應的功能暫不需要實現。

# 計算器軟體介面的設計
from tkinter import *
from tkinter import messagebox
import random


class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()


    def createWidget(self):
        # 通過 grid 佈局實現計算器的介面
        btnText = (("MC","M+","M-","MR"), ("C","±","/","✖ "),
        (7,8,9,"-"),(4,5,6,"+"),(1,2,3,"="),(0,"."))
        Entry(self).grid(row=0,column=0,columnspan=4,pady=10)
        for rindex,r in enumerate(btnText):
            for cindex,c in enumerate(r):
                if c == "=":
                    Button(self,text=c,width=2).grid(row=rindex+1,column=cindex,rowspan=2,sticky=NSEW)
                elif c == 0:
                    Button(self,text=c,width=2).grid(row=rindex+1,column=cindex,columnspan=2,sticky=NSEW)
                elif c == ".":
                    Button(self,text=c,width=2).grid(row=rindex+1,column=cindex+1,sticky=NSEW)
                else:
                    Button(self,text=c,width=2).grid(row=rindex+1,column=cindex,sticky=NSEW)


if __name__ == '__main__':
    root = Tk()
    root.geometry("200x250+200+300")
    app = Application(master=root)
    root.mainloop()

pack 佈局管理器

pack 按照元件的建立順序將子元件新增到父元件中,按照垂直或者水平的方向自然排布。如果不指定任何選項,預設在父元件中自頂向下垂直新增元件。

pack 是程式碼量最少,最簡單的一種,可以用於快速生成介面。
pack()方法提供的選項

【範例】pack 佈局用法,製作鋼琴按鍵佈局

# 測試 pack 佈局管理
from tkinter import *

root = Tk()
root.geometry("700x220")
# Frame 是一個矩形區域,就是用來防止其他子元件
f1 = Frame(root)
f1.pack()
f2 = Frame(root)
f2.pack()
btnText = ("流行風", "中國風", "日本風", "重金屬", "輕音樂")
for txt in btnText:
    Button(f1, text=txt).pack(side="left", padx="10")
for i in range(1, 20):
    Button(f2, width=5, height=10, bg="black" if i % 2 == 0 else "white").pack(side="left")
root.mainloop()

place 佈局管理器

place 佈局管理器可以通過座標精確控制元件的位置,適用於一些佈局更加靈活的場景。
place()方法的選項

【範例】place 佈局管理-基本用法測試

from tkinter import *

root= Tk()
root.geometry("500x300")
root.title("佈局管理 place")
root["bg"]="white"


f1= Frame(root,width=200,height=200,bg="green")
f1.place(x=30,y=30)
Button(root,text="hebut").place(relx=0.5,rely=0,x=100,y=200,relwidth=0.2,relheight=0.2)
Button(f1,text="programmer").place(relx=0.6,rely=0.7)
Button(f1,text="關關雎鳩").place(relx=0.2,rely=0.2)

root.mainloop()

【範例】place 佈局管理-撲克牌遊戲 demo

撲克牌遊戲的介面設計

from tkinter import *
class Application(Frame):
    def __init__(self, master=None):	# super()代表的是父類別的定義,而不是父類別物件
        super().__init__(master)
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):

        # 通過 place 佈局管理器實現撲克牌位置控制
        #self.photo = PhotoImage(file="imgs/puke/puke1.gif")
        #self.puke1 = Label(self.master,image=self.photo)
        #self.puke1.place(x=10,y=50)
        self.photos =[PhotoImage(file="imgs/puke"+str(i+1)+".gif") for i in range(10)]
        self.pukes =[Label(self.master,image=self.photos[i]) for i in range(10)]
        for i in range(10):
            self.pukes[i].place(x=10+i*40,y=50)
            #為所有的 Label 增加事件處理
            self.pukes[0].bind_class("Label","<Button-1>",self.chupai)

    def chupai(self,event):
        print(event.widget.winfo_geometry())
        print(event.widget.winfo_y())
        if event.widget.winfo_y() == 50:
            event.widget.place(y=30)
        else:
            event.widget.place(y=50)

if __name__ == '__main__':
    root = Tk()
    root.geometry("600x370+200+300")
    app = Application(master=root)
    root.mainloop()

事件處理

一個 GUI 應用整個生命週期都處在一個訊息迴圈 (event loop) 中。它等待事件的發生,並作出相應的處理。
Tkinter 提供了用以處理相關事件的機制. 處理常式可被繫結給各個控制元件的各種事件。

widget.bind(event, handler)

如果相關事件發生, handler 函數會被觸發, 事件物件 event 會傳遞給 handler 函數

滑鼠和鍵盤事件

event 物件常用屬性

【範例】滑鼠事件和鍵盤事件用法測試

#測試鍵盤和滑鼠事件
from tkinter import	*

root = Tk()
root.geometry("530x300")
c1 = Canvas(root,width=200,height=200,bg="green")
c1.pack()
def mouseTest(event):
    print("滑鼠左鍵單擊位置(相對於父容器):{0},{1}".format(event.x,event.y))
    print("滑鼠左鍵單擊位置(相對於螢幕):{0},{1}".format(event.x_root,event.y_root))
    print("事件繫結的元件:{0}".format(event.widget))

def testDrag(event):
    c1.create_oval(event.x,event.y,event.x+1,event.y+1)

def keyboardTest(event):
    print("鍵的 keycode:{0},鍵的 char:{1},鍵的 keysym:{2}".format(event.keycode,event.char,event.keysym))

def press_a_test(event):
    print("press a")

def release_a_test(event):
    print("release a")

c1.bind("<Button-1>",mouseTest)
c1.bind("<B1-Motion>",testDrag)
root.bind("<KeyPress>",keyboardTest)
root.bind("<KeyPress-a>",press_a_test)	#只針對小寫的a,大寫的 A 不管用
root.bind("<KeyRelease-a>",release_a_test)
root.mainloop()

多種事件繫結方式彙總

元件物件的繫結
1.通過 command 屬性繫結(適合簡單不需獲取 event 物件)
Button(root,text=”登入”,command=login)
2.通過 bind()方法系結(適合需要獲取 event 物件)
c1 = Canvas(); c1.bind(“”,drawLine)

元件類的繫結

呼叫物件的 bind_class 函數,將該元件類所有的元件繫結事件:
w.bind_class(“Widget”,”event”,eventhanler)

比如:btn01.bind_class(“Button”,””,func)

【範例】多種事件繫結方式總結

#多種事件繫結方式彙總
from tkinter import *

root = Tk()
root.geometry("270x30")
def mouseTest1(event):
    print("bind()方式繫結,可以獲取 event 物件")
    print(event.widget)

def mouseTest2(a, b):
    print("a={0},b={1}".format(a, b))
    print("command 方式繫結,不能直接獲取 event 物件")

def mouseTest3(event):
    print("右鍵單擊事件,繫結給所有按鈕啦!!")
    print(event.widget)

b1 = Button(root, text="測試 bind()繫結")
b1.pack(side="left")
#bind 方式繫結事件
b1.bind("<Button-1>", mouseTest1)
#command 屬性直接繫結事件
b2 = Button(root, text="測試 command2",command=lambda: mouseTest2("關關雎鳩", "hebut"))
b2.pack(side="left")
# 給所有 Button 按鈕都繫結右鍵單擊事件<Button-2>
b1.bind_class("Button", "<Button-2>", mouseTest3)

其他元件

OptionMenu 選擇項
OptionMenu(選擇項)用來做多選一,選中的項會在頂部顯示。
【範例】OptionMenu(選擇項)的基本用法

#optionmenu 的使用測試
from tkinter import *

root= Tk()
root.geometry("200x100")
v= StringVar(root);
v.set("關關雎鳩")
om= OptionMenu(root,v,"關關雎鳩","在河之洲","窈窕淑女","君子好逑")
om["width"]=10
om.pack(pady=20)
def test1():
    print("最喜愛的詩句:",v.get())
    #v.set("關關雎鳩")	#直接修改了optionmenu中選中的值
Button(root,text="確定",command=test1).pack()
root.mainloop()

Scale 移動滾軸

Scale(移動滾軸)用於在指定的數值區間,通過滾軸的移動來選擇值。
【範例】使用 Scale(移動滾軸)控制字型大小變化

#optionmenu 的使用測試
from tkinter import *

root= Tk()
root.geometry("400x150")
def test1(value):
    print("滾軸的值:",value)
    newFont= ("宋體",value)
    a.config(font=newFont)

s1=Scale(root,from_=10,to=50,length=200,orient=HORIZONTAL,command=test1)
s1.pack()
a= Label(root,text="關關雎鳩",width=10,height=1,bg="black",fg="white")
a.pack()
root.mainloop()

顏色選擇框

顏色選擇框可以幫助我們設定背景色、前景色、畫筆顏色、字型顏色等等。
【範例】顏色選擇框基本用法

#askcolor 顏色選擇框的測試,改變背景色
from tkinter import *
from tkinter.colorchooser import *

root= Tk();root.geometry("400x150")

def test1():
    s1= askcolor(color="red", title="選擇背景色")
    #((0.0,0.0,255.99609375),'#0000ff')
    root.config(bg=s1[1])
    
Button(root,text="選擇背景色",command=test1).pack()
root.mainloop()

檔案對話方塊

檔案對話方塊幫助我們實現視覺化的操作目錄、操作檔案。最後,將檔案、目錄的資訊傳入到程式中。檔案對話方塊包含如下一些常用函數

【範例】檔案對話方塊基本用法

from tkinter import *
from tkinter.filedialog import *

root= Tk();root.geometry("400x100")
def test1():
    f= askopenfilename(title="上傳檔案",initialdir="f:/code",filetypes=[("文字檔案",".txt")])
    #print(f)
    show["text"]=f
Button(root,text="選擇編輯的文字檔案",command=test1).pack()
show= Label(root,width=40,height=3,bg="green")
show.pack()
root.mainloop()

【範例】開啟指定 txt 檔案,並讀出檔案內容到視窗

from tkinter import *
from tkinter.filedialog import *

root= Tk();root.geometry("400x100")
def test1():
    with askopenfile(title="上傳檔案",initialdir="f:",filetypes=[("文字檔案",".txt")]) as f:
        show["text"]=f.read()
Button(root,text="選擇編輯的文字檔案",command=test1).pack()
show= Label(root,width=40,height=3,bg="green")
show.pack()
root.mainloop()

簡單輸入對話方塊

simpledialog(簡單對話方塊)包含如下常用函數:

引數中,title 表示視窗標題;prompt 是提示資訊;命名引數**kw 為各種選項:initialvalue(初始值)、minvalue(最小值)、maxvalue(最大值)。
【範例】簡單對話方塊基本用法

#簡單對話方塊
from tkinter.simpledialog import *

root= Tk();root.geometry("400x100")
show= Label(root,width=40,height=3,bg="green")
show.pack()
a=askinteger(title="輸入年齡",prompt="請輸入年齡 ",initialvalue=18,minvalue=1,maxvalue=150)
show["text"]="年齡:"+str(a)
#askfloat,askstring 自行測試
root.mainloop()

通用訊息方塊

messagebox(通用訊息方塊)用於和使用者簡單的互動,使用者點選確定、取消。如下列出了 messagebox 的常見函數:

【範例】通用訊息方塊的基本用法

#簡單對話方塊
from tkinter import *
from tkinter.messagebox import *

root= Tk();root.geometry("400x100")
a1= showinfo(title="關關雎鳩",message="好好學習,天天向上")
print(a1)
root.mainloop()

ttk 子模組控制元件

我們再前面學的元件是 tkinter 模組下的元件,整體風格較老較醜。為了彌補這點不足,推出了 ttk 元件。ttk 元件更加美觀、功能更加強大。使用 Combobox 替代了原來的Listbox 、新增了 LabeledScale( 帶標籤的 Scale) 、Notebook(多檔案視窗)、Progressbar(進度條)、Treeview(數)等元件。
使用 ttk 元件與使用普通的 Tkinter 元件並沒有多大的區別,只要匯入 ttk 模組即可。
ttk 子模組的官方檔案:
https://docs.python.org/3.7/library/tkinter.ttk.html

選單和工具列
GUI 程式通常都有選單,方便使用者的互動。我們一般將選單分為兩種:
1.主選單
主選單通常位於 GUI 程式上方。例如:

2.快捷選單(上下文選單)
通過滑鼠右鍵單擊某個元件物件而彈出的選單,一般是與該元件相關的操作。

主選單

主選單一般包含:檔案、編輯、幫助等,位於 GUI 視窗的上面。建立主選單一般有如下 4 步:
1.建立主選單欄物件

menubar = tk.Menu(root)

2.建立選單,並新增到主選單欄物件

file_menu = tk.Menu(menubar)
menubar.add_cascade(label=」檔案」,menu=file_menu)

3.新增選單項到 2 步中的選單

file_menu.add_command(label=」開啟」)
file_menu.add_command(label=」儲存」,accelerator=」^p」 command=mySaveFile)
file_menu.add_separator()
file_menu.add_command(label=」退出」)

4.將主選單欄新增到根視窗

root[「menu」]=menubar

【範例】記事本軟體主選單設計

#記事本軟體,練習主選單的設計
from tkinter import *
from tkinter.messagebox import *
from tkinter.filedialog import *

root= Tk();root.geometry("400x400")
#建立主選單欄
menubar= Menu(root)
#建立子選單
menuFile= Menu(menubar)
menuEdit= Menu(menubar)
menuHelp= Menu(menubar)
#將子選單加入到主選單欄
menubar.add_cascade(label="檔案(F)",menu=menuFile)
menubar.add_cascade(label="編輯(E)",menu=menuEdit)
menubar.add_cascade(label="幫助(H)",menu=menuHelp)

filename= ""
def openFile():
    global filename
    with askopenfile(title="開啟檔案") as f:
        content =f.read()
        w1.insert(INSERT,content)
        filename =f.name
        print(f.name)

def saveFile():
    with open(filename,"w") as f:
        content =w1.get(1.0,END)
        f.write(content)

def exit():
    root.quit()

#新增選單項
menuFile.add_command(label="開啟",accelerator="^O",command=openFile)
menuFile.add_command(label="儲存",command=saveFile)
menuFile.add_separator() #新增分割線
menuFile.add_command(label="退出",command=exit)

#將主選單欄加到根視窗
root["menu"] =menubar
w1= Text(root,width=50,height=30)
w1.pack()
root.mainloop()

上下文選單

快捷選單(上下文選單)是通過滑鼠右鍵單擊元件而彈出的選單,一般是和這個元件相關的操作,比如:剪下、複製、貼上、屬性等。建立快捷選單步驟如下:

1.建立選單

menubar = tk.Menu(root)
menubar.add_command(label=」字型」)

2.繫結滑鼠右鍵單擊事件

def test(event):
	menubar.post(event.x_root,event.y_root) # 在滑鼠右鍵單擊座標處顯示選單 
	root.bind(「<Button-3>」,test)

【範例】為記事本程式增加快捷選單

from tkinter import *
from tkinter.colorchooser import *
from tkinter.filedialog import *

root= Tk();root.geometry("400x400")

def openAskColor():
    s1= askcolor(color="red", title="選擇背景色")
    #((0.0,0.0,255.99609375),'#0000ff')
    root.config(bg=s1[1])

#建立快捷選單
menubar2= Menu(root)
menubar2.add_command(label="顏色",command=openAskColor)
menuedit= Menu(menubar2,tearoff=0)
menuedit.add_command(label="剪下")
menuedit.add_command(label="複製")
menuedit.add_command(label="貼上")
menubar2.add_cascade(label="編輯",menu=menuedit)

def test(event):
    #選單在滑鼠右鍵單擊的座標處顯示
    menubar2.post(event.x_root,event.y_root)
#編輯區
w1= Text(root,width=50,height=30)
w1.pack()
w1.bind("<Button-3>",test)
root.mainloop()

Tkinter佈局(3種)

Tkinter 提供了佈局功能,主要包含 pack、grid 和 place 三種佈局方法。其中 pack 佈局方法在前面使用過,這是最簡單的佈局方式。

import sys
if sys.version_info.major == 3:
    import tkinter as tk
elif sys.version_info.major == 2:
    import Tkinter as tk
root = tk.Tk()
root.title(u"pack佈局演示")
tk.Button(root, text="side:top").pack(side='top')
tk.Button(root, text="side:bottom").pack(side='bottom')
tk.Button(root, text="side:left").pack(side='left')
tk.Button(root, text="side:right").pack(side='right')
root.mainloop()

grid 佈局法就是將螢幕切成表格的樣子,通過橫向座標 row 和縱向座標 column 來指定元素的位置。第一行標記為 0,第一列也標記為 0。

import sys
if sys.version_info.major == 3:
    import tkinter as tk
elif sys.version_info.major == 2:
    import Tkinter as tk
root = tk.Tk()
root.title(u"grid佈局演示")
for row in range(3):
    for col in range(4):
        text_ = "row=%d, col=%d" % (row, col)
        tk.Button(root, text=text_).grid(row=row, column=col)
root.mainloop()

最後一種佈局方法是 place,它直接指定元素在父元素中的座標值,單位是畫素。

到此這篇關於python Tkinter詳解的文章就介紹到這了,更多相關python Tkinter內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com