首頁 > 軟體

python Tkinter模組使用方法詳解

2022-04-07 13:01:01

一、前言

1.1、Tkinter是什麼

Tkinter 是使用 python 進行視窗視窗設計的模組。Tkinter模組(“Tk 介面”)是Python的標準Tk GUI工具包的介面。作為 python 特定的GUI介面,是一個影象的視窗,tkinter是python自帶的,可以編輯的GUI介面,用來入門,熟悉視窗視窗的使用,非常有必要。

二、準備工作

2.1、Windows演示環境搭建

  • 安裝python3.7
  • 安裝編輯器,演示使用的Visual Studio Code

三、Tkinter建立視窗

3.1、建立出一個視窗

首先我們匯入tkinter的庫

import tkinter as tk  # 在程式碼裡面匯入庫,起一個別名,以後程式碼裡面就用這個別名
root = tk.Tk()  # 這個庫裡面有Tk()這個方法,這個方法的作用就是建立一個視窗

如果只是執行以上的兩句程式碼,執行程式是沒有反應的,因為只有一個主函數,從上到下執行完就沒有了,這個視窗也是很快就消失了,所以現在我們要做的就是讓視窗一直顯示,那麼我們就可以加一個迴圈

建立的視窗的名字是root ,那麼我們之後使用這個root就可以操作這個視窗了。

root.mainloop()  # 加上這一句,就可以看見視窗了

執行以上的3句程式碼,我們就可以看見視窗了

3.2、給視窗取一個標題

root.title('演示視窗')

3.3、視窗設定

通過以下程式碼,我們可以給視窗設定長寬以及視窗在螢幕的位置

root.geometry("300x100+630+80")  # 長x寬+x*y

3.3、建立按鈕,並且給按鈕新增點選事件

這個庫裡面有一個方法Button(),只要呼叫這個方法,我們就可以建立這個元件,建立的這個元件我們賦值給一個常數,以後我們就可以用這個常數來操作這個按鈕,這個方法裡面的引數,就是要我們寫視窗的名字

Button(root) 這樣寫的意思就是 將我們建立的按鈕放到這個視窗上面

btn1 = tk.Button(root)

給按鈕取一個名稱

btn1["text"] = "點選"

我們建立的按鈕元件,已經放到視窗裡面了,但是放到視窗的哪個位置,東南西北哪個地方,我們就可以用pack()去定位(後面會介紹其它定位方法)

btn1.pack()  # 按鈕在視窗裡面的定位

建立點選按鈕事件的彈窗,先匯入messagebox,這個必須單獨匯入

from tkinter import messagebox
def test(e):
    messagebox.showinfo("視窗名稱","點選成功")

現在有了按鈕,有了方法,我想要做的是一點選按鈕,就執行這個方法,那麼就需要將按鈕和方法進行繫結

btn1.bind("<Button-1>",test) #第一個引數為:按滑鼠左鍵的事件 第二個引數為:要執行的方法的名字

按鈕元件裡面有一個方法bind() 這個方法就可以實現繫結

完整程式碼

import tkinter as tk
from tkinter import messagebox
root = tk.Tk()  # 建立視窗
root.title('演示視窗')
root.geometry("300x100+630+80")  # 長x寬+x*y

btn1 = tk.Button(root)  # 建立按鈕,並且將按鈕放到視窗裡面
btn1["text"] = "點選"  # 給按鈕一個名稱
btn1.pack()  # 按鈕佈局

def test(e):
    '''建立彈窗'''
    messagebox.showinfo("視窗名稱", "點選成功")

btn1.bind("<Button-1>", test)  # 將按鈕和方法進行繫結,也就是建立了一個事件
root.mainloop()  # 讓視窗一直顯示,迴圈

3.4、視窗內的元件佈局

3種佈局管理器:pack - grid - place

pack 
這個佈局管理器,要麼將元件垂直的排列,要麼水平的排列

grid 
Grid(網格)佈局管理器會將控制元件放置到一個二維的表格裡。
主控制元件被分割成一系列的行和列,表格中的每個單元(cell)都可以放置一個控制元件。

選項說明
column單元格的列號,從0開始的正整數
columnspan跨列,跨越的列數,正整數
row單元格的行號, 從0開始的正整數
rowspan跨行,跨越的行數,正整數
ipadx, ipady設定子元件之間的間隔,x方向或y方向,預設單位為畫素,非浮點數,預設0.0
padx, pady與之並列的元件之間的間隔,x方向或y方向,預設單位為畫素,非浮點數,預設0.0
sticky元件緊貼所在的單元格的某一腳,對應於東南西北中以及4個角。東 = “e”,南=“s”,西=“w”,北=“n”,“ne”,“se”,“sw”, “nw”;

grid_info() 檢視元件預設的引數

import tkinter as tk
root = tk.Tk()

# 預設按鈕
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid()
print(btn1.grid_info())

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

column 指定控制元件所在的列

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(column=0)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(column=1)


root.title('演示視窗')
root.geometry("300x100+1000+300")
root.mainloop()

  • columnspan 指定每個控制元件橫跨的列數
  • 什麼是columnspan?

類似excel的合併單元格

a佔了兩個格子的寬度,colunmspan就是2

```python
import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(column=0, columnspan=2)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(column=1, columnspan=1)


root.title('演示視窗')
root.geometry("300x100+1000+300")
root.mainloop()

row 指定控制元件所在的行

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(row=0)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(row=1)

# 按鈕3
btn3 = tk.Button(root)
btn3["text"] = "按鈕2"
btn3.grid(row=2)


root.title('演示視窗')
root.geometry("300x100+1000+300")
root.mainloop()

  • rowspan 指定每個控制元件橫跨的行數
  • 什麼是rowspan ?

類似excel的合併單元格

a佔了兩個格子的高度,rowspan就是2

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(row=0, rowspan=2)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(row=2, rowspan=1)

root.title('演示視窗')
root.geometry("300x100+1000+300")
root.mainloop()

ipadx 水平方向內邊距

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(ipadx=20)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(ipadx=5)

root.title('演示視窗')
root.geometry("300x100+1000+300")
root.mainloop()

ipady 垂直方向內邊距

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(ipady=20)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(ipady=5)

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

padx 水平方向外邊距

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(padx=50)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(column=1, padx=20)

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

pady 垂直方向外邊距

import tkinter as tk
root = tk.Tk()

# 按鈕1
btn1 = tk.Button(root)
btn1["text"] = "按鈕1"
btn1.grid(pady=30)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(pady=20)

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

sticky 元件東南西北的方向

import tkinter as tk
root = tk.Tk()

# 預設按鈕
btn1 = tk.Button(root)
btn1["text"] = "預設按鈕演示效果"
btn1.grid(ipadx=50)

# 按鈕2
btn2 = tk.Button(root)
btn2["text"] = "按鈕2"
btn2.grid(row=1, sticky="w")

# 按鈕3
btn3 = tk.Button(root)
btn3["text"] = "按鈕3"
btn3.grid(row=1, sticky="e")

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

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

選項說明
x,y元件左上角的絕對座標(相當於視窗)
relx ,rely元件左上角的座標(相對於父容器)
width , height元件的寬度和高度
relwidth , relheight元件的寬度和高度(相對於父容器)
anchor對齊方式,左對齊“w”,右對齊“e”,頂對齊“n”,底對齊“s”
import tkinter as tk
root = tk.Tk()

but1 = tk.Button(root, text="按鈕1")
but1.place(relx=0.2, x=100, y=20, relwidth=0.2, relheight=0.5)

root.title('演示視窗')
root.geometry("300x150+1000+300")
root.mainloop()

四、Tkinter基本控制元件介紹

4.1、封裝

import tkinter as tk

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('演示視窗')
        self.root.geometry("500x200+1100+150")
        self.interface()

    def interface(self):
        """"介面編寫位置"""
        pass

if __name__ == '__main__':
    a = GUI()
    a.root.mainloop()

4.2、文字顯示_Label

    def interface(self):
        """"介面編寫位置"""
        self.Label0 = tk.Label(self.root, text="文字顯示")
        self.Label0.grid(row=0, column=0)

4.3、按鈕顯示_Button

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="按鈕顯示")
        self.Button0.grid(row=0, column=0)

4.4、輸入框顯示_Entry

    def interface(self):
        """"介面編寫位置"""
        self.Entry0 = tk.Entry(self.root)
        self.Entry0.grid(row=0, column=0)

4.5、文字輸入框顯示_Text

# pack佈局
    def interface(self):
        """"介面編寫位置"""
        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.pack(pady=0, padx=30)
# grid佈局
    def interface(self):
        """"介面編寫位置"""
        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)

4.6、核取按鈕_Checkbutton

    def interface(self):
        """"介面編寫位置"""
        self.Checkbutton01 = tk.Checkbutton(self.root, text="名稱")
        self.Checkbutton01.grid(row=0, column=2)

4.7、無線電鈕_Radiobutton

    def interface(self):
        """"介面編寫位置"""
        self.Radiobutton01 = tk.Radiobutton(self.root, text="名稱")
        self.Radiobutton01.grid(row=0, column=2)

五、元件使用方法介紹

5.1、按鈕(Button)繫結事件

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="執行", command=self.event)
        self.Button0.grid(row=0, column=0)
        
		self.Button1 = tk.Button(self.root, text="退出", command=self.root.destroy, bg="Gray")  # bg=顏色
        self.Button1.grid(row=0, column=1, sticky="e", ipadx=10)

    def event(self):
        """按鈕事件"""
        print("執行成功")

5.2、輸入框(Entry)內容獲取

    def interface(self):
        """"介面編寫位置"""
        self.entry00 = tk.StringVar()
        self.entry00.set("預設資訊")

        self.entry0 = tk.Entry(self.root, textvariable=self.entry00)
        self.entry0.grid(row=1, column=0)

        self.Button0 = tk.Button(self.root, text="執行", command=self.event)
        self.Button0.grid(row=0, column=0)

    def event(self):
        """按鈕事件,獲取文字資訊"""
        a = self.entry00.get()
        print(a)

5.2、文字輸入框(Text),寫入文字資訊和清除文字資訊

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="清除", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)
        self.w1.insert("insert", "預設資訊")

    def event(self):
        '''清空輸入框'''
        self.w1.delete(1.0, "end")

5.3、獲取核取按鈕(Checkbutton)的狀態

  def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.v1 = tk.IntVar()
        self.Checkbutton01 = tk.Checkbutton(self.root, text="核取方塊", command=self.Check_box, variable=self.v1)
        self.Checkbutton01.grid(row=1, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=2, column=0)

    def event(self):
        '''按鈕事件,獲取核取方塊的狀態,1表示勾選,0表示未勾選'''
        a = self.v1.get()
        self.w1.insert(1.0, str(a)+'n')

    def Check_box(self):
        '''核取方塊事件'''
        if self.v1.get() == 1:
            self.w1.insert(1.0, "勾選"+'n')
        else:
            self.w1.insert(1.0, "未勾選"+'n')

5.4、清除控制元件

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.Label0 = tk.Label(self.root, text="文字顯示")
        self.Label0.grid(row=1, column=0)

        self.Entry0 = tk.Entry(self.root)
        self.Entry0.grid(row=2, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=3, column=0)

    def event(self):
        '''按鈕事件,清除Label、Entry、Text元件'''
        a = [self.Label0, self.Entry0, self.w1]
        for i in a:
            i.grid_forget()

5.5、清除核取方塊勾選狀態

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.v1 = tk.IntVar()
        self.Checkbutton01 = tk.Checkbutton(self.root, text="核取方塊", command=self.Check_box, variable=self.v1)
        self.Checkbutton01.grid(row=1, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=2, column=0)

    def event(self):
        '''按鈕事件,清除核取方塊勾選狀態'''
        self.Checkbutton01.deselect()

    def Check_box(self):
        '''核取方塊事件'''
        if self.v1.get() == 1:
            self.w1.insert(1.0, "勾選"+'n')
        else:
            self.w1.insert(1.0, "未勾選"+'n')

5.6、文字方塊(Text)內容獲取

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)

    def event(self):
        a = self.w1.get('0.0', 'end')
        print(a)

六、Tkinter使用多執行緒

6.1、為什麼要使用多執行緒

以下為單執行緒執行

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.event)
        self.Button0.grid(row=0, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)

    def event(self):
        '''按鈕事件,一直迴圈'''
        a = 0
        while True:
            a += 1
            self.w1.insert(1.0, str(a)+'n')

單執行緒下,主執行緒需要執行視窗,如果這個時候點選“確定”按鈕,主執行緒就會去執行event方法,那介面就會出現“無響應”狀態,如果要介面正常顯示,那我們就需要用到多執行緒(threading)

多執行緒,完整程式碼

import tkinter as tk
import threading  # 匯入多執行緒模組

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('演示視窗')
        self.root.geometry("500x200+1100+150")
        self.interface()

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定", command=self.start)
        self.Button0.grid(row=0, column=0)

        self.w1 = tk.Text(self.root, width=80, height=10)
        self.w1.grid(row=1, column=0)

    def event(self):
        '''按鈕事件,一直迴圈'''
        a = 0
        while True:
            a += 1
            self.w1.insert(1.0, str(a)+'n')

    def start(self):
        self.T = threading.Thread(target=self.event)  # 多執行緒
        self.T.setDaemon(True)  # 執行緒守護,即主程序結束後,此執行緒也結束。否則主程序結束子程序不結束
        self.T.start()  # 啟動

if __name__ == '__main__':
    a = GUI()
    a.root.mainloop()

七、Tkinter多執行緒暫停和繼續

import tkinter as tk
import threading
from time import sleep

event = threading.Event()

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('演示視窗')
        self.root.geometry("500x200+1100+150")
        self.interface()

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="啟動", command=self.start)
        self.Button0.grid(row=0, column=0)

        self.Button0 = tk.Button(self.root, text="暫停", command=self.stop)
        self.Button0.grid(row=0, column=1)

        self.Button0 = tk.Button(self.root, text="繼續", command=self.conti)
        self.Button0.grid(row=0, column=2)

        self.w1 = tk.Text(self.root, width=70, height=10)
        self.w1.grid(row=1, column=0, columnspan=3)

    def event(self):
        '''按鈕事件,一直迴圈'''
        while True:
            sleep(1)
            event.wait()
            self.w1.insert(1.0, '執行中'+'n')

    def start(self):
        event.set()
        self.T = threading.Thread(target=self.event)
        self.T.setDaemon(True)
        self.T.start()

    def stop(self):
        event.clear()
        self.w1.insert(1.0, '暫停'+'n')

    def conti(self):
        event.set()
        self.w1.insert(1.0, '繼續'+'n')

if __name__ == '__main__':
    a = GUI()
    a.root.mainloop()

八、Tkinter檔案之間的呼叫

8.1、準備工作

  • a.py檔案 - -介面邏輯+執行緒
  • b.py 檔案 - -業務邏輯
  • 以上檔案在同一個目錄下

8.2、方法

# a.py 檔案
import tkinter as tk
import threading
from b import logic  # 呼叫b檔案中的logic類

class GUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('演示視窗')
        self.root.geometry("500x260+1100+150")
        self.interface()

    def interface(self):
        """"介面編寫位置"""
        self.Button0 = tk.Button(self.root, text="確定執行", command=self.start, bg="#7bbfea")
        self.Button0.grid(row=0, column=1, pady=10)

        self.entry00 = tk.StringVar()
        self.entry00.set("")

        self.entry0 = tk.Entry(self.root, textvariable=self.entry00)
        self.entry0.grid(row=1, column=1, pady=15)

        self.w1 = tk.Text(self.root, width=50, height=8)
        self.w1.grid(row=2, column=0, columnspan=3, padx=60)

    def seal(self):
        '''把b檔案的類單獨寫一個方法'''
        a = self.entry00.get()
        w1 = self.w1
        logic().event(a, w1)

    def start(self):
        '''子執行緒無法直接執行b的類,需要把b檔案單獨寫一個方法,然後執行'''
        self.T = threading.Thread(target=self.seal)
        self.T.setDaemon(True)
        self.T.start()

if __name__ == '__main__':
    a = GUI()
    a.root.mainloop()

# b.py 檔案
import time
class logic():
    def __init__(self):
        pass

    def main(self, a, x):
        while True:
            y = int(a)+int(x)
            self.w1.insert(1.0, str(y)+'n')
            time.sleep(1)
            x += 1

    def event(self, a, w1):
        '''呼叫main的方法'''
        self.w1 = w1
        x = 1
        self.main(a, x)

總結

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


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