Python-Tkinter学习笔记

这篇博客详细介绍了使用Python的Tkinter库进行GUI编程,包括组件的通用写法、布局管理器grid、pack和place的使用,以及事件机制、对话框和菜单栏等高级功能。通过实例解析了label、button、Entry、Text、单选框、多选框等组件的创建与交互,是学习Tkinter的实用教程。

1、一个通用对的GUI模板界面

from tkinter import *
from tkinter import messagebox


# frame 组件是一个容器,可以用来放置其他的组件

class Application(Frame):
    def __init__(self, master):
        super().__init__(master=master)
        self.master = master
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        pass


if __name__ == '__main__':
    root = Tk()
    root.geometry('300x400+100+100')
    app = Application(root)
    app.mainloop()

2、组件继承关系与字符尺寸&字符尺寸

3、 button组件的通用写法

# 导入配置文件;
# in-config: text = 'text'
import config

# 第一种写法
b1 = Button(self)
b1[config.text] = 'HelloWorld'
b1[config.command] = self.say_hai
b1.pack(side='top')

# 第二种写法
q = Button(self, text='Quit', fg='red', command=self.master.destroy)
q.pack(side='bottom')


# 利用anchor属性可以实现对组件内部的样式控制
# 主要由 英语单词 东南西北 首字母进行控制的 'eswn'

# 也就是说,当组件的尺寸过大时,我们可以控制组件内部的样式

self.master.destroy 指向的是自己的父级窗口被销毁的函数。
如果是父级窗口被销毁,那么子窗口也会被销毁 

在tkinter里面,任意一个组件都可以被认为是一个‘窗口’, 也就是意味着其他的窗口组件也可以添加到这个窗口上。

pack布局如果不传入参数,默认的是center居中布局 pack的其他参数 side=‘left’,这个有点像css里面的:display:flex;justfy-content:start;样式。

4、label组件的通用写法

# 换一种写法,自己想怎么写都随意
# 先定义一个样式列表
l2c = {
            config.text: '高旗老师\n哈哈哈\nbui',
            config.width: 10,
            config.height: 3,
            config.bg: 'white',
            config.foreground: config.color_orange,
            config.font: ('黑体', 14),
            config.justify: config.justify_right,
            config.relief: config.relief_groove,
            config.borderwidth: 1,
        }

# 创建一个label组件
l2 = Label(self)
l2.config(**l2c)
l2.pack()

# 将photo定义为全局变量
global photo
photo = PhotoImage(file='path/to/your/photo/img')
l3 = Label(self, image=photo)
l3.pack()

label组件的中可以传入一张 tkinter-img 的tk图片对象,然后将图片对象渲染到label组件。图片对象必须要借助PhotoImage类来实例化,然后将label标签里面的image属性的值设置为该实例对象,要注意的是传入的图片大小和宽度不能修改,但是可以借助PIL图像处理库帮助完成,其方法是先将图片转化大小,然后再进行tk图像实例化。

实例化的图片对象必须是一个全局变量,因为mainloop事件循环里面在不断的进行更新事件

5、Entry单行文本输入框

e1 = Entry(self)
self.v1 = StringVar()
self.v1.set('admin')
# 双向关联绑定
e1[config.textvariable] = self.v1
e1.pack()

首先要设置一个StringVar()对象,这个是tk内置的一个字符类,里面设置了setter以及getter方法,也就是只可以通过这两种方法来设置和访问属性

其次将label组件中的textvariable属性绑定到字符的实例对象上,然后实现数据的双向绑定

6、多行文本输入框Text

# 创建一个多行文本的输入框
self.t1 = Text(self, width=40, height=12, bg=config.color_gray)
self.t1.pack()


# 普通文本通过索引值的插入
# 行的索引值是从1开始的,列的索引值是从0开始的
self.t1.insert(1.0, '0123456789\n9876543210')
# 从第二行,第四列开始的
self.t1.insert(2.3, '楚河日耽误,旱地和下图,谁知盘中惨,丽丽姐幸苦')

# 普通文本通过特殊的方式插入
# INSERT 表示在光标插入的地方输入
self.t1.insert(INSERT, ' Gaoqi')
# END  表示在段落结束的地方插入
self.t1.insert(END, '[sxt]')

# 文本的获取
# 核心,行号是从 1 开始的, 列号是从 0 开始的
text = self.t1.get(1.2, 1.6)
texts = self.t1.get(1.2, END)

# 向输入框中添加一个图片(图片的本质也是文本)
self.photo = PhotoImage(file='./unit.png')
self.t1.image_create(END, image=self.photo)

# 向text文本框中添加一个按钮组件
b1 = Button(self.t1, text='这是动态添加的按钮')
self.t1.window_create(INSERT, window=b1)

# 删除文本
self.t1.delete(1.0, END)

# 段落标记
# 选定段落。创建一个标记
self.t1.tag_add('good', 1.0, 1.9)
# 给标记绑定相关的样式
self.t1.tag_config('good', background=config.color_yellow, foreground=config.color_red)
# 给标记的样式绑定一个事件
self.t1.tag_bind('good', '<Button-1>', callback)

多行文本输入框获取文本用get方法;插入文本用insert方法;添加图片用image_create方法;添加组件用window_create方法;删除文本用delete方法;

段落标记指的是对想要的段落进行标记,其中别标记的段落会有一个标记别名,可以通过别名来实现是对标记段落的样式的更改,同时也可以通过标记名称为相关的段落绑定相应事件。

多行文本输入框中,行是从1开始的,列是从0开始的。也就说,如果我现在给你一个索引值1.5:那么表示的是从第一行的第六个元素开始

 7、ratio-button单选框

self.v = StringVar()
self.v.set('v')

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)

这里唯一需要注意的是,单选框设置的属性名为 variable,并且指向的值必须是同一个内存地址(也就是必须是同一个变量), Entry单行文本输入框中设置的是textvaiable,两者设置的属性名称是不同的,同时这里也需要指定value属性,表示选中后的值。

8、check-button多选文本输入框

# 创建两个字符变量, 创建后默认值为0
self.code_hobby = IntVar()
self.video_hobby = IntVar()

# 创建两个多选输入框
self.c1 = Checkbutton(self, text='敲代码', variable=self.code_hobby, onvalue=1, offvalue=0)
self.c2 = Checkbutton(self, text='看视屏', variable=self.video_hobby, onvalue=1,offvalue=0)

# 布局
self.c1.pack(side=left)
self.c2.pack(side=left)

多选输入框要分别为每一个输入框创建一个单独的变量,将变量分别绑定绑定到variable属性身上,同时设置onvalue and offvalue 来表示选中以及未选中时的值,读取数据时也只能通过变量的get方法一个一个进行读取。

9、canvas画布操作

self.canvas = Canvas(self, width=300, height=200, bg=color_green)
self.canvas.pack()
# 画一条直线, 这里的直线一共被分为了2个线段,因为两点确定一条直线
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='./unit.png')
self.canvas.create_image(150, 70, image=photo)

canavs画布,和h5中的canvas差不多,都可以调用api在画布上绘制图形。这里的canvas不但可以绘制直线,椭圆(绘制的椭圆是矩形的内切圆,如果矩形为正方形,那么绘制的圆形就是标准圆),还可以将图片添加到画布中,同样还是先初始化图片对象,然后绑定到画布中。

10、布局管理器-grid

"""
# grid  网格布局管理器,来实现网格布局, 可以将我的的组件放到单元格中,可以跨行也可以跨列 (int)
# column 单元格列号, 从0开始的正整数 (int)
# columnspan 跨列,列的正整数 (int)
# row 单元格的行号,跨行 (int)
# roespan 同理可得 (int)

# ipadx 设置组件内部的布局间隔, 相当于css中的pading
# padx 设置组件之间的间  隔,相当于css中的margin
# sticky 组件紧贴在单元格子的某一角度,对应的值为东南西北中以及四个角,nswe 等,默认center
        """

'''提过grid布局来实现登录界面'''
l1 = Label(self, text='用户名')
l1.grid(row=0, column=0)
e1 = Entry(self)
e1.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, padx=30)
Button(self, text='取消').grid(row=2, column=2, sticky=E)

gird顾名思义就是网格的意思,换一句话说就是通过网格来布局。可以将网格布局理解为将组件放到类似于excel的单元格中,其中主要通过row 和 column 来对布局排版,row 和 column的初始值都为0,也就是说(0,0)表示的是左上角第一个单元格。同时还有其他属性可以选择,例如ipadx:组件的内边距(css中的padding),padx:组件的外边距(相对于单元格的边框)(css中的margin),但这是里x和y方向上的边距或间隔是相同的。

11、布局管理器- pack

"""
pack 布局
expand:当值为 ‘yes’时,side选项是无效的,组件显示在父组件中心位置
        此时如果fill选项为both时,填充父组件的剩余空间
        (”yse", "no", 默认值为 'no')
fill: 填充x或者y方向上的空间,
        当属性side=‘top'或者’bottom'时填充x方向
        当属性side=‘left'或者’right'时填充y方向
        当属性expand=‘yes’时,填充剩余的空间
        ('x', 'y', 'both', 'none', 默认值为 'none')
ipadx:padding (float)
padx: margin (float)
side:停靠在那一边 (‘left', 'right', 'top', 'bottom', 默认值为’top')
anchor: 组件内部文字对其的方式,东南西北以及四个方向,默认为 center

pack 适用于简单的垂直或水平布局, 这里实现了一个钢琴布局
"""

root = Tk()
root.geometry('700x220')

f1 = Frame(root)
f1.pack()

f2 = Frame(root)
f2.pack()

btnTexts = ['刘晓峰', '中国风', '日本分', '重金属', '轻音乐']

for btnText in btnTexts:
    Button(f1, text=btnText).pack(side='left', padx='10')

for i in range(1, 20):
    Label(f2, width=5, height=10, borderwidth=1, relief=relief_solid,
          bg='black' if i % 2 == 0 else 'white').pack(side='left', padx=2)


root.mainloop()

pack布局一般不会涉及到太多的属性,主要用于整体大致的水平布局或者垂直布局,水平布局一般用pack(side=‘left’),垂直布局直接pack()就行

12、布局管理器place

from tkinter import *
from config import *


"""
place 布局管理器

x, y: 相对于跟组件的绝对坐标, (单位是像素)

relx, rely: 相对于父组件的坐标 (单位是比例, 位于0到1之间)

width, height: 组件的宽度和高度 (单位是像素)

relwidth, relheight: 组件的相对宽度以及高度,相对于父组件来说, 是一个比例

如果同时设置了相对定位和绝对定位,那么实际的定位会在原来定位的基础上进行累加

anchor: 文字的对其方式,东南西北加四个方位

"""

root = Tk()
root.title('布局管理')
root[bg] = color_white
root.geometry('500x300')

# 布局一个frame组件
f1 = Frame(root, width=200, height=200, bg=color_green)
f1.place(x=30, y=30)

Button(root, text='尚学堂').place(relx=0.2, x=100, y=20, relwidth=0.2, relheight=0.5)
Button(f1, text='高旗老手').place(relx=.6, rely=.7)
Button(f1, text='百战程序员').place(relx=.5, rely=.2)

root.mainloop()

plcae布局管理器可以直接对被plcae的组件进行设置宽度以及高度,单位是像素,这样就可以不用在组件上设置宽度和高度,直接在place管理器上设置即可。

13、 事件机制以及消息循环原理

"""
一个GUI应用在整个周期里都处于在一个消息循环里面
他等待事件的发生,然后做出相应的处理

tk里面提供了相关的事件机制,处理函数可以绑定到控件
从而形成一个处理事件
mainloop() 里面包括了一个消息循环(while True)
专门来监听事件,这里mainloop开启的是一个线程
事件可以是鼠标,键盘,同时还包括GUI的画面渲染

所有的组件都有 widget.bind(event, handler) 绑定
同一个组件可以绑定多个事件
event:
    <Button-1> / <1> / <ButtonPress-1>: 鼠标左键按下, 2表示中建, 3表示右键
    <ButtonRelease-1>: 鼠标左键释放
    <B1-Motion>: 按住鼠标左键移动
    <Double-Button-1>: 双击左键
    <Enter>:  鼠标指针进入某一区域
    <Leave>:  鼠标指针离开莫伊区域
    <MouseWheel>: 滚动鼠标滚轮
    <KeyPress-a>:  按下a键
    <KeyRelease-a>:  释放a键
    <KeyPress-A>: 按下A键
    <Alt-KeyPress-A>:  按下 alt + A
    <Double-KeyPress-A>: 快速按两下A
    <Control-V>: control和V同时被按下
    以上末尾的字符可以替换为其他的字符


event 对象常用的属性
    char; 按键字符,只对键盘事件有效
    keycode:按键编码,只对键盘事件有效
    keysym:按键的名称
        比如此时按下的是空格
            char '' ; keycode 32 ; keysym space
    num: 鼠标按键,只对鼠标有用
    type: 触发事件的类型
    widget: 引起事件的组件
    width,height: 组件改变后大小,只有Configure 有效
    x, y : 鼠标当前的位置
    x_root, y_root : 鼠标当前的位置,相对于整个屏幕(用户计算机屏幕)的位置
"""

14、option-menu选择菜单

from tkinter import *
from config import *

root = Tk()
root.geometry('200x100')

v = StringVar(root)
v.set('程序员')

om = OptionMenu(root, v, '程序员', '机器人', '蒸汽机')
om['width'] = 10
om.pack()

Button(root, text='确定', command=lambda: print('选中的值为: %s' % v.get()), width=10).pack()

root.mainloop()

选择菜单简单来说就是一个选择下拉框,点击按钮后会出现选择下拉选项。选择下拉框需要一个双向绑定的变量来储存被选择的值。可以通过回调函数来处理选择相应的值后执行相应的操作。

15、scale滑块

from tkinter import *
from config import *

a: Label


def bc(value_):
    print('滑块的值:', value_)
    new_font = ('宋体', value_)
    a.config(font=new_font)


root = Tk()
"""
from_: 设置起始的位置
to:设置终止的位置
length: 设置width宽度,默认为像素
orient: 设置布局的方向
"""
s1 = Scale(root, from_=10, to=50, length=300, tickinterval=5, orient=HORIZONTAL, command=bc)
s1.pack()

a = Label(root, text='你好啊', width=10, height=1, bg=color_black, fg=color_white)
a.pack()


root.mainloop()

滑块就是类似于看视屏的进度条,每一次值的改变都会执行回调函数,在这里不需要变量来储存值,而是直接将值传入回调函数。

16、颜色选择框

from tkinter import *
from tkinter.colorchooser import *
from config import *


root = Tk()
root.geometry('400x500')

def test():
    s1 = askcolor(color=color_red, title='选择背景颜色')
    print(s1)
    # s1 的值为 ((0.0, 0.0, 255.9), ‘#0000ff’)
    root.config(bg=s1[1])


Button(root, text='选择背景颜色', command=test).pack()


root.mainloop()

17、文件对话框

from tkinter import *
from tkinter.filedialog import *
from config import *

"""
文件对话框
    askopenfilename: 返回打开的文件名(是一个文件目录)
    askopenfilenames: 返回打开的多个文件的文件名
    askopenfile: 返回打开的文件对象(是一个文件句柄)
        with askopenfile(**options) as f:
            contents = f.read()
    askopenfiles: 返回打开的多个文件对象的列表

目录对话框
    askdirectory: 返回目录的名称

保存对话框
    asksaveasfile: 返回保存的文件对象
    asksaveasfilename: 返回保存的文件名

参数:
    defaultextension: 默认后缀 .xxx
    filetypes=[(label1, pattern1), ... ] 文件显示过滤器
    initialdir: 初始化目录
    parent: 父窗口,默认跟窗口
    title:窗口的标题
"""


def test():
    f = askopenfilename(title='上传文件', initialdir='d:', filetypes=[('视频文件', '.mp4')])
    show['text'] = f
    print(f)


root = Tk()

Button(root, text='查看文件目录', command=test).pack()
show = Label(root, text='...', width=10, height=2, bg=color_green, fg=color_red)
show.pack()

root.mainloop()

18、简单的的输入对话框

from tkinter.simpledialog import *

root = Tk()
root.geometry('400x100')


def test():
    a = askinteger(title='输入年龄', prompt='请输入年龄', initialvalue=18, minvalue=1, maxvalue=150)
    print('输入的年龄是:', a)


Button(root, text='测试', command=test).pack()

root.mainloop()

19、消息弹出框

from tkinter import *
from tkinter.messagebox import *
from config import *

"""
askokcancel: OK、cancel对话框
askquestion: 问题对话框
askretrycancle: 问题对话框
showerror: 问题对话框
showinfo: 消息框

参数:title, msg, 
"""

root = Tk()

showinfo('info', 'this is a info')

root.mainloop()

20、菜单栏Menu-bar

# 创建主菜单兰
menu_bar = Menu(root)

# 创建子菜单栏
menu_file = Menu(menu_bar)
menu_edit = Menu(menu_bar)
menu_help = Menu(menu_bar)

# 将子菜单添加到主菜单栏目
menu_bar.add_cascade(label='文件', menu=menu_file)
menu_bar.add_cascade(label='编辑', menu=menu_edit)
menu_bar.add_cascade(label='帮助', menu=menu_help)

# 向子菜单栏目中添加选项
menu_file.add_command(label='新建', accelerator='ctrl+n', command=self.test)
menu_file.add_command(label='打开', accelerator='ctrl+o', command=self.test)
menu_file.add_command(label='保存', accelerator='ctrl+s', command=self.test)
# 添加一个分界线
menu_file.add_separator()
menu_file.add_command(label='退出', accelerator='ctrl+q', command=self.test)

# 将主菜单栏添加到跟窗口
root['menu'] = menu_bar

21、上下文菜单(鼠标右键点击显示)

# 创建上下文菜单
context_menu = Menu(root)
context_menu.add_command(label='背景颜色', command=test)

# 向根窗口绑定事件
root.bind('<Button-3>', create_context_menu)

def create_context_menu(event):
     self.context_menu.post(event.x_root, event.y_root)

22、config.py文件

# ================================ STANDARD OPTIONS ====================================
activebackground = 'activebackground'
activeforeground = 'activeforeground'
anchor = 'anchor'   # 设置组件内部文字定位的方式(可以是按钮)
anchor_top = 'n'
anchor_top_right = 'ne'
anchor_right = 'e'
anchor_bottom_right = 'se'
anchor_bottom_left = 'sw'
anchor_left = 'w'
anchor_top_left = 'nw'
anchor_center = 'center'
background = 'background'
bitmap = 'bitmap'
borderwidth = 'borderwidth'     # 用来设置边框的宽度,单位为像素
cursor = 'cursor'
disabledforeground = 'disabledforeground'
font = 'font'
foreground = 'foreground'
file = 'file'
highlightbackground = 'highlightbackground'
highlightcolor = 'highlightcolor'
highlightthickness = 'highlightthickness'
image = 'image'
justify = 'justify'     # 用来设置文字的对其方式
justify_left = 'left'
justify_right = 'right'
justify_center = 'center'
padx = 'padx'
pady = 'pady'
relief = 'relief'   # 专门用来设置组件的三D效果
relief_flat = 'flat'
relief_groove = 'groove'
relief_raised = 'raised'
relief_ridge = 'ridge'
relief_solid = 'solid'
relief_sunken = 'sunken'
repeatdelay = 'repeatdelay'
repeatinterval = 'repeatinterval'
takefocus = 'takefocus'
text = 'text'
textvariable = 'textvariable'
underline = 'underline'
wraplength = 'wraplength'

exportselection = 'exportselection'
insertbackground = 'insertbackground'
insertborderwidth = 'insertborderwidth'
insertofftime = 'insertofftime'
insertontime = 'insertontime'
insertwidth = 'insertwidth'
invalidcommand = 'invalidcommand'
invcmd = 'invcmd'
selectbackground = 'selectbackground'
selectborderwidth = 'selectborderwidth'
selectforeground = 'selectforeground'
show = 'show'
validate = 'validate'
validatecommand = 'validatecommand'
vcmd = 'vcmd'
xscrollcommand = 'xscrollcommand'

fg = foreground
bg = background
bd = borderwidth
left = justify_left
right = justify_right

# ================================ WIDGET-SPECIFIC OPTIONS ====================================
command = 'command'
compound = 'compound'
default = 'default'
height = 'height'
overrelief = 'overrelief'
state = 'state'
state_disabled = 'disabled'
state_active = 'active'
state_normal = 'normal'
width = 'width'

value = ''
variable = ''
side = ''
onvalue = ''
offvalue = ''
row = ''
column = ''
sticky = ''
relx = ''
rely = ''
relwidth = ''
relheight = ''
from_ = ''
to = ''
length = ''
tickinterval = ''
orient = ''
title = ''
# ======================================= COLOR OPTIONS =======================================

color_red = 'red'
color_black = 'black'
color_pink = 'pink'
color_blue = 'blue'
color_white = 'white'
color_green = 'green'
color_purple = 'purple'
color_yellow = 'yellow'
color_orange = 'orange'
color_gray = 'gray'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值