天天看點

python小練習--GUI設計

文章目錄

          • 練習1:canvas畫布的使用
          • 練習2:練習三個布局管理器
            • 1.grid 布局管理器
            • 2.pack 布局管理器
            • 3.place布局管理器
          • 練習3:滑鼠事件和鍵盤事件用法
          • 練習4:lambda 表達式實作傳參
          • 練習5:多種事件綁定方式
          • 練習6:OptionMenu 選擇項
          • 練習7:Scale移動滑塊
          • 練習8:字型動态調整的方法測試
          • 練習9:顔色選擇框基本用法
          • 練習10:檔案對話框基本用法
            • 測試1:傳回選擇好的檔案名
            • 測試2:打開指定 txt 檔案,并讀出檔案内容到視窗
          • 練習11:簡單輸入對話框
          • 練習12:通用消息框
練習1:canvas畫布的使用

測試畫直線,圓形,半圓,三角形等圖像,或者插入圖檔

from tkinter import *
from tkinter import messagebox

#定義坐标位置
lineposition = ((30,50),(300,100),(20,50))
rectposition = ((50,50),(100,100))
ovalposition = ((150,50),(250,150))
arcposition = ((350,50),(250,150))
coorposition = ((100,100),(50,150),(150,150),(80,200),(120,200))

class Application(Frame):

    def __init__(self,master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.TestCanvas()

    def TestCanvas(self):
        canvas = Canvas(self, width = 500, height = 350)
        canvas["bg"] = "blue"
        canvas.pack()
		
		#畫直線
        line = canvas.create_line(lineposition)
        #畫矩形
        rect = canvas.create_rectangle(rectposition)
        #畫圓形
        oval = canvas.create_oval(ovalposition)
        #畫四分一圓形
        arc = canvas.create_arc(arcposition)
        #畫多邊形
        coor1 = canvas.create_polygon(coorposition)
        coor2 = canvas.create_polygon(200,200,400,200,300,300)
		
		#插入圖畫
        global photo
        photo = PhotoImage(file="photo/pngphoto/小黃人.png")
        canvas.create_image(380,250,image=photo)

Clichong = Tk()
Clichong.geometry("600x400+100+200")
Clichong.title("GUI設計測試")
app = Application(master=Clichong)
app.mainloop()
           
python小練習--GUI設計
python小練習--GUI設計
練習2:練習三個布局管理器

tkinter 提供了三種管理器:pack、grid、place。

1.grid 布局管理器

grid 表格布局,采用表格結構組織元件。子元件的位置由行和列的單元格來确定,并且可以跨行和跨列,進而實作複雜的布局。

python小練習--GUI設計

測試1:寫一個簡單的登入界面

#使用grid布局

from tkinter import *
from tkinter import messagebox

class Application(Frame):

    def __init__(self,master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.Mytest()

    def Mytest(self):

        lb1 = Label(self,text="使用者名:")
        lb1.grid(row=0,column=0)

        et1 = Entry(self,show="*")
        et1.grid(row=0,column=1)

        bt1 = Button(self,width=5,height=1,text="登入")
        bt1.grid(row=1,column=1,sticky="es")    # sticky控制好方位

Clichong = Tk()
Clichong.geometry("600x400+100+200")
Clichong.title("GUI設計測試")
app = Application(master=Clichong)
app.mainloop()
           
python小練習--GUI設計

測試2:寫一個電腦的簡單布局

#使用grid布局

from tkinter import *
from tkinter import messagebox

#定義好按鈕上面text内容
btnumber = (("MC","M+","M-","MR"),\
            ("C","±","+","*"),\
            (7,8,9,"-"),\
            (4,5,6,"+"),\
            (1,2,3,"="),\
            (0,"."))

class Application(Frame):

    def __init__(self,master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.Mytest()

    def Mytest(self):

        Entry(self).grid(row=0,column=0,columnspan=4,pady=10,sticky="nsew")

        print((list(enumerate(btnumber))))
        for rows,datainfo in enumerate(btnumber):
            for nums,singledatainfo in enumerate(datainfo):
                #對于等号與點号需要做特殊在處理
                if singledatainfo == "=":
                    Button(self,text=singledatainfo).grid(row=rows+1,column=nums,rowspan=2,sticky="nsew")
                elif singledatainfo == ".":
                    Button(self, text=singledatainfo).grid(row=rows + 1, column=nums, columnspan=2, sticky="nsew")
                else:
                    Button(self,text=singledatainfo).grid(row=rows+1,column=nums,sticky="nsew")


Clichong = Tk()
Clichong.geometry("140x220+100+200")
Clichong.title("GUI設計測試")
app = Application(master=Clichong)
app.mainloop()
           
python小練習--GUI設計

2.pack 布局管理器

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

python小練習--GUI設計

測試:制作鋼琴按鍵布局

#使用grid布局

from tkinter import *
from tkinter import messagebox

btstring = ("伴奏1","伴奏2","伴奏3","旋律1","旋律2")

Clichong = Tk()
Clichong.geometry("500x240+300+300")
Clichong.title("鋼琴鍵")

# 思路,這裡我們需要定義兩個pack,一個放按鈕,另外一個放置鋼琴鍵。而這兩個pack都在Clichong這個背景上面
# 放置按鈕
pianobt = Frame(Clichong)
pianobt.pack(pady=15)
for bttext in btstring:
    Button(pianobt,text=bttext,width=5,height=1).pack(side="left",padx=10)

# 放置鋼琴鍵
pianoky = Frame(Clichong)
pianoky.pack(pady=10)
for btpiano in range(0,11):
    Button(pianoky,width=5,height=10,bg="black" if btpiano%2==0 else "white").pack(side="left")

# 一定要設定循環,不然無法實作
Clichong.mainloop()
           
python小練習--GUI設計

3.place布局管理器

place 布局管理器可以通過坐标精确控制元件的位置,适用于一些布局更加靈活的場景。

python小練習--GUI設計
python小練習--GUI設計

測試1:簡單測試place元件

# 測試place布局
from tkinter import *

Clichong = Tk()
Clichong.geometry("400x200+400+300")
Clichong["bg"] = "blue"

# 放置一個黃色的方框
fm1 = Frame(Clichong,bg="yellow",width=100,height=100)
fm1.place(x=30,y=35)

# 放置一個綠色的方框
fm2 = Frame(Clichong,bg="green",width=100,height=100)
fm2.place(x=270,y=35)

# 放置三個按鈕
Button(fm1,text="bt1",bg="green").place(relx=0.3,rely=0.7)
Button(fm2,text="bt2",bg="yellow").place(relx=0.7,rely=0.3)
Button(Clichong,text="bt",bg="white").place(width=60,height=30,relx=0.45,rely=0.4)

Clichong.mainloop()

           
python小練習--GUI設計

測試2:撲克牌遊戲出牌操作設定

# 撲克出牌

from tkinter import *

Clichong = Tk()
Clichong.geometry("600x400+300+300")

# 圖像處理
myphoto = [PhotoImage(file="photo/puke/puke"+str(pukenumber+1)+".gif")for pukenumber in range(10)]
mypuke = [Label(Clichong,image=myphoto[i])for i in range(10)]

# 放置撲克牌
for i in range(10):
    mypuke[i].place(x=50+40*i,y=130)

# 觸發事件的操作函數
def pukeoutfunction(event):
    print(event.widget.winfo_geometry())    # 列印geometry資訊
    print(event.widget.winfo_y())           # 列印y坐标
    # 如果y坐标在底下,則出牌
    if event.widget.winfo_y() == 130:
        event.widget.place(y=80)
    # 如果y坐标已出,則收牌
    else:
        event.widget.place(y=130)

# 對label事件點選的綁定出牌操作
mypuke[1].bind_class("Label","<Button-1>",pukeoutfunction)

Clichong.mainloop()
           

初始狀态

python小練習--GUI設計

點選任意一張牌

python小練習--GUI設計

再次點選則收回來

python小練習--GUI設計
練習3:滑鼠事件和鍵盤事件用法

  一個 GUI 應用整個生命周期都處在一個消息循環 (event loop) 中。它等待事件的發生,并作出相應的處理。Tkinter 提供了用以處理相關事件的機制. 處理函數可被綁定給各個控件的各種事件。widget.bind(event, handler)如果相關事件發生, handler 函數會被觸發, 事件對象event 會傳遞給 handler 函數.

滑鼠和鍵盤事件:

python小練習--GUI設計

event 對象常用屬性:

python小練習--GUI設計
from tkinter import *

Clichong = Tk()
Clichong.geometry("600x400+300+300")

bt1 = Button(Clichong,bg="blue",text="bt1").place(x=50,y=120,width=50,height=20)
#lb1 = Label(Clichong,bg="pink").place(x=300,y=100,width=100,height=30)

c1 = Canvas(Clichong,width=50,height=50,bg="pink")
c1.place(x=50,y=20)
c2 = Canvas(Clichong,width=200,height=200,bg="orange")
c2.place(x=120,y=20)

# 列印相關資訊,測試event 對象常用屬性
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))
    print("event.type:{0}".format(event.type))
    print("event.width:{0},event.height:{1}".format(event.width,event.height))

penfont=2         # 設定畫筆的粗細
def mouseDrag(event):
    # 不斷的畫圓,看上去像是畫筆,但是event.x+var加大了就知道是個圓
    c2.create_oval(event.x, event.y, event.x+penfont, event.y+penfont)

# 鍵盤任意按鍵觸發事件,列印按下的鍵盤鍵,測試event 對象常用屬性
def keyboardTest(event):
    print("按鍵keycode:{0}\n按鍵char:{1}\n按鍵keysym:{2}\n".format(event.keycode,event.char,event.keysym))

# 按鍵A/a測試
def keyboardTest_A(event):
    print("your press A/a")
def keyboardTest_DoubleA(event):
    print("your press A/a twice times")
def keyboardTest_CtrlA(event):
    print("your press ctrl+A/a")

# 進入c2元件區域測試
def enterTest(event):
    print("event_x:{0},event_y:{1}".format(event.x_root,event.y_root))

# 點選觸發事件
c1.bind("<Button-1>",mouseTest)

# 拖動觸發事件
c2.bind("<B1-Motion>",mouseDrag)

# 鍵盤觸發事件,一個個測試
# 一般來說,鍵盤的按鍵都是綁定主界面
Clichong.bind("<KeyPress>",keyboardTest)
Clichong.bind("<KeyPress-a>",keyboardTest_A)
Clichong.bind("<KeyPress-A>",keyboardTest_A)
Clichong.bind("<Double-KeyPress-a>",keyboardTest_DoubleA)
Clichong.bind("<Control-KeyPress-a>",keyboardTest_CtrlA)

# 滑鼠指針進入某一元件區域測試
c2.bind("<Enter>",enterTest)

Clichong.mainloop()
           
python小練習--GUI設計
練習4:lambda 表達式實作傳參

lambda 表達式定義的是一個匿名函數,隻适合簡單輸入參數,簡單計算傳回結果,不适合功能複雜情況。lambda 定義的匿名函數也有輸入、也有輸出,隻是沒有名字。

文法格式如下:lambda 參數值清單:表達式

  • 參數值清單即為輸入。
  • 表達式計算的結構即為輸出。
    python小練習--GUI設計
from tkinter import *

Clichong = Tk()
Clichong.geometry("270x100")

def MyTest(str1,str2):
    print(str1,"make friend with",str2)

# 使用lambda關鍵字可以實作傳遞多個參數操作
Button(Clichong,text="bt1",command=lambda :MyTest("Clichong","Lawrence")).pack()

t1 = lambda x,y:x**y
t2 = lambda :MyTest("A","B")
print("t1(2,3):",t1(2,3),"\n","MyTest(A,B)",t2)

Clichong.mainloop()
           
python小練習--GUI設計
練習5:多種事件綁定方式
  • 元件對象的綁定
  1. 通過 command 屬性綁定(适合簡單不需擷取 event 對象)

    Button(root,text=”登入”,command=login)

  2. 通過 bind()方法綁定(适合需要擷取 event 對象)

    c1 = Canvas(); c1.bind(“”,drawLine)

ps:

command方式綁定,不能直接擷取event 對象" "

bind方式綁定,可以擷取 event 對象" "

  • 元件類的綁定

調用對象的 bind_class 函數,将該元件類所有的元件綁定事件:w.bind_class(“Widget”,”event”,eventhanler)

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

參考前面撲克出牌的小例子:

from tkinter import *

Clichong = Tk()
Clichong.geometry("600x400+300+300")

myphoto = [PhotoImage(file="photo/puke/puke"+str(pukenumber+1)+".gif")for pukenumber in range(10)]
mypuke = [Label(Clichong,image=myphoto[i])for i in range(10)]

for i in range(10):
    mypuke[i].place(x=50+40*i,y=130)
    
def pukeoutfunction(event):
    print(event.widget.winfo_geometry())    
    print(event.widget.winfo_y())         
    if event.widget.winfo_y() == 130:
        event.widget.place(y=80)
    else:
        event.widget.place(y=130)

# 對label事件點選的綁定出牌操作,bind_class直接綁定label這整一類
mypuke[1].bind_class("Label","<Button-1>",pukeoutfunction)

Clichong.mainloop()
           
練習6:OptionMenu 選擇項

介紹:

class OptionMenu(Menubutton):
    """OptionMenu which allows the user to select a value from a menu."""
    def __init__(self, master, variable, value, *values, **kwargs):
        """Construct an optionmenu widget with the parent MASTER, with
        the resource textvariable set to VARIABLE, the initially selected
        value VALUE, the other menu values VALUES and an additional
        keyword argument command."""
        kw = {"borderwidth": 2, "textvariable": variable,
              "indicatoron": 1, "relief": RAISED, "anchor": "c",
              "highlightthickness": 2}
           

測試:

from tkinter import *

Clichong = Tk()
Clichong.geometry("400x300+300+300")

# 設定變量,友善回去選擇項擷取的内容,與其他空間類型操作
opmfirstvar = StringVar()
opmfirstvar.set("蔬菜面")
opm1 = OptionMenu(Clichong,opmfirstvar,"蔬菜面","蘭州拉面","豚骨拉面","地獄拉面")
opm1.place(x=50,y=30,width=120,height=40)

def ShowLabel():
    print(opmfirstvar.get())

bt1 = Button(Clichong,width=3,command=ShowLabel).place(x=50,y=100)

Clichong.mainloop()

           
python小練習--GUI設計
練習7:Scale移動滑塊

介紹:

class Scale(Widget):
    """Scale widget which can display a numerical scale."""
    def __init__(self, master=None, cnf={}, **kw):
        """Construct a scale widget with the parent MASTER.

        Valid resource names: activebackground, background, bigincrement, bd,
        bg, borderwidth, command, cursor, digits, fg, font, foreground, from,
        highlightbackground, highlightcolor, highlightthickness, label,
        length, orient, relief, repeatdelay, repeatinterval, resolution,
        showvalue, sliderlength, sliderrelief, state, takefocus,
        tickinterval, to, troughcolor, variable, width."""
        Widget.__init__(self, master, 'scale', cnf, kw)
           

測試:

from tkinter import *

Clichong = Tk()
Clichong.geometry("400x300")

lb1 = Label(Clichong,text="Clichong",width=10,height=2,font=("宋體",20))
lb1.pack()
# label不支援以下的操作:TypeError: 'NoneType' object does not support item assignment
# lb1["font"] = ("宋體",20)

# 通過函數傳遞目前值
def mytest(value):
    print(value)
    newFont = ("黑體", value)
    lb1.config(font=newFont)

sc1 = Scale(Clichong,from_=10,to=100,length=300,width=30,command=mytest)
# 元件Scale可以支援如下操作
sc1["orient"] = HORIZONTAL
sc1.pack()

Clichong.mainloop()
           

未調整前:

python小練習--GUI設計

調整之後:

python小練習--GUI設計
練習8:字型動态調整的方法測試

基于以上字型調整失敗,此部分再次進行調試

from tkinter import *

Clichong = Tk()
Clichong.geometry("400x300")

lb1 = Label(Clichong,text="Clichong",width=10,height=2,font=("宋體",20))
lb1.pack()

# 經測試,以下兩種動态調整字型的方法都可以
def func1():
    lb1["font"] = ("黑體", 40)
def func2():
    lb1.config(font=("黑體",30))

bt1 = Button(Clichong,command=func1).pack(side="left")
bt2 = Button(Clichong,command=func2).pack(side="left")
Clichong.mainloop()
           

按鈕1:

python小練習--GUI設計

按鈕2:

python小練習--GUI設計
練習9:顔色選擇框基本用法

顔色選擇框可以幫助我們設定背景色、前景色、畫筆顔色、字型顔色等等。

# 顔色選擇框

from tkinter import *
from tkinter.colorchooser import *

Clichong = Tk()
Clichong.geometry("400x300")

def mytest():
    # 設定初始選擇的顔色是綠色,顔色框标題是"My color"
    cr = askcolor(color="green",title="My color")
    # 得出的結果是((128.5, 255.99609375, 255.99609375), '#80ffff')
    print(cr)

    # 設定背景顔色,以下兩種方法均可
    Clichong["bg"] = cr[1]
    Clichong.config(bg = cr[1])

Button(Clichong,text="選擇背景色",command=mytest).pack()

Clichong.mainloop()
           

調出顔色選擇框:

python小練習--GUI設計

點選确定更換背景色

python小練習--GUI設計
練習10:檔案對話框基本用法

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

python小練習--GUI設計
python小練習--GUI設計

命名參數 options 的常見值如下:

python小練習--GUI設計

測試1:傳回選擇好的檔案名

# 檔案選擇框

from tkinter import *
from  tkinter.filedialog import *

Clichong = Tk()
Clichong.geometry("400x300")

def mytest():
    askfile = askopenfilename(title="My File")
    lb1["text"] = askfile

Button(Clichong,command=mytest).pack()

lb1 = Label(Clichong,width=40,height=3,bg="green")
lb1.pack()
Clichong.mainloop()
           

點選按鈕彈出檔案選擇框:

python小練習--GUI設計

選擇好後在label顯示檔案名

python小練習--GUI設計

測試2:打開指定 txt 檔案,并讀出檔案内容到視窗

# 檔案選擇框

from tkinter import *
from  tkinter.filedialog import *

Clichong = Tk()
Clichong.geometry("400x300")

def mytest1():
    askfile = askopenfilename(title="My File")
    lb1["text"] = askfile

def mytest2():
    with askopenfile(title="File") as fd:
        lb2.config(text=fd.read())

Button(Clichong,command=mytest1).pack(side="left")
Button(Clichong,command=mytest2).pack(side="left")

lb1 = Label(Clichong,width=40,height=3,bg="pink")
lb1.pack()
lb2 = Label(Clichong,width=40,height=10,bg="blue")
lb2.pack()

Clichong.mainloop()
           

測試按鈕1:

python小練習--GUI設計

輸出檔案路勁

python小練習--GUI設計

測試按鈕2:

python小練習--GUI設計

輸出檔案内容

python小練習--GUI設計
練習11:簡單輸入對話框

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

python小練習--GUI設計

參數中,title 表示視窗标題;prompt 是提示資訊;命名參數kw 為各種選項:initialvalue(初始值)、minvalue(最小值)、maxvalue(最大值)。

# 顔色選擇框

from tkinter import *
from tkinter.simpledialog import *

Clichong = Tk()
Clichong.geometry("400x300")

lb1 = Label(Clichong,width=40,height=3,bg= "green")
lb1.pack()
# Button(Clichong,text="選擇背景色",command=mytest).pack()

getstr = askinteger(title="about age",prompt="input your age",initialvalue=0,minvalue=0,maxvalue=100)
lb1.config(text=getstr)

Clichong.mainloop()
           
python小練習--GUI設計

超過100會警告:

python小練習--GUI設計
python小練習--GUI設計
練習12:通用消息框

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

python小練習--GUI設計

測試代碼:

from tkinter import *
from tkinter.messagebox import *

Clichong = Tk()
Clichong.geometry("400x300")

# box1 = askokcancel(Clichong,"你是男的女的")
# box2 = askquestion(title="問題1",message="你是男的女的")
# box3 = askyesnocancel(title="問題1",message="你是男的女的")
# box4 = showinfo(title="問題1",message="你是男的女的")
box5 = showerror(title="問題1",message="你是男的女的")

Clichong.mainloop()
           
python小練習--GUI設計
  • ttk 子子產品控件

我們再前面學的元件是 tkinter 子產品下的元件,整體風格較老較醜。為了彌補這點不足,推出了 ttk 元件。ttk 元件更加美觀、功能更加強大。使用 Combobox 替代了原來的Listbox 、 新 增 了 LabeledScale( 帶 标 簽 的 Scale) 、Notebook(多文檔視窗)、Progressbar(進度條)、Treeview(數)等元件。

使用 ttk 元件與使用普通的 Tkinter 元件并沒有多大的

差別,隻要導入 ttk 子產品即可。