天天看点

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 模块即可。