python?Tkinter實(shí)例詳解
簡介
- tkinter
tkinter(Tk interface)是Python的標(biāo)準(zhǔn)GUl庫,支持跨平臺的GUl程序開發(fā)。tkinter適合小型的GUl程序編寫,也特別適合初學(xué)者學(xué)習(xí)GUl編程。
- wxPython
wxPython是比較流行的GUI庫,適合大型應(yīng)用程序開發(fā),功能強(qiáng)于tkinter,整體設(shè)計(jì)框架類似于MFC(MicrosoftFoundation Classes微軟基礎(chǔ)類庫).
- PyQT
Qt是一種開源的GUI庫,適合大型GUI程序開發(fā),PyQt是Qt工具包標(biāo)準(zhǔn)的Python實(shí)現(xiàn)。我們也可以使用QtDesginer界面設(shè)計(jì)器快速開發(fā)GUl應(yīng)用程序.
官網(wǎng)
https://docs.python.org/3/library/tkinter.html
創(chuàng)建一個(gè)窗口
from tkinter import * root = Tk() # 實(shí)例化TK root.mainloop() # 進(jìn)入事件循環(huán)
第一個(gè)GUI帶事件的程序
from tkinter import *
from tkinter import messagebox
root = Tk()
bt = Button(root)
bt['text'] = '點(diǎn)我'
bt.pack()
def dianji(e):
messagebox.showinfo('message', 'give flower') # 提示框
bt.bind('<Button-1>', dianji) # 綁定點(diǎn)擊事件
root.mainloop() # 進(jìn)入事件循環(huán)窗口大小和位置
geometry()尺寸

from tkinter import *
from tkinter import messagebox
root = Tk()
root.title('我的gui程序')
root.geometry('500x300+100+200')
# 500寬度 300高度 距屏幕左側(cè)100像素 頂部200像素
bt = Button(root)
bt['text'] = '點(diǎn)我'
bt.pack()
def dianji(e):
print(e)
messagebox.showinfo('message', 'give flower') # 提示框
bt.bind('<Button-1>', dianji) # 綁定點(diǎn)擊事件
root.mainloop() # 進(jìn)入事件循環(huán)
窗口放至屏幕中間
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()常用組件匯總
組件類關(guān)系圖



GUI面向?qū)ο髮懛?/h2>
通過類 Application 組織整個(gè) GUI 程序,類 Application繼承了 Frame 及通過繼承擁有了父類的特性。通過構(gòu)造函數(shù)__init__()初始化窗口中的對象,通過 createWidgets()方法創(chuàng)建窗口中的對象。
Frame 框架是一個(gè) tkinter 組件,表示一個(gè)矩形的區(qū)域。
Frame 一般作為容器使用,可以放置其他組件,從而實(shí)現(xiàn)復(fù)雜的布局。
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):
# 創(chuàng)建組件
self.btn01 = Button(self)
self.btn01['text'] = '點(diǎn)擊送花'
self.btn01.pack()
self.btn01['command'] = self.songhua
# 創(chuàng)建一個(gè)退出按鈕
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('一個(gè)經(jīng)典的GUI程序類的測試')
app = Application(master=root)
root.mainloop()
簡單組件
- Label 標(biāo)簽
Label(標(biāo)簽)主要用于顯示文本信息,也可以顯示圖像。
Label(標(biāo)簽)有這樣一些常見屬性:
- width,height
用于指定區(qū)域大小,如果顯示是文本,則以單個(gè)英文字符大小為單位(一個(gè)漢字寬度占 2 個(gè)字符位置,高度和英文字符一樣);如果顯示是圖像,則以像素為單位。默認(rèn)值是根據(jù)具體顯示的內(nèi)容動態(tài)調(diào)整。
- font
指定字體和字體大小,如:font =(font_name,size)
- image
顯示在 Label 上的圖像,目前 tkinter 只支持 gif 格式。
- fg 和 bg
fg(foreground):前景色、bg(background):背景色
- justify
針對多行文字的對齊,可設(shè)置 justify 屬性,可選值"left" “center” “right”
【示例】Label(標(biāo)簽)的用法
from tkinter import *
class Application(Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
# 創(chuàng)建組件
self.label01 = Label(self, text='關(guān)關(guān)雎鳩', 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='hebut\n關(guān)關(guān)雎鳩', 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 選項(xiàng)詳解
通過學(xué)習(xí) Label 組件,我們發(fā)現(xiàn)可以通過 Options 設(shè)置組件的屬性,從而控制組件的各種狀態(tài)。比如:寬度、高度、顏色、位置等等。
我們可以通過三種方式設(shè)置 Options 選項(xiàng),這在各種 GUI 組件中用法都一致。
1.創(chuàng)建對象時(shí),使用可變參數(shù)
fred = Button(self, fg="red", bg="blue")
2.創(chuàng)建對象后,使用字典索引方式
fred["fg"] = "red" fred["bg"] = "blue"
3 創(chuàng)建對象后,使用 config()方法
fred.config(fg="red", bg="blue")
如何查看組件的 Options 選項(xiàng):
1.可以通過打印 config()方法的返回值,查看 Options 選項(xiàng) print(fred.config())
2.通過在 IDE 中,點(diǎn)擊組件對象的構(gòu)造方法,進(jìn)入到方法內(nèi)觀察:
上面代碼中有:“standard options 標(biāo)準(zhǔn)選項(xiàng)”和“widget-specific options 組件特定選項(xiàng)”。我們將常見的選項(xiàng)匯總?cè)缦拢?/p>



Button
Button(按鈕)用來執(zhí)行用戶的單擊操作。Button 可以包含文本,也可以包含圖像。按鈕被單擊后會自動調(diào)用對應(yīng)事件綁定的方法。
【示例】Button 按鈕用法(文字、圖片、事件)
#測試Button組件的基本用法,使用面向?qū)ο蟮姆绞?
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):
# 創(chuàng)建組件
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") #設(shè)置按鈕為禁用
def login(self):
messagebox.showinfo("學(xué)習(xí)系統(tǒng)", "登錄成功!歡迎開始學(xué)習(xí)!")
if __name__ == '__main__':
root = Tk()
root.geometry("400x400+200+300")
app = Application(master=root)
root.mainloop()
Entry 單行文本框
Entry 用來接收一行字符串的控件。如果用戶輸入的文字長度長于 Entry 控件的寬度時(shí), 文字會自動向后滾動。如果想輸入多行文本, 需要使用 Text 控件。
【示例】Entry 單行文本框?qū)崿F(xiàn)簡單登錄界面
# 測試 Entry 組件的基本用法,使用面向?qū)ο蟮姆绞?
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):
# 創(chuàng)建登錄界面的組件
self.label01 = Label(self, text="用戶名")
self.label01.pack()
# StringVar 變量綁定到指定的組件。
# StringVar 變量的值發(fā)生變化,組件內(nèi)容也變化;
# 組件內(nèi)容發(fā)生變化,StringVar 變量的值也發(fā)生變化。 v1 = StringVar()
v1 = StringVar()
self.entry01 = Entry(self, textvariable=v1)
self.entry01.pack()
v1.set("admin")
print(v1.get())
print(self.entry01.get())
# 創(chuàng)建密碼框
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("去數(shù)據(jù)庫比對用戶名和密碼!")
print("用戶名:" + username)
print("密碼:" + pwd)
if username == "關(guān)關(guān)雎鳩" and pwd == "123456":
messagebox.showinfo("學(xué)習(xí)系統(tǒng)", "登錄成功!歡迎開始學(xué)習(xí)!")
else:
messagebox.showinfo("學(xué)習(xí)系統(tǒng)", "登錄失??!用戶名或密碼錯(cuò)誤!")
if __name__ == '__main__':
root = Tk()
root.geometry("400x130+200+300")
app = Application(master=root)
root.mainloop()
Text 多行文本框
Text(多行文本框)的主要用于顯示多行文本,還可以顯示網(wǎng)頁鏈接, 圖片, HTML 頁面, 甚至 CSS 樣式表,添加組件等。因此,也常被當(dāng)做簡單的文本處理器、文本編輯器或者網(wǎng)頁瀏覽器來使用。比如 IDLE 就是 Text 組件構(gòu)成的。
【示例】Text 多行文本框基本用法(文本輸入、組件和圖像顯示)
# 測試 Text 多行文本框組件的基本用法,使用面向?qū)ο蟮姆绞?
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 個(gè)字母(10 個(gè)漢字),高度一個(gè)行高
self.w1.pack()
self.w1.insert(1.0, "0123456789\nabcdefg")
self.w1.insert(2.3, "鋤禾日當(dāng)午,汗滴禾下土。誰知盤中餐,粒粒皆辛苦\n")
Button(self, text="重復(fù)插入文本", 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 索引表示在光標(biāo)處插入
self.w1.insert(INSERT, '關(guān)關(guān)雎鳩')
# END 索引號表示在最后插入
self.w1.insert(END, '[hebut]')
self.w1.insert(1.8, "關(guān)關(guān)雎鳩")
def returnText(self):
# Indexes(索引)是用來指向 Text 組件中文本的位置,Text 的組件索引也是對應(yīng)實(shí)際字符之間的位置。
# 核心:行號以 1 開始 列號以 0 開始
print(self.w1.get(1.2, 1.6))
print("所有文本內(nèi)容:\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='愛學(xué)習(xí)')
# 在text 創(chuàng)建組件的命令
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!\nhebut\n關(guān)關(guān)雎鳩\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 實(shí)現(xiàn)更加強(qiáng)大的文本顯示和控制
Tags 通常用于改變 Text 組件中內(nèi)容的樣式和功能。你可以修改文本的字體、尺寸和顏色。另外,Tags 還允許你將文本、嵌入的組件和圖片與鼠標(biāo)和鍵盤等事件相關(guān)聯(lián)。
【示例】利用 Tag 屬性實(shí)現(xiàn)更復(fù)雜文本控制
from tkinter import *
import webbrowser
root= Tk();root.geometry("300x300+400+400")
w1= Text(root,width=40,height=20) #寬度 20 個(gè)字母(10 個(gè)漢字),高度一個(gè)行高
w1.pack()
w1.insert(INSERT,"good goodstudy,day day up!\nhebut\n關(guān)關(guān)雎鳩\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 控件用于選擇同一組單選按鈕中的一個(gè)。Radiobutton 可以顯示文本,也可以顯示圖像。
【示例】Radiobutton 基礎(chǔ)用法
測試 Radiobutton 組件的基本用法,使用面向?qū)ο蟮姆绞?/p>
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 復(fù)選按鈕
Checkbutton 控件用于選擇多個(gè)按鈕的情況。Checkbutton可以顯示文本,也可以顯示圖像。
【示例】Checkbutton 復(fù)選按鈕用法
#測試 Checkbutton 組件的基本用法,使用面向?qū)ο蟮姆绞?
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()) # 默認(rèn)值是 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(畫布)是一個(gè)矩形區(qū)域,可以放置圖形、圖像、組件等。
【示例】canvas 畫布使用基礎(chǔ)示例
# 測試 Canvas 組件的基本用法,使用面向?qū)ο蟮姆绞?
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)
#畫一個(gè)矩形.
rect = self.canvas.create_rectangle(50, 50, 100, 100)
#畫一個(gè)橢圓.坐標(biāo)兩雙。為橢圓的邊界矩形左上角和底部右下角
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 個(gè)矩形", 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()
布局管理器
一個(gè) GUI 應(yīng)用程序必然有大量的組件,這些組件如何排布?這時(shí)候,就需要使用 tkinter 提供的布局管理器幫助我們組織、管理在父組件中子組件的布局方式。tkinter 提供了三種管理器:pack、grid、place。
grid 布局管理器
grid 表格布局,采用表格結(jié)構(gòu)組織組件。子組件的位置由行和列的單元格來確定,并且可以跨行和跨列,從而實(shí)現(xiàn)復(fù)雜的布局。
grid()方法提供的選項(xiàng)

【示例】grid 布局用法-登錄界面設(shè)計(jì)
# 測試 Grid 布局管理器的基本用法,使用面向?qū)ο蟮姆绞?
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 布局實(shí)現(xiàn)登錄界面
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="用戶名為手機(jī)號").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 布局-實(shí)現(xiàn)計(jì)算器軟件界面。根據(jù)實(shí)際簡易計(jì)算器的按鍵分布,設(shè)計(jì)一個(gè)相仿的計(jì)算器界面,相應(yīng)的功能暫不需要實(shí)現(xiàn)。
# 計(jì)算器軟件界面的設(shè)計(jì)
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 布局實(shí)現(xiàn)計(jì)算器的界面
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 按照組件的創(chuàng)建順序?qū)⒆咏M件添加到父組件中,按照垂直或者水平的方向自然排布。如果不指定任何選項(xiàng),默認(rèn)在父組件中自頂向下垂直添加組件。
pack 是代碼量最少,最簡單的一種,可以用于快速生成界面。
pack()方法提供的選項(xiàng)

【示例】pack 布局用法,制作鋼琴按鍵布局
# 測試 pack 布局管理
from tkinter import *
root = Tk()
root.geometry("700x220")
# Frame 是一個(gè)矩形區(qū)域,就是用來防止其他子組件
f1 = Frame(root)
f1.pack()
f2 = Frame(root)
f2.pack()
btnText = ("流行風(fēng)", "中國風(fēng)", "日本風(fēng)", "重金屬", "輕音樂")
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 布局管理器可以通過坐標(biāo)精確控制組件的位置,適用于一些布局更加靈活的場景。
place()方法的選項(xiàng)

【示例】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="關(guān)關(guān)雎鳩").place(relx=0.2,rely=0.2)
root.mainloop()【示例】place 布局管理-撲克牌游戲 demo
撲克牌游戲的界面設(shè)計(jì)
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 布局管理器實(shí)現(xiàn)撲克牌位置控制
#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()
事件處理
一個(gè) GUI 應(yīng)用整個(gè)生命周期都處在一個(gè)消息循環(huán) (event loop) 中。它等待事件的發(fā)生,并作出相應(yīng)的處理。
Tkinter 提供了用以處理相關(guān)事件的機(jī)制. 處理函數(shù)可被綁定給各個(gè)控件的各種事件。
widget.bind(event, handler)
如果相關(guān)事件發(fā)生, handler 函數(shù)會被觸發(fā), 事件對象 event 會傳遞給 handler 函數(shù)
鼠標(biāo)和鍵盤事件

event 對象常用屬性

【示例】鼠標(biāo)事件和鍵盤事件用法測試
#測試鍵盤和鼠標(biāo)事件
from tkinter import *
root = Tk()
root.geometry("530x300")
c1 = Canvas(root,width=200,height=200,bg="green")
c1.pack()
def mouseTest(event):
print("鼠標(biāo)左鍵單擊位置(相對于父容器):{0},{1}".format(event.x,event.y))
print("鼠標(biāo)左鍵單擊位置(相對于屏幕):{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)
組件類的綁定
調(diào)用對象的 bind_class 函數(shù),將該組件類所有的組件綁定事件:
w.bind_class(“Widget”,”event”,eventhanler)
比如:btn01.bind_class(“Button”,””,func)
【示例】多種事件綁定方式總結(jié)
#多種事件綁定方式匯總
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("關(guān)關(guān)雎鳩", "hebut"))
b2.pack(side="left")
# 給所有 Button 按鈕都綁定右鍵單擊事件<Button-2>
b1.bind_class("Button", "<Button-2>", mouseTest3)其他組件
OptionMenu 選擇項(xiàng)
OptionMenu(選擇項(xiàng))用來做多選一,選中的項(xiàng)會在頂部顯示。
【示例】OptionMenu(選擇項(xiàng))的基本用法
#optionmenu 的使用測試
from tkinter import *
root= Tk()
root.geometry("200x100")
v= StringVar(root);
v.set("關(guān)關(guān)雎鳩")
om= OptionMenu(root,v,"關(guān)關(guān)雎鳩","在河之洲","窈窕淑女","君子好逑")
om["width"]=10
om.pack(pady=20)
def test1():
print("最喜愛的詩句:",v.get())
#v.set("關(guān)關(guān)雎鳩") #直接修改了optionmenu中選中的值
Button(root,text="確定",command=test1).pack()
root.mainloop()Scale 移動滑塊
Scale(移動滑塊)用于在指定的數(shù)值區(qū)間,通過滑塊的移動來選擇值。
【示例】使用 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="關(guān)關(guān)雎鳩",width=10,height=1,bg="black",fg="white")
a.pack()
root.mainloop()顏色選擇框
顏色選擇框可以幫助我們設(shè)置背景色、前景色、畫筆顏色、字體顏色等等。
【示例】顏色選擇框基本用法
#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()文件對話框
文件對話框幫助我們實(shí)現(xiàn)可視化的操作目錄、操作文件。最后,將文件、目錄的信息傳入到程序中。文件對話框包含如下一些常用函數(shù)


【示例】文件對話框基本用法
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 文件,并讀出文件內(nèi)容到窗口
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(簡單對話框)包含如下常用函數(shù):

參數(shù)中,title 表示窗口標(biāo)題;prompt 是提示信息;命名參數(shù)**kw 為各種選項(xiàng):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(通用消息框)用于和用戶簡單的交互,用戶點(diǎn)擊確定、取消。如下列出了 messagebox 的常見函數(shù):

【示例】通用消息框的基本用法
#簡單對話框
from tkinter import *
from tkinter.messagebox import *
root= Tk();root.geometry("400x100")
a1= showinfo(title="關(guān)關(guān)雎鳩",message="好好學(xué)習(xí),天天向上")
print(a1)
root.mainloop()ttk 子模塊控件
我們再前面學(xué)的組件是 tkinter 模塊下的組件,整體風(fēng)格較老較丑。為了彌補(bǔ)這點(diǎn)不足,推出了 ttk 組件。ttk 組件更加美觀、功能更加強(qiáng)大。使用 Combobox 替代了原來的Listbox 、新增了 LabeledScale( 帶標(biāo)簽的 Scale) 、Notebook(多文檔窗口)、Progressbar(進(jìn)度條)、Treeview(數(shù))等組件。
使用 ttk 組件與使用普通的 Tkinter 組件并沒有多大的區(qū)別,只要導(dǎo)入 ttk 模塊即可。
ttk 子模塊的官方文檔:
https://docs.python.org/3.7/library/tkinter.ttk.html
菜單和工具欄
GUI 程序通常都有菜單,方便用戶的交互。我們一般將菜單分為兩種:
1.主菜單
主菜單通常位于 GUI 程序上方。例如:

2.快捷菜單(上下文菜單)
通過鼠標(biāo)右鍵單擊某個(gè)組件對象而彈出的菜單,一般是與該組件相關(guān)的操作。

主菜單
主菜單一般包含:文件、編輯、幫助等,位于 GUI 窗口的上面。創(chuàng)建主菜單一般有如下 4 步:
1.創(chuàng)建主菜單欄對象
menubar = tk.Menu(root)
2.創(chuàng)建菜單,并添加到主菜單欄對象
file_menu = tk.Menu(menubar) menubar.add_cascade(label=”文件”,menu=file_menu)
3.添加菜單項(xiàng)到 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
【示例】記事本軟件主菜單設(shè)計(jì)
#記事本軟件,練習(xí)主菜單的設(shè)計(jì)
from tkinter import *
from tkinter.messagebox import *
from tkinter.filedialog import *
root= Tk();root.geometry("400x400")
#創(chuàng)建主菜單欄
menubar= Menu(root)
#創(chuàng)建子菜單
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()
#添加菜單項(xiàng)
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()
上下文菜單
快捷菜單(上下文菜單)是通過鼠標(biāo)右鍵單擊組件而彈出的菜單,一般是和這個(gè)組件相關(guān)的操作,比如:剪切、復(fù)制、粘貼、屬性等。創(chuàng)建快捷菜單步驟如下:
1.創(chuàng)建菜單
menubar = tk.Menu(root) menubar.add_command(label=”字體”)
2.綁定鼠標(biāo)右鍵單擊事件
def test(event): menubar.post(event.x_root,event.y_root) # 在鼠標(biāo)右鍵單擊坐標(biāo)處顯示菜單 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])
#創(chuàng)建快捷菜單
menubar2= Menu(root)
menubar2.add_command(label="顏色",command=openAskColor)
menuedit= Menu(menubar2,tearoff=0)
menuedit.add_command(label="剪切")
menuedit.add_command(label="復(fù)制")
menuedit.add_command(label="粘貼")
menubar2.add_cascade(label="編輯",menu=menuedit)
def test(event):
#菜單在鼠標(biāo)右鍵單擊的坐標(biāo)處顯示
menubar2.post(event.x_root,event.y_root)
#編輯區(qū)
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 布局法就是將屏幕切成表格的樣子,通過橫向坐標(biāo) row 和縱向坐標(biāo) column 來指定元素的位置。第一行標(biāo)記為 0,第一列也標(biāo)記為 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,它直接指定元素在父元素中的坐標(biāo)值,單位是像素。
到此這篇關(guān)于python Tkinter詳解的文章就介紹到這了,更多相關(guān)python Tkinter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pycharm中如何自定義設(shè)置通過“ctrl+滾輪”進(jìn)行放大和縮小實(shí)現(xiàn)方法
這篇文章主要介紹了pycharm中如何自定義設(shè)置通過“ctrl+滾輪”進(jìn)行放大和縮小實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
python利用tkinter實(shí)現(xiàn)圖片格式轉(zhuǎn)換的示例
這篇文章主要介紹了python利用tkinter實(shí)現(xiàn)圖片格式轉(zhuǎn)換,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-09-09
ansible作為python模塊庫使用的方法實(shí)例
ansible是一個(gè)python package,是個(gè)完全的unpack and play軟件,對客戶端唯一的要求是有ssh有python,并且裝了python-simplejson包,部署上簡單到發(fā)指。下面這篇文章就給大家主要介紹了ansible作為python模塊庫使用的方法實(shí)例,需要的朋友可以參考借鑒。2017-01-01
python實(shí)現(xiàn)多進(jìn)程按序號批量修改文件名的方法示例
這篇文章主要介紹了python實(shí)現(xiàn)多進(jìn)程按序號批量修改文件名的方法,涉及Python多進(jìn)程與文件相關(guān)操作技巧,需要的朋友可以參考下2019-12-12
TensorFlow Saver:保存和讀取模型參數(shù).ckpt實(shí)例
今天小編就為大家分享一篇TensorFlow Saver:保存和讀取模型參數(shù).ckpt實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python實(shí)現(xiàn)進(jìn)程同步和通信的方法
本篇文章主要介紹了Python實(shí)現(xiàn)進(jìn)程同步和通信的方法,詳細(xì)的介紹了Process、Queue、Pipe、Lock等組件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01

