当前位置:   article > 正文

python --Tkinter详解_python tkinter

python tkinter

简介

  • 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()  # 进入事件循环
  • 1
  • 2
  • 3
  • 4
  • 5

第一个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()  # 进入事件循环
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

窗口大小和位置

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()  # 进入事件循环
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在这里插入图片描述

窗口放至屏幕中间

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

常用组件汇总

组件类关系图
请添加图片描述
在这里插入图片描述

在这里插入图片描述

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

简单组件

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='hebut\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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

Options 选项详解

通过学习 Label 组件,我们发现可以通过 Options 设置组件的属性,从而控制组件的各种状态。比如:宽度、高度、颜色、位置等等。

我们可以通过三种方式设置 Options 选项,这在各种 GUI 组件中用法都一致。

1.创建对象时,使用可变参数

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

2.创建对象后,使用字典索引方式

fred["fg"] = "red"
fred["bg"] = "blue"
  • 1
  • 2

3 创建对象后,使用 config()方法

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

如何查看组件的 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

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, "0123456789\nabcdefg")
        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!\nhebut\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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

利用 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!\nhebut\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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

布局管理器

一个 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

【示例】通过 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

【示例】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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

事件处理

一个 GUI 应用整个生命周期都处在一个消息循环 (event loop) 中。它等待事件的发生,并作出相应的处理。
Tkinter 提供了用以处理相关事件的机制. 处理函数可被绑定给各个控件的各种事件。

widget.bind(event, handler)
  • 1

如果相关事件发生, 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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

多种事件绑定方式汇总

组件对象的绑定
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

其他组件

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

颜色选择框

颜色选择框可以帮助我们设置背景色、前景色、画笔颜色、字体颜色等等。
【示例】颜色选择框基本用法

#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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

文件对话框

文件对话框帮助我们实现可视化的操作目录、操作文件。最后,将文件、目录的信息传入到程序中。文件对话框包含如下一些常用函数

在这里插入图片描述

在这里插入图片描述
【示例】文件对话框基本用法

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

【示例】打开指定 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

简单输入对话框

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

通用消息框

messagebox(通用消息框)用于和用户简单的交互,用户点击确定、取消。如下列出了 messagebox 的常见函数:

在这里插入图片描述

【示例】通用消息框的基本用法

#简单对话框
from tkinter import *
from tkinter.messagebox import *

root= Tk();root.geometry("400x100")
a1= showinfo(title="关关雎鸠",message="好好学习,天天向上")
print(a1)
root.mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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)
  • 1

2.创建菜单,并添加到主菜单栏对象

file_menu = tk.Menu(menubar)
menubar.add_cascade(label=”文件”,menu=file_menu)
  • 1
  • 2

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=”退出”)
  • 1
  • 2
  • 3
  • 4

4.将主菜单栏添加到根窗口

root[“menu”]=menubar
  • 1

【示例】记事本软件主菜单设计

#记事本软件,练习主菜单的设计
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

上下文菜单

快捷菜单(上下文菜单)是通过鼠标右键单击组件而弹出的菜单,一般是和这个组件相关的操作,比如:剪切、复制、粘贴、属性等。创建快捷菜单步骤如下:

1.创建菜单

menubar = tk.Menu(root)
menubar.add_command(label=”字体”)
  • 1
  • 2

2.绑定鼠标右键单击事件

def test(event):
	menubar.post(event.x_root,event.y_root) # 在鼠标右键单击坐标处显示菜单 
	root.bind(“<Button-3>”,test)
  • 1
  • 2
  • 3

【示例】为记事本程序增加快捷菜单

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

最后一种布局方法是 place,它直接指定元素在父元素中的坐标值,单位是像素。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/124883
推荐阅读
相关标签
  

闽ICP备14008679号