Python记8(tkinter

目录

1、参考:

2、窗口:

2.1、创建窗口 Tk()、长宽geometry()、屏幕宽高、拉伸窗口resizable()、窗口名title()、循环mainloop()、获取窗口大小:

from tkinter import *

root = Tk()                     # Tk():实例化tk类,需配合后面root.mainloop()才能循环显示弹框

width, height = root.winfo_screenwidth(), root.winfo_screenheight() # 获取屏幕宽度和高度:1280, 720

# .geometry():宽300,长60,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.geometry('300x60+500+300')

root.resizable(False, False)    # 不准拉伸(宽,高)
root.title('这是title')          # .title():设置弹框名称
root.mainloop()                 # mainloop()    :循环弹窗

运行得到:
在这里插入图片描述

  • 获取窗口大小:
from tkinter import *

root = Tk(); root.geometry('300x60+500+300'); root.title('这是title')


print("循环前窗口宽{}\t高{}".format(root.winfo_width(), root.winfo_height()))  # 循环前窗口宽1	高1

def Btn1_fun():
    print("窗口宽{}\t高{}".format(root.winfo_width(), root.winfo_height()))     # 窗口宽300	高60

Button(root, text="按钮1", command=Btn1_fun).pack()       # 点击按钮就执行 Btn1_fun()


root.mainloop()                 # mainloop()    :循环弹窗

# 输出:
循环前窗口宽11
窗口宽30060

关于侦听窗口大小变化,参见后面 事件处理相关内容

2.2、窗口最大化/最小化/正常显示 state()、iconify()、attributes

from tkinter import * 
from tkinter.filedialog import askopenfilename
import time

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

root.state('icon')                      # icon:窗口最小化显示,normal:正常显示,zoomed:最大化

print(root.state())                     # state()没有参数可以返回窗口状态,打印:icon

# 另外最小化可以使用root.iconify() 

# 可以使用attributes属性最大化窗口显示,但是会连窗口标题和电脑任务栏都覆盖掉:
root.attributes("-fullscreen", True)
print(root.state())                     # 打印:zoomed

# 循环弹窗
root.mainloop()

2.3、隐藏、显示窗口

(隐藏之后不知道在哪里找回,以后学到再更新)
root.withdraw()可将根窗体隐藏,其作用是将窗体移动到另一个地方但并不销毁它。
root.deiconify()还原窗口

2.4、关闭窗口

在这里插入图片描述

from tkinter import *
from tkinter.messagebox import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    if askokcancel("退出", "确认退出程序吗?"):
        root.destroy()
        
root.protocol("WM_DELETE_WINDOW", fun)

root.mainloop()

2.5、其他设置

函数名解析
root.iconbitmap(“图标路径”)设置窗口图标
root.update()刷新窗口
root.after(second,command)自动触发事件,表示多少秒以后自动执行command
root.maxsize()设置窗体大小最大值(不带参数时获取最大值)
root.minsize()设置窗体大小最小值(不带参数时获取最小值)
root.attributes(“-toolwindow”, True)设置为工具窗口(没有最大最小按钮)
root.attributes(“-topmost”, True)使窗口保持处于顶层
root.attributes(’-transparentcolor’,‘blue’)设置透明色,blue可替换其他颜色
root.attributes(’-alpha’,0.5)设置窗口透明度,0~1之间
root[‘background’]=‘blue’设置窗口背景色,blue可替换其他颜色
root.overrideredirect(True)隐藏窗口边框和标题栏(缺点:脱离windows窗口管理,窗口也不会出现在任务栏,且无法设置最大化、最小化,否则会报错)
root.resizable(True,True)设置窗口x,y方向的可变性(也可设0或1等)
root.winfo_screenwidth()
root.winfo_screenheight()
获取屏幕分辨率(屏幕的高和宽)

3、Label标签:

显示文本/图像

3.1、3种设置属性的方式:

本质上都是操作键值对

3.1.1、创建时初始化:fred = Button(self, fg=“red”, bg=“blue”)

class Label(Widget):
    """Label widget which can display text and bitmaps."""

    def __init__(self, master=None, cnf={}, **kw):
        """Construct a label widget with the parent MASTER.

        STANDARD OPTIONS

            activebackground, activeforeground, anchor,
            background, bitmap, borderwidth, cursor,
            disabledforeground, font, foreground,
            highlightbackground, highlightcolor,
            highlightthickness, image, justify,
            padx, pady, relief, takefocus, text,
            textvariable, underline, wraplength

        WIDGET-SPECIFIC OPTIONS

            height, state, width

        """
        Widget.__init__(self, master, 'label', cnf, kw)
  • 看初始化函数参数列表,传递master、字典对象cnf、关键字参数(也就是**kw)
  • 下文示例代码:Label(root,text=“这是Label的文本” , font=(‘黑体’,15))
    root就是self,“text=“这是Label的文本” , font=(‘黑体’,15)”都被**kw接收为字典的键值对
  • 改为:Label(root, dict(text=“这是Label的文本” , font=(‘黑体’,15)))
    root是self,dict(text=“这是Label的文本” , font=(‘黑体’,15))被cnf接收
  • 调用父类 Widget的初始化函数:
Widget.__init__(self, master, 'label', cnf, kw)
  • 然后,Widget类继承BaseWidget类(这里没看得很明白)
class Widget(BaseWidget, Pack, Place, Grid):
    """Internal class.

    Base class for a widget which can be positioned with the geometry managers
    Pack, Place or Grid."""
    pass
  • BaseWidget类
class BaseWidget(Misc):
    """Internal class."""

	def _setup(self, master, cnf):
		这里省略...
		
	def __init__(self, master, widgetName, cnf={}, kw={}, extra=()):
        """Construct a widget with the parent widget MASTER, a name WIDGETNAME
        and appropriate options."""
        if kw:		# 逻辑:如果kw存在,就将cnf, kw合并merge
            cnf = _cnfmerge((cnf, kw))
        self.widgetName = widgetName
        BaseWidget._setup(self, master, cnf)
        if self._tclCommands is None:
            self._tclCommands = []
        classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)]
        for k, v in classes:
            del cnf[k]
        self.tk.call(
            (widgetName, self._w) + extra + self._options(cnf))
        for k, v in classes:
            k.configure(self, v)

3.1.2、字典索引方式:fred[“fg”]=“red” # fred[“bg”]=“blue”

部分IDE按Ctrl后点击“label[“bg”] = “yellow””的中括号可进入__init__.py文件,实际调用了:

def __setitem__(self, key, value)
===> def configure(self, cnf=None, **kw):
===> def _configure(self, cmd, cnf, kw):

class Misc:
	省略。。。
    def __setitem__(self, key, value):
        self.configure({key: value})
    
    def configure(self, cnf=None, **kw):
        """Configure resources of a widget.

        The values for resources are specified as keyword
        arguments. To get an overview about
        the allowed keyword arguments call the method keys.
        """
        return self._configure('configure', cnf, kw)
            
   	def _configure(self, cmd, cnf, kw):
        """Internal function."""
        if kw:  # 参见2.1.1.1创建时初始化,都是将2个字典cnf、kw融合
            cnf = _cnfmerge((cnf, kw))
        elif cnf:
            cnf = _cnfmerge(cnf)
        if cnf is None:
            return self._getconfigure(_flatten((self._w, cmd)))
        if isinstance(cnf, str):
            return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))

调用:self.configure({key: value})

3.1.3、 config()方法:fred.config(fg=“red”, bg=“blue”)

class Misc:

    def configure(self, cnf=None, **kw):
        """Configure resources of a widget.

        The values for resources are specified as keyword
        arguments. To get an overview about
        the allowed keyword arguments call the method keys.
        """
        return self._configure('configure', cnf, kw)

	config = configure # config方法就是self.configure

3.2、常用属性:

属性描述
width,height若是文本,则单个英文字符为1单位(汉字占2字符);若是图像,则以1像素为1单位。默认值是根据所显示具体内容动态调整
font字体、字体大小,(font_name, size)
image图像,目前仅仅支持gif格式
fg、bg前景色(foreground)、背景色(background)
justify文字对齐方式,如:“left” “right” “right”

3.3、示例代码

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('300x40+500+300')    # 宽300,长40,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')              # 设置弹框名称

# 设置一个文字Label,grid()是网格化布局,默认是从上往下,从左往右为0 1 2...
# 布局管理器pack/grid/place只可以使用一个,将button 显示到窗口上
label = Label(root,text="这是Label的文本" , font=('黑体',15))
label.grid()        # 也可以用label.pack()

label["bg"] = "yellow"      # 索引方式设置背景色
label.config(fg="blue")     # config()设置前景色


root.mainloop()                      # 循环弹窗

在这里插入图片描述

4、button

语法:

w = Button ( master, option=value, ... )

master: 按钮的父容器。
options: 可选项,即该按钮的可设置的属性。这些选项可以用键 = 值的形式设置,并以逗号分隔。

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高150,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

def Btn1_fun(event):
    print("1")

Btn1 = Button(root, text="按钮1", command=Btn1_fun)       # 点击按钮就执行 Btn1_fun()
Btn1.pack()


Button(root, text="退出", command=root.destroy).pack()    # 退出按钮

root.mainloop()                      # 循环弹窗

在这里插入图片描述

4.1、options(属性):

options描述options描述
activebackground当鼠标放上去时,按钮的背景色activeforeground当鼠标放上去时,按钮的前景色
bd按钮边框的大小,默认为 2 个像素bg按钮的背景色
command按钮关联的函数,当按钮被点击时,执行该函数fg按钮的前景色(按钮文本的颜色)
font文本字体height按钮的高度
highlightcolor要高亮的颜色image按钮上要显示的图片
justify显示多行文本的时候,设置不同行之间的对齐方式,可选项包括LEFT, RIGHT, CENTERpadx按钮在x轴方向上的内边距(padding),是指按钮的内容与按钮边缘的距离
pady按钮在y轴方向上的内边距(padding)relief边框样式,设置控件3D效果,可选的有:flat(无边框)、sunken、raised(默认)、groove、ridge。默认为 FLAT。
state设置按钮组件状态,可选的有active(正点击状态),disabled(不可点击),normal。默认 normal。underline下划线。默认按钮上的文本都不带下划线。取值就是带下划线的字符串索引,为 0 时,第一个字符带下划线,为 1 时,前两个字符带下划线,以此类推
width按钮的宽度,如未设置此项,其大小以适应按钮的内容(文本或图片的大小)wraplength限制按钮每行显示的字符的数量
text按钮的文本内容anchor锚选项,控制文本的位置,默认为中心center,可选n,e,s,w,ne,se,sw,nw

4.2、方法

方法描述
flash()在激活状态颜色和正常颜色之间闪烁几次单选按钮,但保持它开始时的状态。
invoke()单击按钮

5、单选按钮Radiobutton、复选按钮Checkbutton

简单理解就是单项选择、多项选择,按钮可以是文本、图片

  • 单选按钮:
    在这里插入图片描述
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('300x30+500+300')    # 宽300,高30,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

str1 = StringVar()
str1.set("A")

def confirm():
    print(str1.get())

button1 = Radiobutton(root, text="A选项", value="A", variable=str1)  # 就是将value的值传递给variable,因此打印str1是"A"
button2 = Radiobutton(root, text="B选项", value="B", variable=str1)

button1.pack(side="left")
button2.pack(side="left")

Button(root, text="确定", command=confirm).pack(side="left")

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗
  • 复选按钮:

在这里插入图片描述

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('300x30+500+300')    # 宽300,高30,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

int_1 = IntVar()	# 需要用2个变量分别接收2个选项
int_1.set(1)
int_2 = IntVar()
int_2.set(1)

def confirm():
    print(int_1.get())
    print(int_2.get())

button1 = Checkbutton(root, text="A选项", onvalue=1, offvalue=0, variable=int_1)  # 就是将value的值传递给variable,因此打印str1是"A"
button2 = Checkbutton(root, text="B选项", onvalue=1, offvalue=0, variable=int_2)

button1.pack(side="left")
button2.pack(side="left")

Button(root, text="确定", command=confirm).pack(side="left")

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗

6、Entry 单行文本框、messagebox 弹窗

  • Entry的可选参数参考:https://blog.csdn.net/qq_41556318/article/details/85108328
  • 接受一行字符串(多行字符请用Text控件)。如果用户输入的文字长度长于Entry控件的宽度时,文字会自动向后滚动。
  • 可以使用tkinter定义的类型接受文本框内容:

tkinter.Variable派生了:
  tkinter.BooleanVar
  tkinter.IntVar
  tkinter.DoubleVar
  tkinter.StringVar

from tkinter import *
from tkinter import messagebox

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('300x100+500+300')    # 宽300,长100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')              # 设置弹框名称

entryStr = StringVar()          # 接收文本框字符,StringVar 继承 tkinter.Variable
entryStr.set("显示默认值")

entry = Entry(root, textvariable=entryStr)  # 文本框中的内容和entryStr是联动的
entry.pack()
Entry(root, textvariable=entryStr, show="*").pack()


def tanchuang():
    print(entry.get())
    messagebox.showinfo("弹窗标题", "弹窗内容")
button = Button(root, text="点击弹窗", command=tanchuang)
button.pack()

Button(root, text="退出", command=root.destroy).pack()

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7、Text 多行文本框

  • 显示多行文本,可以显示图片、HTML页面、网页链接、CSS样式表、添加组件。

7.1、创建Text,插入insert(),删除delete():

Text组件默认就可以手动输入删除文本的,Ctrl C、Ctrl V、上下滚动等操作都可以用

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=40, height=12, bg="green")   # 宽40列字符,高12行字符
text.pack()
text.insert(1.0, "这里显示\n默认文本123")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)
text.insert(2.2, "abc")                 # 1汉字和1字母都是占1列
text.delete(2.7, END)                   # 删除 2行7列之后的文本,就是删了"123"

def insertText():
    text.insert(index=INSERT, chars="光标处插入的文本")    # INSERT索引:在光标处插入
    text.insert(index=END, chars="\n文末处插入文本")       # END索引:文末处插入文本
    
    
Button(root, text="重复插入文本", command=insertText).pack(side="left") # side默认是竖直排列

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7.2、返回文本 get()

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽300,长100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=40, height=12, bg="green")
text.pack()
text.insert(1.0, "这里显示\n默认文本")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)
text.insert(2.2, "abc")                 # 1汉字和1字母都是占1列

def returnText():
    print(text.get(1.2, 2.3))                       # 返回 [1行2列,2行3列) 文本,注意最左上为1.0
    print("\n所有文本:\n" + text.get(1.0, END))     # 返回所有文本
    
Button(root, text="返回文本", command=returnText).pack(side="left")   # side默认是竖直排列

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7.3、添加图片 image_create()

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('450x330+500+300')    # 宽450,高330,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=57, height=23, bg="green")
text.pack()
text.insert(1.0, "这里显示\n默认文本")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)
text.insert(2.2, "abc")                 # 1汉字和1字母都是占1列

def addImage():
    global photo 
    photo = PhotoImage(file="./test.gif")
    text.image_create(END, image=photo)
    
Button(root, text="添加图片", command=addImage).pack(side="left")   # side默认是竖直排列

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7.4、添加组件

如:添加按钮

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=55, height=13, bg="green")
text.pack()
text.insert(1.0, "这里显示\n默认文本")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)
text.insert(2.2, "abc")                 # 1汉字和1字母都是占1列

def addButton():
    Button(root, text="添加按钮", command=addButton).pack(side="left")
    
Button(root, text="添加按钮", command=addButton).pack(side="left")   # side默认是竖直排列

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7.5、tag组件

from tkinter import *
import webbrowser

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=55, height=13, bg="green")
text.pack()
text.insert(1.0, "这里显示\n默认文本")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)

def webshow(event):         # tag_bind()会传入一个参数,因此这里需要一个event接收
    webbrowser.open("https://blog.csdn.net/qq_42888201?spm=1000.2115.3001.5343")

def tagControl():
    text.delete(1.0, END)               # 清空文本框内容
    text.insert(INSERT, "good good study,\nday day up!")
    
    text.tag_add("tag1", 1.5, 1.11)     # 添加标签,标签名:tag1 作用范围[1行5列, 1行11列)
    text.tag_config("tag1",             # 将tag1标签设为 背景色灰色,前景色白色
                    background="gray", foreground="white")
    
    text.tag_add("tag2", 2.1, END)
    text.tag_config("tag2", underline=True)
    text.tag_bind(tagName="tag2",       # tag2标签区域绑定 按钮事件,调用webshow
                  sequence="<Button-1>", func=webshow)
    
    
    
    
Button(root, text="tag标记控制", command=tagControl).pack(side="left")   # side默认是竖直排列

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗

在这里插入图片描述

7.6、关于index

  • 就是insert函数的第一个参数:表示Text组件中文本的位置

例如:“行号.列号”,例如1.0表示第1行第0列

注意:
1、行号以1开始,列号则以0开始
2、text.tag_add(“tag1”, 1.1, 1.3)也可以写为
  text.tag_add(“tag1”, “1.1”, “1.3”)
  1.10必须写为"1.10"

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x80+500+300')    # 宽400,高80,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


text = Text(root, width=40, height=4, bg="green")   # 宽40列字符,高12行字符
text.pack()
text.insert(1.0, "0123456789\n0123456789\n0123456789\n")   # 列从0列开始,行从1行开始,1.0表示从第1列第0列插入(就是最左上角)

text.tag_add("tag1", 1.1, 1.3)      # 包括1.1而不包括1.3,表示 [1行1列, 1行3列)
text.tag_config("tag1", background="black", foreground="white")
    
Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列
root.mainloop()                      # 循环弹窗

在这里插入图片描述

一些说明:

格式说明例子
行号.end该行最后一个字符串的位置text.tag_add(“tag1”, “1.10”, “1.end”)
INSERT对应光标的位置text.tag_add(“tag1”, “2.1”, INSERT)
CURRENT对应与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,会直接到你松开才相应。
ENDText组件的文本缓冲区最后一个字符的下一个位置

其他详细的参考:https://www.cnblogs.com/pinpin/p/9960779.html

8、canvas(画布)

一个矩形区域,可以放入图像、图形、组件等。

在这里插入图片描述

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('300x200+500+300')    # 宽300,高30,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

canvas = Canvas(root, width=280, height=150, bg="green")    # 创建一个画布
canvas.pack()

line = canvas.create_line(10, 10, 10, 50, 70, 50)   # 折线:(x, y):(10,10) (10,50) (70,50)连成折线
rect = canvas.create_rectangle(20, 80, 100, 130)    # 矩形:左上角(20,80),右下角:(100,130)
oval = canvas.create_oval(20, 80, 100, 130)         # 椭圆:外接矩形的左上角(20,80)、右下角(100,130)

global photo
photo = PhotoImage(file="./test.gif")
canvas.create_image(320, 170, image=photo)          # 图像中心位置(320, 170)

Button(root, text="退出", command=root.destroy).pack(side="left")     # 退出按钮,靠左侧排列

root.mainloop()                      # 循环弹窗
  • delete()
函数说明
delete(id)通过id来删除,id是canvas.create_something的返回值
delete(tag)通过tag来删除,tag通过canvas.create_something(tag=tag)来指定
delete(“all”)删除所有已绘制对象

9、OptionMenu、ttk.Combobox下拉选项框

9.1、OptionMenu

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高150,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

v = StringVar(root)
v.set("选项1")            # 记录选项框的内容,会和选项框联动

# OptionMenu的初始化函数:__init__(self, master, variable, value, *values, **kwargs):
om = OptionMenu(root, v, "选项1", "选项2", "选项2333")
om["width"] = 30    # 宽度
om.pack()

Button(root, text="输出", command=lambda:print(v.get())).pack()

root.mainloop()                      # 循环弹窗

在这里插入图片描述

9.2、ttk.Combobox()

from tkinter import *
from tkinter.messagebox import *
from tkinter import ttk

root = Tk();root.title('这是title')
screenwidth, screenheight = root.winfo_screenwidth(), root.winfo_screenheight()
width, height = 400, 150
x, y = int((screenwidth-width)/2), int((screenheight-height)/2)     # 居中后 窗口左上角坐标
root.geometry('{}x{}+{}+{}'.format(width, height, x, y))

value = StringVar()
value.set('CCC')
valueList = ['AAA', 'BBB', 'CCC', 'DDD']
combobox = ttk.Combobox(master=root,  # 父容器
                        height=10,  # 高度,下拉显示的条目数量
                        width=20,  # 宽度
                        state='readonly',  # 设置状态 normal(可选可输入)、readonly(只可选)、 disabled
                        cursor='arrow',  # 鼠标移动时样式 arrow, circle, cross, plus...
                        font=('', 20),  # 字体
                        textvariable=value,  # 通过StringVar设置可改变的值
                        values=valueList,  # 设置下拉框的选项
                        )
print(combobox.keys())  # 可以查看支持的参数
combobox.pack()

def fun(event):
    print("执行{}的函数".format(value.get()))            # 绑定函数

combobox.bind("<<ComboboxSelected>>", fun)

root.mainloop()                      # 循环弹窗

在这里插入图片描述

10、Scale移动滑块

在这里插入图片描述

from tkinter import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

L1 = Label(root, text="滑动滑块控制文本大小")

def ScaleFun(value):
    print("滑块值:\t", value)
    L1.config(font=("宋体", value))
    
# 初始值frim_10,最大值to50,滑块长度length250,相邻显示的2个值公差5,水平HORIZONTAL排列(默认竖直VERTICAL)
Scale(root, from_=10, to=50, length=250, tickinterval=5, orient=HORIZONTAL,
      command=ScaleFun).pack()  
L1.pack()

root.mainloop()                      # 循环弹窗

11、各种选择框、消息框

11.1、askcolor颜色选择框

s1 = askcolor(color=“green”, title=“请选择背景颜色”) # 默认颜色绿色
print(s1) # 输出:((0, 128, 0), ‘#008000’),第一个是(R, G, B)

在这里插入图片描述

from tkinter import *
from tkinter.colorchooser import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def colorSelect():
    s1 = askcolor(color="green", title="请选择背景颜色") # 默认颜色绿色
    print(s1)	# 输出:((0, 128, 0), '#008000')
    root.config(bg=s1[1])	# s1[1]就是'#008000'

Button(root, text="选择颜色", command=colorSelect).pack()

root.mainloop()                      # 循环弹窗

11.2、askopenfilename文件对话框

需要导入包:from tkinter.filedialog import *

函数名对话框说明
askopenfilename(**options)
askopenfilenames(**options)
文件对话框返回打开的文件名
返回打开的文件名列表
askopenfile(**options)
askopenfiles(**options)
返回打开文件对象
返回打开文件对象的列表
askdirectory(**options)目录对话框返回目录名
asksaveasfile(**options)保存对话框返回保存的文件对象
asksaveasfilename(**options)返回保存的文件名
  • options:
参数名说明
defaultextension保存文件,用户没有定义后缀时的默认后缀(默认值:.xxx)
filetypes=[(label1,pattern1),(label2,pattern2)]文件显示过滤器
initaldir文件窗口的初始目录
parent父窗口
title窗口标题
from tkinter import *
from tkinter.filedialog import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    f = askopenfilename(title="这是标题", initialdir="D:/test",     # initialdir初始路径,注意 /,而\需要r"\"
                        filetypes=[("文档", "txt"), ("视频", "mp4")])
    print(f)

Button(root, text="选择文件", command=fun).pack()

root.mainloop()                      # 循环弹窗

在这里插入图片描述

  • 读取文件内容:
from tkinter import *
from tkinter.filedialog import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    with askopenfile(title="这是标题", initialdir="D:/test",     # initialdir初始路径,注意 /,而\需要r"\"
                        filetypes=[("文档", "txt"), ("视频", "mp4")]) as f:    
        print(f.read())             # 如果是'utf-8'文本会失败,可以将文本另存为ANSI,或者使用open(file,encoding="utf-8")
        
        
Button(root, text="读取文件内容", command=fun).pack()

root.mainloop()                      # 循环弹窗

11.3、simpledialog 简单输入对话框

函数名说明
askfloat(title, prompt, **kw)
askinteger(title, prompt, **kw)
askstring(title, prompt, **kw)
输入并返回浮点数、整数、字符串

title:窗口标题
prompt:提示信息
命名参数kw:initialvalue(初始值)、minvalue(最小值)、maxvalue(最大值)

from tkinter.simpledialog import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    a = askinteger(title="整数输入框", prompt="输入一个整数:", initialvalue=2333,
                   minvalue=1, maxvalue=10000)      # 确认:返回数字,若数字非法会弹窗报错  取消:返回None 
    print(a)
        
Button(root, text="输入整数", command=fun).pack()

root.mainloop()                      # 循环弹窗

在这里插入图片描述

11.4、通用消息框

在这里插入图片描述

函数名说明函数名说明
askokcancel(title,message, **options)OK/Cancel对话框askquestion(title,message, **options)问题对话框
askretrycancel(title,message, **options)Retry/Cancel对话框showerror(title,message, **options)错误消息框
showinfo(title,message, **options)消息框showwarning(title,message, **options)警告消息框
from tkinter import *
from tkinter.messagebox import *

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    a1 = askokcancel(title="OK/Cancel对话框", message="这是框内信息\nhello world!")        # True, False
    a2 = askquestion(title="问题对话框", message="这是框内信息\nhello world!")             # 'yes', 'no'
    a3 = askretrycancel(title="Retry/Cancel对话框", message="这是框内信息\nhello world!")  # True, False
    showerror(title="错误消息框", message="这是框内信息\nhello world!")
    showinfo(title="消息框", message="这是框内信息\nhello world!")
    showwarning(title="警告消息框", message="这是框内信息\nhello world!")
    
    print((a1, a2, a3))
        
Button(root, text="弹窗", command=fun).pack()

root.mainloop()                      # 循环弹窗

12、Menu菜单栏

tearoff=0:
在这里插入图片描述

tearoff=1:在这里插入图片描述

from tkinter import * 
from tkinter.filedialog import askopenfilename
import time

root = Tk();root.geometry('400x150+500+300');root.title('这是title')

def fun():
    print("执行fun")

def createContextMenu(event):
    contextMenu.post(event.x_root, event.y_root)

# 主菜单
menubar = Menu(root)

# 创建子菜单
menu_1 = Menu(menubar, tearoff=0)   # 默认tearoff=1,可以使菜单独立一个窗口显示出来
menu_2 = Menu(menubar, tearoff=0)

# 将子菜单加入到主菜单栏
menubar.add_cascade(label="文件(F)", menu=menu_1) # 但是F不会真正生效
menubar.add_cascade(label="帮助(H)", menu=menu_2)

# 添加菜单项
menu_1.add_command(label="新建", accelerator="ctrl+n", command=fun)   # 快捷键不会真正生效
menu_1.add_separator()              # 添加分割线
menu_1.add_command(label="打开", accelerator="ctrl+o", command=fun)

root["menu"] = menubar      # root中加入menubar

# 创建上下文菜单(右键菜单)
contextMenu = Menu(root)
contextMenu.add_command(label="背景颜色", command=fun)
root.bind("<Button-3>", createContextMenu)

# 循环弹窗
root.mainloop()

13、frame容器

  • 就是放置其他组件的容器
  • 实测,当放置了其他组件后,原来设定长宽会失效,frame的大小适配他的子组件
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


f1 = Frame(root,width=100,  height=50, highlightcolor="red", bg="blue")     # Frame是一个矩形区域,放置子组件
f1.pack()

f2 = Frame(root, width=100, height=50,bg="yellow")
f2.pack()

f3 = Frame(root, width=100, height=50,bg="green")   # 由于放置了部件,长宽适配组件
f3.pack()

# 当Frame上面放置了部件,那么frame原长宽值失效,而适配他的组件
Label(f3, text="L1_left", relief="solid").pack(side="left")
Label(f3, text="L2_bottom", relief="solid").pack(side="bottom")
Label(f3, text="L3_top", relief="solid").pack(side="top")

root.mainloop()                      # 循环弹窗

效果图如下,关于side="left"参考布局管理器条目pack()
在这里插入图片描述

14、布局管理器pack()、grid()、place()

顾名思义,就是整体布局的设置

14.1、表格布局grid()

用类似表格的结构组织组件,子组件的位置由(行, 列)的单元格来确定,可以跨行跨列。

  • grid()参数:
选项说明取值范围
row行号0,1,2,3,…
column列号0,1,2,3,…
rowspan跨行,跨越的行数正整数
columnspan跨列,跨越的列数正整数
padx, pady组件之间的间隔,x、y方向,默认单位为像素非负浮点数,默认0.0
ipadx, ipady子组件之间的间隔,x、y方向,默认单位为像素非负浮点数,默认0.0
sticky组件紧贴所在单元格的某一角,东南西北(eswn)和四个角落“n”, “s”, “w”, “e”, “nw”, “sw”, “se”, “ne”, “center”(默认)

在这里插入图片描述

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称



Button(root, text="(0, 0)").grid(row=0, column=0)   # 0行0列
Button(root, text="(0, 1)").grid(row=0, column=1)   # 0行1列
Button(root, text="(0, 3)").grid(row=0, column=3)   # 0行3列

Button(root, text="(1, 0)").grid(row=1, column=0)   # 1行0列
Button(root, text="(1, 1)").grid(row=1, column=1)   # 1行1列
Button(root, text="(1, 2)").grid(row=1, column=2)   # 1行2列
Button(root, text="(1, 5)").grid(row=1, column=5)   # 1行5列,但是1行3、4列没组件,自动向左移2列

Button(root, text="(2, 0)").grid(row=2, column=0, padx=15)   # 2行0列,组件之间的间隔拉大了15个像素

Entry(root, ).grid(row=3, column=1)                 # 3行1列,但是组件比较宽,是的整个组件拉宽了

Button(root, text="w(4, 1)").grid(row=4, column=1, sticky="w")   # 4行1列,组件紧邻单元格左侧
Button(root, text="w(5, 1)e").grid(row=5, column=1, sticky="we") # 5行1列,组件紧邻单元格左右两侧

root.mainloop()                      # 循环弹窗

14.2、pack()

  • 最简单的一种,按照水平、竖直方向自然排布,默认竖直方向。
可选项描述取值范围
side停靠在父组件的哪一边上
若属性expand=“yes”,side属性失效
“top”(默认值), “bottom”, “left”, “right”
expand布尔值
当expand="yes"时side选项失效,若fill=“both”,则填充父组件剩余空间
“yes”,自然数,“no”(默认值"no"或0)
fill填充x、y方向上的空间。
 属性side=top\bottom时,填充x、方向
 (left\right填充y方向)
“x”、“y”、“both”、“none”(默认值)
padx, pady组件之间的间隔,x、y方向,默认单位为像素非负浮点数,默认0.0
ipadx, ipady子组件之间的间隔,x、y方向,默认单位为像素非负浮点数,默认0.0
before、afterbefore:将本组件设定在另一组件之前进行pack(),作用效果就是先创建其他组件,再创建本组件
after:…之后…
已经pack后的组件
in_本组件作为另一组件的子组件已经pack后的组件
anchor对齐方式,左对齐"w",右对齐"w",顶对齐"n",底对齐"s"“n” “s” “w” “e” “nw” “sw” “se” “ne” “center”(默认)
  • 关于side选项示例代码:
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x200+500+300')    # 宽400,高200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


f1 = Frame(root,width=100,  height=50, highlightcolor="red", bg="blue")     # Frame是一个矩形区域,放置子组件
f1.pack()

f2 = Frame(root, width=100, height=50,bg="green")   # 由于放置了部件,长宽适配组件
f2.pack()

# 当Frame上面放置了部件,那么frame原长宽值失效,而适配他的组件
Label(f2, text="L1_left", relief="solid").pack(side="left")
Label(f2, text="L2_bottom", relief="solid").pack(side="bottom")
Label(f2, text="L3_top", relief="solid").pack(side="top")
Label(f2, text="L4_left", relief="solid").pack(side="left")
Label(f2, text="L5_top", relief="solid").pack(side="top")
Label(f2, text="L6_top", relief="solid").pack(side="top")


root.mainloop()                      # 循环弹窗

在这里插入图片描述

  • 关于fill选项,示例代码:
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x100+500+300')    # 宽400,高100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称


f1 = Frame(root, width=100, height=50,bg="green")   # 由于放置了部件,长宽适配组件
f1.pack()

# 当Frame上面放置了部件,那么frame原长宽值失效,而适配他的组件
Label(f1, text="L1_left_none", relief="solid").pack(side="left")
Label(f1, text="L2_left_y", relief="solid").pack(side="left", fill="y")
Label(f1, text="L3_top_none", relief="solid").pack(side="top")
Label(f1, text="L4_top_x", relief="solid").pack(side="top", fill="x")
Label(f1, text="L4_left_none", relief="solid").pack(side="left")
Label(f1, text="L5_left_none", relief="solid").pack(side="left")


root.mainloop()                      # 循环弹窗

在这里插入图片描述

  • 关于expand
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x100+500+300')    # 宽400,高100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

Label(root, text="L1", bg="green").pack(side="left",fill="both", expand="yes")
Label(root, text="L2", bg="red").pack(side="left", fill="both", expand="yes")
Label(root, text="L3", bg="green").pack(side="left", fill="both", expand="yes")

root.mainloop()                      # 循环弹窗

在这里插入图片描述
依次注释掉L1, L2, L3的代码,expand=yes、no,如下图。当为yes时,只有L1就会占满整个root窗口(而不是靠在左侧left):
在这里插入图片描述

14.3、place()

  • 通过坐标精准控制组件位置
选项说明取值范围
relx, rely组件左上角坐标(相对于父容器)
实际坐标是先计算relx\rely的值后再加上x\y的偏移值
0~1的浮点数
0:最左\上
0.5:中间
1:最右\下
x, y组件左上角的绝对坐标(相对于窗口)
实际位置需要考虑relx、rely
非负整数,单位像素
width, height组件的宽度、高度计算凡是与x、y类似
relwidth, relheight组件的宽度、高度(相对于父组件)计算方式与relx、rely取值类似,相对于父组件的尺寸
anchor对齐方式,左对齐"w",右对齐"w",顶对齐"n",底对齐"s"“n” “s” “w” “e” “nw” “sw” “se” “ne” “center”(默认)
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(True, False)         # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

Label(root, text="x,y=(30,30)", bg="yellow").place(x=30, y=30)
Label(root, text="relx,rely=(0.5,0.5)", bg="green").place(relx=0.5, rely=0.5)   # 拉伸root窗口,位置会跟随变化
Label(root, text="x,y=(30,30)\nrelx,rely=(0.5,0.5)", bg="gray").place(x=30, y=30, relx=0.5, rely=0.5)

root.mainloop()                      # 循环弹窗

在这里插入图片描述

15、事件处理

参考:http://www.manongjc.com/article/61145.html

  • 一个GUI应用整个生命周期都处在一个消息循环(event loop)中,它等待事件(Event)的发生(鼠标事件、键盘事件)。
  • 3个概念:
  • 事件(event):是指点击、按键等操作,在tkinter中,event是一个类,当某个事件发生时,生成一个event对象,不同类型的事件生成具有不同属性的event对象。
  • 事件处理(event handler):是指在捕获到事件后,程序自动执行的操作,是回调函数(recall function)。
  • 事件绑定(event binding):是当一个事件发生时程序能够做出响应。tkinter提供三种绑定方式:实例绑定bind(将某个事件处理绑定到某个组件上)、类绑定bind_class(将某个事件处理绑定到某类组件上)、应用绑定bind_all(将某个事件处理绑定到所有组件上)。

15.1、 将函数绑定控件 发生的事件

  • 组件对象的绑定

两种方法:
 1、组件名.bind(event事件, handler被触发的函数)
 2、command属性来执行事件,适合简单且不需要event对象

  • 组件类的绑定:组件名.bind_class(“Widget组件类型”, “event”, eventhanler)
      将该组件类的所有组件绑定事件。如 btn01.bind_class(“Button”, “<Button-1>”, myFun01)
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高150,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

def Btn1_fun(event):              
    print("{}\t({},{})".format(event.widget["text"], event.x, event.y))

btn0 = Button(root, text="按钮1", command=Btn1_fun)
btn0.pack()
btn0.bind_class("Button", "<Button-1>", Btn1_fun)

Button(root, text="按钮2").pack()

root.mainloop()                      # 循环弹窗

点击按钮2时也会执行Btn1_fun():
在这里插入图片描述

  • 使用lambda表达式传递多个参数
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高150,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

def Btn1_fun(a, b, c):              # 注意参数列表没有event
    print(a+b+c)

Button(root, text="按钮1", command=lambda:Btn1_fun(1, 2, 3)).pack()       # 点击按钮就执行 Btn1_fun()

root.mainloop()                      # 循环弹窗

在这里插入图片描述

15.2、鼠标、键盘事件、侦听窗口大小变化

语法:<modifier - type - dateil>

  • modifier:事件修饰符。如:Alt、Shit组合键和Double事件。
  • type:事件类型。如:按键(Key)、鼠标(Button/Motion/Enter/Leave/Relase)、Configure等。
  • detail:事件细节。如:鼠标左键(1)、鼠标中键(2)、鼠标右键(3)

注意:接受键盘事件,只有组件获取焦点才能接受键盘事件,用focus_set()获取焦点

  • modifier:
取值说明取值说明
Alt按下Alt键Shift按下Shift键
Control按下Ctrl键Any任何类型的按键被按下,如<Any-KeyPress>表示按下任何键
Double后续事件连续2次被触发,如<Double-1>表示双击左键Triple当后续事件连续3次触发
Lock当打开大写字母
  • type:
    <Button-1>左键,<Button-2>中键,<Button-3>右键,<Button-4>滚轮上(liunx),<Button-5>滚轮下(liunx)

  • dateil部分是可选的,它通常是描述具体的键,(<Control-Shift-Key-H>,表示用户同时按下Ctrl+Shift+H)

  • 常用例子:

事件类型事件格式事件解释
鼠标事件<Button-1>
<ButtonPress-1>
<1>
鼠标按下(1-左键,2-中键,3-右键)
<Double-Button-1>鼠标双击(1-左键,2-中键,3-右键)
<B1-Motion>鼠标拖动(1-左键,2-中键,3-右键)
<ButtonRelease-1>鼠标按下之后释放(1-左键,2-中键,3-右键)
<Enter>鼠标进入控件范围(widget),不是键盘按键
<Leave>鼠标离开控件范围(widget)
<MouseWheel>滚动滚轮
键盘事件<Return>
<Cancel>
<space>
<Tab>
<Shift_L>
<Control_L>
<Alt_L>
<Home>
<Left>
<Up>
<Down>
<Right>
<Delete>
<F1>
<F2>
对应键盘按键
<KeyPress-a>按下a键,a可以是其他字符(如1,2,b,c,大写字母A等)
<KeyRelease-a>释放a键
<Control-a>同时按下Ctrl和a
<Alt-KeyPress-a>同时按下Alt和a,Alt可用Ctrl,Shift替换
<Double-KeyPress-a>快速按两下a
组件事件<Configure>如果widget的大小发生改变,新的大小(width和height)会打包到event发往handler。
<Activate>当组件从不可用变为可用
<Deactivate>当组件从可用变为不可用
<Destroy>当组件被销毁时
<Expose>当组件从被遮挡状态变为暴露状态
<Map>当组件由隐藏状态变为显示状态
<Unmap>当组件由显示状态变为隐藏状态
<FocusIn>当组件获得焦点时
<FocusOut>当组件失去焦点时
<Property>当组件属性发生改变时
<Visibility>当组件变为可视状态时

参考:https://www.weixueyuan.net/a/574.html
<Key>:此事件在按下 ASCII 码为 48~90 时发生,即数字键、字母键及 +、~ 等符号。
<Control-Up>:此事件在按下 Ctrl+Up 组合键时发生。同理,可以使用类似的名称在 Alt、Shift 键加上 Up、Down、Left 与 Right 键。
其他按键,使用其按键名称。包括 <Return>、<Escape>、<F1>、<F2>、<F3>、<F4>、<F5>、<F6>、<F7>、<F8>、<F9>、<F13>、<F11>、<F12>、<Num_Lock>、<Scroll_Lock>、<Caps_Lock>、<Print>、<Insert>、<Delete>、<Pause>、<Prior>(Page Up)、<Next>(Page Down)、<BackSpace>、<Tab>、<Cancel>(Break)、<Control_L>(任何的 Ctr l键)、<Alt_L>(任何的Alt键)、<Shift_L>(任何的Shift键)、<End>、<Home>、<Up>、<Down>、<Left>、<Right>

  • 侦听窗口大小变化
from tkinter import *

root = Tk(); root.geometry('300x60+500+200'); root.title('这是title')

def getConfigure(event):
    print(event)
    print("{}\t{}\t{}\t{}".format(event.x, event.y, event.width, event.height))
    print("循环前窗口宽{}\t高{}".format(root.winfo_width(), root.winfo_height()))

root.bind('<Configure>', getConfigure)


root.mainloop()                 # mainloop()    :循环弹窗

# 输出:
<Configure event x=500 y=200 width=300 height=60>
500	200	300	60
循环前窗口宽30060

15.3、Event对象常用属性

名称说明
char
keycode
keysym
按键字符、编码、名称,仅对键盘事件有效如按下
键a:字符char:a  编码keycode:65  名称keysym:a
空格键:字符char:   编码keycode:32  名称keysym:space
num鼠标按键,仅对鼠标事件有效
1:左键
2:中键
3:右键
type所触发的事件类型
widget引起事件的组件
width、height组件改变后的大小,仅Configure有效
x、y鼠标当前位置,相对于父容器
x_root、y_root鼠标当前位置,相对于整个屏幕

在这里插入图片描述

from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x150+500+300')    # 宽400,高150,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 是否拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

global last_x, last_y
last_x, last_y = 0, 0       # 记录鼠标位置

def draw(event):            # 左键按下-->画图
    global last_x, last_y
    event.widget.create_line(last_x, last_y, event.x, event.y)  # 画直线
    last_x, last_y = event.x, event.y
    print("组件:"+str(event.widget)+"\t鼠标位置:({},{})".format(event.x, event.y))
    
def moveMouse(event):       # 移动鼠标-->记录鼠标位置
    global last_x, last_y
    last_x ,last_y = event.x, event.y
    print("组件:"+str(event.widget)+"\t鼠标位置:({},{})".format(event.x, event.y))
    
def keyPress(event):        # 按下键盘-->按下delete画布清除
    print("组件:"+str(event.widget)+"\t按下:{}".format(event.keysym))
    if event.keysym == "Delete":
        c1.delete("all")

c1 = Canvas(root, width=350, height=100, bg="green")
c1.place(x=5, y=5)
c1.bind("<B1-Motion>", draw)        # 按住左键移动
c1.bind("<Motion>", moveMouse)      # 记录鼠标当前位置
c1.delete()

L1 = Label(c1, text="Key press event", bg="yellow")
L1.focus_set()                      # 键盘事件需要设置焦点
L1.place(x=10, y=5)
L1.bind("<KeyPress>", keyPress)     # 按下键盘的键

root.mainloop()                      # 循环弹窗
  • create_rectangle还有fill、outline等参数(实心、边框填充),详细可以百度找找

15.4、协议处理机制 protocol handlers

参考:https://www.jianshu.com/p/9c66c0090edb

  • 除了事件绑定,tkinter 还支持一种称为协议处理程序(protocol handlers)的机制。在这里,术语协议(protocol)是指应用程序和窗口管理器之间的交互。最常用的协议称为 WM_DELETE_WINDOW,用于定义当用户使用窗口管理器显式关闭窗口时发生的情况(上面 2.4 部分有示例代码)。用法:

widget.protocol(“WM_DELETE_WINDOW”, handler)
注意:部件必须是 root 或者 Toplevel 小部件;点击窗体右上叉X时,不会关闭窗口,而是调用handler函数

x、一些例子

x.1、编写UI:

from tkinter import *

def button1fun():
    data = entry.get().strip()
    print(data)
    pass

# 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root = Tk()

# 宽600,长200,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.geometry('600x200+500+300')

# 不准拉伸(宽,高)
root.resizable(False, False)

# 设置弹框名称
root.title('这是title')

# 设置一个文字Label,grid()是网格化布局,默认是从上往下,从左往右为0 1 2...
# 布局管理器pack/grid/place只可以使用一个,将button 显示到窗口上
Label(root,text="这是Label的文本" , font=('黑体',15)).grid()
# 也可以用Label(root,text="这是Label的文本" , font=('黑体',15)).pack()

# 输入框
entry = Entry(root)

# 设置输入框位置,上面Label是(0,0),若输入框在Label右边则grid()为(0, 1)
entry.grid(row=0,column=1)

# 按钮1,注意回调函数(callback)是没有括号的,反复调用,而button1fun()则只执行一次
button1 = Button(master=root, text='按钮 弹窗',width='15',command=button1fun)
button1.grid(row=1,column=0)

# 按钮绑定事件 & 弹窗
def tanChuang(e):   # e就是事件
    messagebox.showinfo("弹窗标题","这是弹窗的内容")
button1.bind("<Button-1>",tanChuang)

# 退出按钮 & 布局管理器
button2 = Button(master=root, text='退出',width='15',command=root.destroy)
button2.grid()    

# 循环弹窗
root.mainloop()

在这里插入图片描述

  • before、after:
from tkinter import *

root = Tk()                         # 实例化tk类,需要配合后面root.mainloop()才能循环显示弹框
root.geometry('400x100+500+300')    # 宽400,高100,边框距离屏幕最左端距离为500,与最上端距离为300(也可以用最右/下端用减号-)
root.resizable(False, False)        # 不准拉伸(宽,高)
root.title('这是title')             # 设置弹框名称

label1 = Label(root, text="L1")
label2 = Label(root, text="L2")
label3 = Label(root, text="L3")

label1.pack(side="left")
label2.pack(side="left", before=label1)     # 将label2放到label1前面
label3.pack(side="left", after=label2)      # 将label3放到label2后面
# 最终排列为 2->3->1

root.mainloop()                      # 循环弹窗

在这里插入图片描述

x.2、使用面向对象的方式

"""使用面向对象的方式"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):   # 继承tkinter.Frame
    """一个经典的GUI程序的类的写法"""    

    def __init__(self, master=None):   # master=根窗口root
        super().__init__(master) # super()代表父类Frame的定义(而不是父类对象
        self.master = master
        self.pack()                     # 窗口管理器
        self.createWidget()
    
    def createWidget(self):
        """创建组件"""
        # 1、按钮
        self.btn01 = Button(self.master)        # Button(self)也可以运行,但若用place而不是pack则不会显示
        self.btn01["text"] = "点击送花"
        self.btn01["command"] = self.songhua
        self.btn01.pack()
        
        # 2、label显示图片
        global photo
        photo = PhotoImage(file="./test.gif")
        self.label1 = Label(self.master, image=photo)
        # 需将photo定义全局变量或者类变量(如下),否则在:mainloop循环中会销毁,不显示
        # self.photo = PhotoImage(file="./test.gif")
        # self.label1 = Label(self, image=self.photo)
        self.label1.pack()
        
        # 3、退出按钮
        self.btnQuit = Button(self.master, text="退出", command=self.master.destroy)
        self.btnQuit.pack()
        
    def songhua(self):
        messagebox.showinfo("送花", "送你99朵玫瑰花")
    
if __name__ == '__main__':
    root = Tk()
    root.geometry("400x300+200+300")    # 创建窗口,长x宽+距离屏幕左边+距离屏幕右侧
    root.title("一个经典的GUI程序类的测试")
    app = Application(master=root)
    app.mainloop()     # 循环

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值