当前位置:   article > 正文

python3基础知识复习 --TKinter GUI的终极选择(1)_tkinter tab页

tkinter tab页

TKIinter – GUI的终极选择

Python支持多种图形界面的第三方库,包括Tk, wxWidgets, Qt, GTK, 我们python自带的库Tkinter支持Tk,作为默认的GUI库,可以直接使用。

NOTE: 内置的Tkinter可以满足基本的GUI程序的要求,如果是非常复杂的GUI程序,建议用操作系统原生支持的语言和库来编写。

TK +interface = Tkinter

我们编写的Python代码会调用内置的Tkinter,Tkinter封装了访问Tk的接口;

Tk是一个图形库,支持多个操作系统,使用Tcl语言开发;

Tk会调用操作系统提供的本地GUI接口,完成最终的GUI。

所以,我们的代码只需要调用Tkinter提供的接口就可以了。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

''' TKinter example 之封装用法'''
# 定义一个frame,里面有个button, command用来执行点击buttom的动作
import tkinter as tk

class APP:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('Tkinter example') # 设置窗口标题
        self.root.geometry('300x100+630+80') # 设置主窗口的长宽以及窗口在屏幕的位置:长x宽+x+y
        self.frame = tk.Frame(self.root)
        self.frame.pack(side=tk.LEFT, padx=20, pady=30) # side用来设置frame位置,xy轴间距
        self.interface()      

    def click(self):
        print("Hello World!!")
       
    def interface(self):
        self.button = tk.Button(self.frame, text="Hello!!", fg="red", bg="yellow", command=self.click)
        self.button.pack()


if __name__ == "__main__":
    app = APP()
    app.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

Label

在这里插入图片描述

Label(master=None, **options)(class)

master – 父组件

*options – 组件选项,下方表格详细列举了各个选项的具体含义和用法

显示文本或图像,单一字体文字(可跨行),个别字加下划线

如果希望显示的数据用户可以进行操作,使用 Canvas 组件或许更为合适。

	EG:
# -*- coding: utf-8 -*-
	''' the Label and Button of tkinter  '''
	from tkinter import *
	
	root = Tk()
	frame1 = Frame(root)
	frame2 = Frame(root)
	photo = PhotoImage(file='minion.gif')
	
	def callback(): #点击按钮时改变文字
	    text.set('NO WAY! You are just 3-month old!')
	
	text = StringVar()
	text.set('You are too young to play basketball!')
	
	theLabel = Label(frame1, textvariable=text, font="Kaiti, 22", justify='left')
	theLabel.pack(side='left', padx=10, pady=10)
	
	imageLabel = Label(frame1, image=photo)
	imageLabel.pack(side='right', padx=10, pady=10)
	
	
	button = Button(frame2, text='I can play!', font='kaiti, 22' ,command=callback)
	button.pack()
	
	frame1.pack(side='top')
	frame2.pack(pady=20)
	mainloop()
	
'''
	# show the text in front of image.
	
	textLabel = Label(root, text = 'Mr.Anzai, I want to play basketball!',
	                  image=photo,
	                  compound='center',
	                  justify='center',
	                  font='Lucida, 20')
	textLabel.pack()
'''
  • 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

Button

[上传(img-tUkCkLyZ-1654222300866)(../resources/image64-3.png)]

*Button(master=None, **options) (class)

特性和label差不多,但是按下后可以执行给定的函数或者方法, Button 组件常常被用于工具栏、应用程序窗口、和表示接受或拒绝的对话框。

checkbutton 和 Radiobutton组件更适合做数据输入按钮使用。

state=DISABLED — 表示按钮不可用

按钮按照像素变化:

f = Frame(master, height=64, width=64)
f.pack_propagate(0)
f.pack()

b = Button(f, text="确定", command=callback)
b.pack(fill=BOTH, expand=1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

b.config(relief=SUNKEN/RAISED) – 按钮保持按下的状态

compound=CENTER 使得文字位于图片的上方(重叠显示),通过 LEFT,RIGHT,TOP 和 BOTTOM 则可以设置文字在图像的旁边显示

*方法*:

flash()

-- 刷新 Button 组件,该方法将重绘 Button 组件若干次(在 ACTIVE 和 NORMAL 状态间切换)。

invoke()

-- 调用 Button 中 command 选项指定的函数或方法,并返回函数的返回值。

-- 如果 Button 的状态是 DISABLED(不可用)或没有指定 command 选项,则该方法无效。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Checkbutton(多选按钮)

1

Checkbutton(master=None, **options) (class)

master – 父组件

*options – 组件选项,下方表格详细列举了各个选项的具体含义和用法:

默认tab 按键被用于在按钮间切换

使用 Checkbutton,你必须创建一个 Tkinter 变量用于存放按钮的状态:(1 选中,0未选中)

var = IntVar()
c = Checkbutton(master, text="我是帅锅", variable=var)
c.pack()
  • 1
  • 2
  • 3

indicator=FALSE — 表示不显示选择框

方法:

deselect()

– 取消 Checkbutton 组件的选中状态,也就是设置 variable 为 offvalue。

flash()

– 刷新 Checkbutton 组件,该方法将重绘 Checkbutton 组件若干次(在 ACTIVE 和 NORMAL 状态间切换)。

invoke()

– 调用 Checkbutton 中 command 选项指定的函数或方法,并返回函数的返回值。

– 如果 Checkbutton 的状态是 DISABLED(不可用)或没有指定 command 选项,则该方法无效。

select()

– 将 Checkbutton 组件设置为选中状态,也就是设置 variable 为 onvalue。

toggle()

– 切换 Checkbutton 组件的状态(选中 -> 未选中 / 未选中 -> 选中)。

Anchor=W

在这里插入图片描述

	from tkinter import *
	
	root = Tk()
	
	GIRLS = ["Jenny","Penny","Lenny","Donny"]
	var = []
	
	for girl in GIRLS:
	    var.append(IntVar())
	    c = Checkbutton(root, text=girl, variable=var[-1])
	    c.pack(anchor=W)
	
mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Radiobutton(单选按钮)

为了实现其“单选”行为,确保一组中的所有按钮的 variable 选项都使用同一个变量,并使用 value 选项来指定每个按钮代表什么值,当一个被选中的时候value的值就会赋给variable,从而来互斥其他value(选项)

在这里插入图片描述

from tkinter import *

master = Tk()
v = IntVar()
v.set(2)

Radiobutton(master, text="One", variable=v, value=1).pack(anchor=W)
Radiobutton(master, text="Two", variable=v, value=2).pack(anchor=W)
Radiobutton(master, text="Three", variable=v, value=3).pack(anchor=W)
mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

indicatoron 选项设置为 False,Radiobutton 的样式就会变成普通按钮的样式了:

在这里插入图片描述

方法

deselect()

– 取消该按钮的选中状态。

flash()

– 刷新 Radiobutton 组件,该方法将重绘 Radiobutton 组件若干次(在 ACTIVE 和 NORMAL 状态间切换)。

– 该方法在调试的时候很有用,也可以使用此方法提醒用户激活了该按钮。

invoke()

– 调用 Radiobutton 中 command 选项指定的函数或方法,并返回函数的返回值。

– 如果 Radiobutton 的状态是 DISABLED(不可用)或没有指定 command 选项,则该方法无效。

select()

– 将 Radiobutton 组件设置为选中状态。

LabelFrame

将一些相关的组件分为一组的时候,可以使用 LabelFrame 组件,比如一系列 Radiobutton(单选按钮)组件。

在这里插入图片描述

	from tkinter import *
	
	root = Tk()
	lf = LabelFrame(root, text='Who is the most butiful girl?', padx=10, pady=10)
	lf.pack(padx=20, pady=20)
	
	GIRLS = [
	    ("Jenny", 1),
	    ("Penny", 2),
	    ("Lenny", 3),
	    ("Donny", 4)
	    ]
	
	v = IntVar()
	v.set(2)
	
	for girl, num in GIRLS:
	    c = Radiobutton(lf, text=girl, value=num, variable=v)
	    c.pack(anchor=W)
	
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Entry (输入框)

Entry(master=None, **options) (class)

最后需要提到的是 Entry 组件允许通过以下几种方式指定字符的位置:

  • 数字索引号:常规的 Python 索引号,从 0 开始
  • ANCHOR:对应第一个被选中的字符(如果有的话)
  • END:对应已存在文本的后一个位置
  • INSERT:对应插入光标的当前位置
  • 鼠标坐标(“@x”):x 是鼠标位置与 Entry 左侧边缘的水平距离,这样就可以通过鼠标相对地定位字符的位置
选项含义
background

1. 设置 Entry 的背景颜色

2. 默认值由系统指定

bg跟 background 一样
borderwidth

1. 设置 Entry 的边框宽度

2. 默认值是 1 或 2 像素

bd跟 borderwidth 一样
cursor

1. 指定当鼠标在 Entry 上飘过的时候的鼠标样式

2. 默认值由系统指定

exportselection

1. 指定选中的文本是否可以被复制到剪贴板

2. 默认值是 True

3. 可以修改为 False 表示不允许复制文本

font

1. 指定 Entry 中文本的字体

2. 默认值由系统指定

foreground

1. 设置 Entry 的文本颜色

2. 默认值由系统指定

fg跟 foreground 一样
highlightbackground

1. 指定当 Entry 没有获得焦点的时候高亮边框的颜色

2. 默认值由系统指定

highlightcolor

1. 指定当 Entry 获得焦点的时候高亮边框的颜色

2. 默认值由系统指定

highlightthickness

1. 指定高亮边框的宽度

2. 默认值是 1 或 2 像素

insertbackground指定输入光标的颜色
insertborderwidth

1. 指定输入光标的边框宽度

2. 如果被设置为非 0 值,光标样式会被设置为 RAISED

3. 小甲鱼温馨提示:将 insertwidth 设置大一点才能看到效果哦

insertofftime

1. 该选项控制光标的闪烁频率(灭)

2. 单位是毫秒

insertontime

1. 该选项控制光标的闪烁频率(亮)

2. 单位是毫秒

insertwidth

1. 指定光标的宽度

2. 默认值是 1 或 2 像素

invalidcommand

1. 指定当输入框输入的内容“非法”时调用的函数

2. 也就是指定当 validateCommand 选项指定的函数返回 False 时的函数

3. 详见本内容最下方小甲鱼关于验证详解

invcmd跟 invalidcommand 一样
justify

1. 定义如何对齐输入框中的文本

2. 使用 LEFT,RIGHT 或 CENTER

3. 默认值是 LEFT

relief

1. 指定边框样式

2. 默认值是 SUNKEN

3. 其他可以选择的值是 FLAT,RAISED,GROOVE 和 RIDGE

selectbackground

1. 指定输入框的文本被选中时的背景颜色

2. 默认值由系统指定

selectborderwidth

1. 指定输入框的文本被选中时的边框宽度(选中边框)

2. 默认值由系统指定

selectforeground

1. 指定输入框的文本被选中时的字体颜色

2. 默认值由系统指定

show

1. 设置输入框如何显示文本的内容

2. 如果该值非空,则输入框会显示指定字符串代替真正的内容

3. 将该选项设置为 "*",则是密码输入框

state

1. Entry 组件可以设置的状态:NORMAL,DISABLED 或 "readonly"(注意,这个是字符串。它跟 DISABLED 相似,但它支持选中和拷贝,只是不能修改,而 DISABLED 是完全禁止)

2. 默认值是 NORMAL

3. 注意,如果此选项设置为 DISABLED 或 "readonly",那么调用 insert() 和 delete() 方法都会被忽略

takefocus

1. 指定使用 Tab 键可以将焦点移动到输入框中

2. 默认是开启的,可以将该选项设置为 False 避免焦点在此输入框中

textvariable

1. 指定一个与输入框的内容相关联的 Tkinter 变量(通常是 StringVar)

2. 当输入框的内容发生改变时,该变量的值也会相应发生改变

validate

1. 该选项设置是否启用内容验证

2. 详见本内容最下方小甲鱼关于验证详解

validatecommand

1. 该选项指定一个验证函数,用于验证输入框内容是否合法

2. 验证函数需要返回 True 或 False 表示验证结果

3. 注意,该选项只有当 validate 的值非 "none" 时才有效

3. 详见本内容最下方小甲鱼关于验证详解

vcmd跟 validatecommand 一样
width

1. 设置输入框的宽度,以字符为单位

2. 默认值是 20

3. 对于变宽字体来说,组件的实际宽度等于字体的平均宽度乘以 width 选项的值

xscrollcommand

1. 与 scrollbar(滚动条)组件相关联

2. 如果你觉得用户输入的内容会超过该组件的输入框宽度,那么可以考虑设置该选项

3. 使用方法可以参考:Scrollbar 组件 [bbs.fishc.com]

方法

delete(first, last=None)

– 删除参数 first 到 last 范围内(包含 first 和 last)的所有内容

– 如果忽略 last 参数,表示删除 first 参数指定的选项

– 使用 delete(0, END) 实现删除输入框的所有内容

get()

– 获得当前输入框的内容

icursor(index)

– 将光标移动到 index 参数指定的位置

– 这同时也会设置 INSERT 的值

index(index)

– 返回与 index 参数相应的选项的序号(例如 e.index(END))

insert(index, text)

– 将 text 参数的内容插入到 index 参数指定的位置

– 使用 insert(INSERT, text) 将 text 参数指定的字符串插入到光标的位置

– 使用 insert(END, text) 将 text 参数指定的字符串插入到输入框的末尾

scan_mark(x)

– 使用这种方式来实现输入框内容的滚动

– 需要将鼠标按下事件绑定到 scan_mark(x) 方法(x 是鼠标当前的水平位置),然后再将 <motion> 事件绑定到 scan_dragto(x) 方法(x 是鼠标当前的水平位置),就可以实现输入框在当前位置和 sacn_mack(x) 指定位置之间的水平滚动

selection_adjust(index)

– 该方法是为了确保输入框中选中的范围包含 index 参数所指定的字符

– 如果选中的范围已经包含了该字符,那么什么事情也不会发生

– 如果选中的范围不包含该字符,那么会从光标的位置将选中的范围扩展至该字符

selection_clear()

– 取消选中状态

selection_from(index)

– 开始一个新的选中范围

– 会设置 ANCHOR 的值

selection_present()

– 返回输入框是否有处于选中状态的文本

– 如果有则返回 True,否则返回 False

selection_range(start, end)

– 设置选中范围

– start 参数必须必 end 参数小

– 使用 selection_range(0, END) 选中整个输入框的所有内容

selection_to(index)

– 选中 ANCHOR 到 index 参数的间的所有内容

xview(index)

– 该方法用于确保给定的 index 参数所指定的字符可见

– 如有必要,会滚动输入框的内容

xview_moveto(fraction)

– 根据 fraction 参数给定的比率调整输入框内容的可见范围

– fraction 参数的范围是 0.0 ~ 1.0,0.0 表示输入框的开始位置,1.0 表示输入框的结束位置

xview_scroll(number, what)

– 根据给定的参数水平滚动输入框的可见范围

– number 参数指定滚动的数量,如果是负数则表示反向滚动

– what 参数指定滚动的单位,可以是 UNITS 或 PAGES(UNITS 表示一个字符单元,PAGES 表示一页)

eg:

在这里插入图片描述

	from tkinter import *
	 
	root = Tk()
	 
	label1 = Label(root, text='作品:').grid(row=0, column=0, padx=10, pady=10)
	label2 = Label(root, text='作者:').grid(row=1, column=0, padx=10, pady=10)
	 
	 
	e1 = Entry(root)
	e1.grid(row=0, column=1, padx=10, pady=10)
	e2 = Entry(root)
	e2.grid(row=1, column=1, padx=10, pady=10)
	 
	 
	def show():
	    print('作品: <<%s>> \n作者: %s' % (e1.get(), e2.get()))
	    e1.delete(0, END)
	    e2.delete(0, END)
	          
	b1 = Button(root, text='获取信息', width=10, command=show).grid(row=2, column=0, sticky=W, padx=10, pady=10)
	b2 = Button(root, text='退出', width=10, command=root.quit).grid(row=2, column=1, sticky=E, padx=10, pady=10)
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
关于验证详解

Entry 组件是支持验证输入内容的合法性的,比如要求输入数字,你输入了字母那就是非法。实现该功能,需要通过设置 validate、validatecommand 和 invalidcommand 选项。

首先启用验证的“开关”是 validate 选项,该选项可以设置的值有:

含义
'focus'当 Entry 组件获得或失去焦点的时候验证
'focusin'当 Entry 组件获得焦点的时候验证
'focusout'当 Entry 组件失去焦点的时候验证
'key'当输入框被编辑的时候验证
'all'当出现上边任何一种情况的时候验证
'none'

1. 关闭验证功能

2. 默认设置该选项(即不启用验证)

3. 注意,是字符串的 'none',而非 None

invalidcommand 选项指定的函数只有在 validatecommand 的返回值为 False 的时候才被调用。

Tkinter 为验证函数提供一些额外的选项:

额外选项含义
'%d'操作代码:0 表示删除操作;1 表示插入操作;2 表示获得、失去焦点或 textvariable 变量的值被修改
'%i'

1. 当用户尝试插入或删除操作的时候,该选线表示插入或删除的位置(索引号)

2. 如果是由于获得、失去焦点或 textvariable 变量的值被修改而调用验证函数,那么该值是 -1

'%P'

1. 当输入框的值允许改变的时候,该值有效

2. 该值为输入框的最新文本内容

'%s'该值为调用验证函数前输入框的文本内容
'%S'

1. 当插入或删除操作触发验证函数的时候,该值有效

2. 该选项表示文本被插入和删除的内容

'%v'该组件当前的 validate 选项的值
'%V'

1. 调用验证函数的原因

2. 该值是 'focusin','focusout','key' 或 'forced'(textvariable 选项指定的变量值被修改)中的一个

'%W'该组件的名字

为了使用这些选项,你可以这样写:validatecommand=(f, s1, s2, …)

其中,f 就是你“冷却后”的验证函数名,s1、s2、s3 这些是额外的选项,这些选项会作为参数依次传给 f 函数。我们刚刚说了,使用隐藏技能前需要冷却,其实就是调用 register() 方法将验证函数包装起来:

加法计算器:

	from tkinter import *
	 
	root = Tk()
	 
	v1 = StringVar()
	v2 = StringVar()
	v3 = StringVar()
	 
	def check(num):
	    return num.isdigit():
	    
	CMD = root.register(check)    
	e1 = Entry(root, textvariable=v1, validate='key', validatecommand=(CMD, '%P'))
	e2 = Entry(root, textvariable=v2, validate='key', validatecommand=(CMD, '%P'))
	e3 = Entry(root, textvariable=v3, state='readonly')
	e1.grid(row=0, column=0, padx=10, pady=10)
	e2.grid(row=0, column=2, padx=10, pady=10)
	e3.grid(row=0, column=4, padx=10, pady=10)
	 
	l1 = Label(root, text='+', font='20').grid(row=0, column=1)
	l2 = Label(root, text='=', font='20').grid(row=0, column=3)
	 
	def calc():
	    total = int(e1.get()) + int(e2.get())
	    v3.set(str(total))
	 
	b = Button(root, text='Calculate', command=calc).grid(row=1, column=2)
	 
	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

Listbox 列表框

Listbox 只能包含文本项目,并且所有的项目都需要使用相同的字体和颜色。根据组件的配置,用户可以从列表中选择一个或多个选项。

listbox.insert(索引号,字符串) 方法添加文本。eg, inset(0, ‘a’) or insert(END, ‘b’) 上一行结束位置插入

listbox.delete(索引号) eg delete(ACTIVE) 删除选中项(多个选中时选择最后一个)

selectmode

1. 决定选择的模式

2. 四种不同的选择模式:SINGLE(单选)、BROWSE(也是单选,但拖动鼠标或通过方向键可以直接改变选项)、MULTIPLE(多选)和 EXTENDED(也是多选,但需要同时按住 Shift 键或 Ctrl 键或拖拽鼠标实现)

3. 默认是 BROWSE

xscrollcommand

1. 为 Listbox 组件添加一条水平滚动条

2. 将此选项与 Scrollbar 组件相关联即可

yscrollcommand

1. 为 Listbox 组件添加一条垂直滚动条

2. 将此选项与 Scrollbar 组件相关联即可

方法:

*yview(*args)

– 该方法用于在垂直方向上滚动 Listbox 组件的内容,一般通过绑定 Scollbar 组件的 command 选项来实现(具体操作参考:Scrollbar [bbs.fishc.com]

– 如果第一个参数是 MOVETO,则第二个参数表示滚动到指定的位置:0.0 表示最顶端,1.0 表示最底端

– 如果第一个参数是 SCROLL,则第二个参数表示滚动的数量,第三个参数表示滚动的单位(可以是 UNITS 或 PAGES),例如:yview(SCROLL, 3, PAGES) 表示向下滚动三页

通常和scrollbar联动,显示更多项目

Scrollbar 滚动条

Scrollbar 组件通常几乎与 Text 组件、Canvas 组件和 Listbox 组件一起使用,水平滚动条还能跟 Entry 组件配合。

为了在某个组件上安装垂直滚动条,需要做两件事:

1.设置该组件的yscrollcommand==Scrollbar的组件的set方法

2.设置Scrollbar组件的command选项为该组件的yview()方法

分析:当 Listbox 组件的可视范围发生改变的时候,Listbox 组件通过调用 set() 方法通知 Scrollbar 组件。而当用户操纵滚动条的时候,将自动调用 Listbox 组件的 yview() 方法。

添加水平滚动条方法跟上边一样,只是将 yscrollcommand 改为 xscrollcommand,yview 改为 xview 即可。

eg:

在这里插入图片描述

	from tkinter import *
	 
	root = Tk()
	f1 = Frame(root)
	f1.pack(side=TOP)
	f2 = Frame(root)
	f2.pack(side=BOTTOM)
	 
	s = Scrollbar(f1)
	s.pack(side=RIGHT, fill=Y)
	 
	lb = Listbox(f1, selectmode=EXTENDED, yscrollcommand=s.set)
	lb.pack(side=LEFT, fill=BOTH)
	 
	for i in range(1000):
	    lb.insert(END, i)
	 
	Button(f2, text='DELETE', command=lambda x=lb:x.delete(ACTIVE)).pack(side=BOTTOM)
	 
	s.config(command=lb.yview)
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Scale组件

*Scale(master=None, **options) (class)

frome_ 和 to 滚动范围

tickinterval 刻度

resolution 步长(一次调节的量)

length 滚动条的长度

get()

– 获得当前滑块的位置

在这里插入图片描述

	from tkinter import *
	 
	root = Tk()
	 
	s1 = Scale(root, from_=0, to=50, \
	           tickinterval=5, resolution=3, length=150)
	s1.pack()
	s2 = Scale(root, from_=0, to=100, orient=HORIZONTAL, \
	           tickinterval=10, resolution=20, length=150)
	s2.pack()
	 
	def location():
	    print('VERTICAL: %s \nHORIZONTAL: %s' %(s1.get(), s2.get()))
	Button(root, text='Location', command=location).pack()
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

text组件

Text 组件用于显示文本文档,包含纯文本或格式化文本(使用不同字体,嵌入图片,显示链接,甚至是带 CSS 格式的 HTML 等)。因此,它常常也被用于作为简单的文本编辑器和网页浏览器使用.

给其插入内容,你可以使用 insert() 方法以及 INSERT 或 END 索引号.

在 Text 组件中插入对象,可以使用 window_create() 和 image_create() 方法

删除 Text 组件中的内容可以用 delete() 方法,下边代码用于删除所有内容(也包含 window 和 image 对象,但不会删除 marks 的内容),删除单个时使用第一个参数即可

text.delete(1.0, END)

text.delete(b1)

state 默认NORMAL, 设为DISABLED 表示只读

get() – 获取内容

index() 方法用于将所有支持的“索引”格式 --> print(text.index(INSERT))

在这里插入图片描述

	from tkinter import *
	 
	root = Tk()
	 
	text1 = Text(root, width=50, height=40)
	text1.pack()
	 
	text1.insert(INSERT, 'starting writing\n')
	 
	photo = PhotoImage(file='g.gif')
	 
	def show():
	    text1.insert(END, '\nshow a new photo')
	    text1.image_create(END, image=photo)  # insert a photo into textbox after click button
	    
	button = Button(text1, text='Click Me!', command=show)
	 
	# insert a button into the textbox
	text1.window_create(INSERT, window=button)
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
–Indexes 用法

Indexes(索引)是用来指向 Text 组件中文本的位置,跟 Python 的序列索引一样,Text 组件索引也是对应实际字符之间的位置。

Tkinter 提供一系列不同的索引类型:

  • “line.column”(行/列)
    • 1.0 – 行号以 1 开始,列号则以 0 开始
    • 允许使用行号大于当前行数,取已有内容末尾的下一个位置
    • 允许使用浮点数表示,“1.2”, 1.6 都可以用
    • 使用 index() 方法可以将所有支持的“索引”格式转换为“行/列”格式的索引号。
  • “line.end”(某一行的末尾)
    • 表示为该行最后一个字符的位置
  • INSERT
    • 对应插入光标的位置。
  • CURRENT
    • 对应与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应。
  • END
    • 对应 Text 组件的文本缓冲区最后一个字符的下一个位置。
  • user-defined marks
    • INSERT 和 CURRENT 是两个预先命名好的 marks,除此之外你可以自定义 marks
  • user-defined tags(“tag.first”,“tag.last”)
    • User-defined tags 代表可以分配给 Text 组件的特殊事件绑定和风格
    • 如果查无此 tag,那么 Tkinter 会抛出一个TclError 异常。
  • selection(SEL_FIRST,SEL_LAST)
    • 是一个名为 SEL(或 “sel”)的特殊 tag,表示当前被选中的范围,你可以使用 SEL_FIRST 到 SEL_LAST 来表示这个范围。如果没有选中的内容,那么 Tkinter 会抛出一个TclError 异常。
  • window coordinate(“@x,y”)
    • 窗口坐标作为索引, “@%d,%d” % (event.x, event.y) --找到最接近鼠标位置的字符
  • embedded object name(window,images)
    • 用于指向在 Text 组件中嵌入的 window 和 image 对象。要引用一个 window,只要简单地将一个 Tkinter 组件实例作为索引即可。
  • expressions
    • 用字符串的形式实现修改索引的表达式。
表达式含义
"+ count chars"

1. 将索引向前(->)移动 count 个字符

2. 可以越过换行符,但不能超过 END 的位置

"- count chars"

1. 将索引向后(<-)移动 count 个字符

2. 可以越过换行符,但不能超过 "1.0" 的位置

"+ count lines"

1. 将索引向前(->)移动 count 行

2. 索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾

"- count lines"

1. 将索引向后(<-)移动 count 行

2. 索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾

" linestart"

1. 将索引移动到当前索引所在行的起始位置

2. 注意,使用该表达式前边必须有一个空格隔开

" lineend"

1. 将索引移动到当前索引所在行的末尾

2. 注意,使用该表达式前边必须有一个空格隔开

" wordstart"

1. 将索引移动到当前索引指向的单词的开头

2. 单词的定义是一系列字母、数字、下划线或任何非空白字符的组合

3. 注意,使用该表达式前边必须有一个空格隔开

" wordend"

1. 将索引移动到当前索引指向的单词的末尾

2. 单词的定义是一系列字母、数字、下划线或任何非空白字符的组合

3. 注意,使用该表达式前边必须有一个空格隔开

TIPS:只要结果不产生歧义,关键字可以被缩写,空格也可以省略。例如:“+ 5 chars” 可以简写成 “+5c”

–mark_set()方法

Marks(标记)通常是嵌入到 Text 组件文本中的不可见对象。事实上 Marks 是指定字符间的位置(可以理解为一种索引),并跟随相应的字符一起移动。Marks 有 INSERT,CURRENT 和 user-defined marks(用户自定义的 Marks)。其中,INSERT 和 CURRENT 是 Tkinter 预定义的特殊 Marks,它们不能够被删除。

INSERT(或 “insert”)用于指定当前插入光标的位置,Tkinter 会在该位置绘制一个闪烁的光标(因此并不是所有的 Marks 都不可见)。

CURRENT(或 “current”)用于指定与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应。

你还可以自定义任意数量的 Marks,Marks 的名字是由普通字符串组成,可以是除了空白字符外的任何字符。使用 mark_set() 方法创建和移动 Marks。

如果你在一个 Mark 标记的位置之前插入或删除文本,那么 Mark 跟着一并移动(插入一个字符的话,Mark 向后移动了一个字符的位置)。

  • 默认插入内容到 Mark,是插入到它的左侧,mark_gravity为LEFT时,是插入到他的右侧, 感觉是默认mark会’记住’后面元素的位置,mark_gravity为LEFT时,那就是’记住’前面的元素位置。
  • 删除 Marks 的唯一办法是使用 mark_unset() 方法,删除 Mark 周围的文本并不会删除 Mark 本身(mark周围所有元素被删除时,会被初始化为1.0)。

在这里插入图片描述

	from tkinter import *
	 
	root = Tk()
	 
	text = Text(root, width=50, height=30)
	text.pack()
	 
	text.insert(INSERT, 'starting writing')
	text.mark_set('here', '1.3', )
	#text.mark_gravity('here', LEFT)
	text.insert('here', 'GOD')
	text.insert('here', 'GUN')
	 
	text.mark_unset('here') # clear the mark
	text.insert('here', 'CAR')  # TclError: bad text index "here" as mark had gone
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
–tags用法

Tags(标签)通常用于改变 Text 组件中内容的样式和功能。你可以修改文本的字体、尺寸和颜色。另外,Tags 还允许你将文本、嵌入的组件和图片与键盘和鼠标等事件相关联。除了 user-defined tags(用户自定义的 Tags),还有一个预定义的特殊 Tag:SEL(或 “sel” 用于表示对应的选中内容)

创建方法:

text.insert(INSERT, “I love this iphone13”)

text.tag_add(“tag1”, “1.7”, “1.12”, “1.14”) # 范围两个一组表示区间,单个的表示一个位置

text.tag_config(“tag1”, background=“yellow”, foreground=“red”)

Note: 可以直接使用tag_config()来创建一个不存在的tag, 但是指定不了范围

Tag_config() 参数

选项含义
background

1. 指定该 Tag 所描述的内容的背景颜色

2. 注意:bg 并不是该选项的缩写,在这里 bg 被解释为 bgstipple 选项的缩写

bgstipple

1. 指定一个位图作为背景,并使用 background 选项指定的颜色填充

2. 只有设置了 background 选项该选项才会生效

3. 默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question' 和 'warning'

borderwidth

1. 指定文本框的宽度

2. 默认值是 0

3. 只有设置了 relief 选项该选项才会生效

4. 注意:该选项不能使用 bd 缩写

fgstipple

1. 指定一个位图作为前景色

2. 默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question' 和 'warning'

font指定该 Tag 所描述的内容使用的字体
foreground

1. 指定该 Tag 所描述的内容的前景色

2. 注意:fg 并不是该选项的缩写,在这里 fg 被解释为 fgstipple 选项的缩写

justify

1. 控制文本的对齐方式

2. 默认是 LEFT(左对齐),还可以选择 RIGHT(右对齐)和 CENTER(居中)

3. 注意:需要将 Tag 指向该行的第一个字符,该选项才能生效

lmargin1

1. 设置 Tag 指向的文本块第一行的缩进

2. 默认值是 0

3. 注意:需要将 Tag 指向该文本块的第一个字符或整个文本块,该选项才能生效

lmargin2

1. 设置 Tag 指向的文本块除了第一行其他行的缩进

2. 默认值是 0

3. 注意:需要将 Tag 指向整个文本块,该选项才能生效

offset

1. 设置 Tag 指向的文本相对于基线的偏移距离

2. 可以控制文本相对于基线是升高(正数值)或者降低(负数值)

3. 默认值是 0

overstrike

1. 在 Tag 指定的文本范围画一条删除线

2. 默认值是 False

relief

1. 指定 Tag 对应范围的文本的边框样式

2. 可以使用的值有:SUNKEN, RAISED, GROOVE, RIDGE 或 FLAT

3. 默认值是 FLAT(没有边框)

rmargin

1. 设置 Tag 指向的文本块右侧的缩进

2. 默认值是 0

spacing1

1. 设置 Tag 所描述的文本块中每一行与上方的空白间隔

2. 注意:自动换行不算

3. 默认值是 0

spacing2

1. 设置 Tag 所描述的文本块中自动换行的各行间的空白间隔

2. 注意:换行符('\n')不算

3. 默认值是 0

spacing3

1. 设置 Tag 所描述的文本块中每一行与下方的空白间隔

2. 注意:自动换行不算

3. 默认值是 0

tabs

1. 定制 Tag 所描述的文本块中 Tab 按键的功能

2. 默认 Tab 被定义为 8 个字符的宽度

3. 你还可以定义多个制表位:tabs=('3c', '5c', '12c') 表示前 3 个 Tab 宽度分别为 3厘米,5厘米,12厘米,接着的 Tab 按照最后两个的差值计算,即:19厘米,26厘米,33厘米

4. 你应该注意到了,它上边 'c' 的含义是“厘米”而不是“字符”,还可以选择的单位有 'i'(英寸),'m'(毫米)和 'p'(DPI,大约是 '1i' 等于 '72p')

5. 如果是一个整型值,则单位是像素

underline

1. 该选项设置为 True 的话,则 Tag 所描述的范围内文本将被画上下划线

2. 默认值是 False

wrap

1. 设置当一行文本的长度超过 width 选项设置的宽度时,是否自动换行

2. 该选项的值可以是:NONE(不自动换行),CHAR(按字符自动换行)和 WORD(按单词自动换行)

如果你对同一个范围内的文本加上多个 Tags,并且设置相同的选项,那么新创建的 Tag 样式会覆盖比较旧的 Tag:

tag_raise() / tag_lower() 可以改变优先级

tag支持事件绑定, see the example.

tag_bind(‘tag_name’, ‘<event_name>’, command)

移除tag:

tag_delete(*tagNames) – 删除 tagNames 指定的 Tags

tag_remove(tagName, index1, index2=None)

– 删除 index1 到 index2 之间所有的 tagName

– 如果忽略 index2 参数,那么只删除 index1 指定的那个字符的 tagName(如果有的话)

	from tkinter import *
	import webbrowser
	
	root = Tk()
	t1 = Text(root, width=40, height=20)
	t1.pack()
	t1.insert('1.0', 'Iceberg Right Head!')
	
	#创建两个tag
	t1.tag_config('tag1', background='black', foreground='yellow')
	t1.tag_config('tag2', background='gray')
	
	# 新建的tag优先级比旧的高,可用tag_raise() or tag_lower()改变优先级
	t1.insert(END, 'click me to escape', ('tag1', 'tag2')) # backgroud 会显示blue
	
	# 创建新tag用于超链(click me)
	t1.tag_add('tag3', '1.19', '1.27', '1.30', '1.32') 
	t1.tag_config('tag3', underline=True)
	
	def show_hand_cursor(event):
	    t1.config(cursor='arrow')
	
	def show_arrow_cursor(event):
	    t1.config(cursor='xterm')
	
	def click(event):
	    webbrowser.open('www.zhihu.com')
	
	#绑定事件
	t1.tag_bind('tag3', '<Enter>', show_hand_cursor)
	t1.tag_bind('tag3', '<Leave>', show_arrow_cursor)
	t1.tag_bind('tag3', '<Button-1>', click)
	
	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
Text.Get() — 获得text内容

eg:通过hashlib.md5 – 检测内容变动

	from tkinter import *
	import hashlib
	
	root = Tk()
	text = Text(root, width=20, height=10)
	text.pack()
	
	text.insert('1.0', 'Love is burn into peace')
	
	contents = text.get('1.0', END)
	
	def getSig(contents):
	    m = hashlib.md5(contents.encode())
	    return m.digest()
	
	org = getSig(contents)
	
	def check():
	    new_content = text.get('1.0', END)
	    if org != getSig(new_content):
	        print('情况有变,小心traitor!')
	    else:
	        print('一切如旧~')
	
	Button(root, text='稽查', command=check).pack()
	
	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
Text.Search()

*search(pattern, index, stopindex=None, forwards=None, backwards=None, exact=None, regexp=None, nocase=None, count=None)

– 从 index 开始搜索 pattern,到 stopindex 结束(不指定表示搜索到末尾)

– 如果成功找到,以 “line.column” 返回第一个匹配的字符;否则返回空字符串

– forwards 参数设置为 True 表示向前(->)搜索

– backwards 参数设置为 True 表示向后(<-)搜索

– exact 参数设置为 True 表示搜索与 pattern 完全匹配的结果

– regexp 参数设置为 True,则 pattern 被解释为 Tcl 格式的正则表达式

– nocase 参数设置为 True 是忽略大小写,默认是区分大小写的搜索

– count 参数指定为一个 IntVar 的 Tkinter 变量,用于存放当找到匹配的字符个数(如果匹配结果中没有嵌入的 image 或 window 对象的话,一般该值等于 pattern 的字符个数)

Eg: 查找字符串

	from tkinter import *
	
	root = Tk()
	text = Text(root, width=20, height=10)
	text.pack()
	
	text.insert('1.0', 'Love is burn into peace')
	
	def getIndex(text, inx):
	    return tuple(map(int, text.index(inx).split('.')))
	
	start = '1.0'
	while True:
	    loc= text.search('o', start, stopindex=END) #查找到第一个结果后返回line.num并停止
	    if not loc: #找不到结果时终止循环
	        break
	    print('found it in ', getIndex(text, loc))
	    start = loc + '+1c'  #向后移动一个字节,继续查找
	    
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

撤销 和 恢复

通过设置 undo 选项为 True 可以开启 Text 组件的“撤销”功能。然后用 edit_undo() 方法实现“撤销”操作,用 edit_redo() 方法实现“恢复”操作。

这是因为 Text 组件内部有一个栈专门用于记录内容的每次变动,所以每次“撤销”操作就是一次弹栈操作,“恢复”就是再次压栈。

默认情况下,每一次完整的操作将会放入栈中。但怎么样算是一次完整的操作呢?Tkinter 觉得每次焦点切换、用户按下 Enter 键、删除\插入操作的转换等之前的操作算是一次完整的操作。也就是说你连续输入“FishC 是个 P”的话,一次的“撤销”操作就会将所有的内容删除。

做法就是先将 autoseparators 选项设置为 False(因为这个选项是让 Tkinter 在认为一次完整的操作结束后自动插入“分隔符”),然后绑定键盘事件,每次有输入就用 edit_separator() 方法人为地插入一个“分隔符”,这样插入一个字符就算一次完整的操作,然后每次点击“撤销”就去掉一个字符。

*edit_redo(self)

– “恢复”上一次的“撤销”操作

– 如果 undo 选项为 False,该方法无效

– 详见上方用法【“撤销”和“恢复”操作】

*edit_separator()

– 插入一个“分隔符”到存放操作记录的栈中,用于表示已经完成一次完整的操作

– 如果 undo 选项为 False,该方法无效

– 详见上方用法【“撤销”和“恢复”操作】

*edit_undo()

– 撤销最近一次操作

– 如果 undo 选项为 False,该方法无效

– 详见上方用法【“撤销”和“恢复”操作】

EG:

	from tkinter import *
	import hashlib
	
	root = Tk()
	# 'undo=True' 激活撤销/恢复功能
	# 'autoseparators=False' 关闭自动设置separator设置
	text = Text(root, width=30, height=10, undo=True, autoseparators=False, maxundo=10)
	text.pack()
	
	def typing(event):
	    text.edit_separator()
	
	def undo():
	    text.edit_undo()
	
	def redo():
	    text.edit_redo()
	
	text.bind('<Key>', typing) #绑定键盘按键,每次点击都设置separator,方便undo/redo
	text.insert('1.0', 'Love is burn into peace')
	
	Button(root, text='UNDO', command=undo).pack()
	Button(root, text='REDO', command=redo).pack()
	
	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

Canvas 组件

Canvas(画布)组件为 Tkinter 的图形绘制提供了基础。Canvas 是一个高度灵活的组件,你可以用它绘制图形和图表,创建图形编辑器,并实现各种自定义的小部件。

–随心所欲绘制图像

Canvas(root, width=100, height=100) 单位像素

创建的对象一直保留,直到被修改才会覆盖

修改方法:

w.coords() 移动对象

w.itemcofig() 设置对象属性

w.delete() 删除对象

anvas 组件支持对象*

  • arc(弧形、弦或扇形)
  • bitmap(内建的位图文件或 XBM 格式的文件)
  • image(BitmapImage 或 PhotoImage 的实例对象)
  • line(线)
  • oval(圆或椭圆形)
  • polygon(多边形)
  • rectangle(矩形)
  • text(文本)
  • window(组件)
    其中,弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线和填充颜色组成的,但都可以设置为透明(传入空字符串表示透明)。

常用创建方法:

Create_line(x1,y1,x2,y2,dash=(4,4), fill=‘blue’) – 直线, 虚线(指定dash)

Create_rectangle() – 矩形,添加对角坐标

Create_oval() – 椭圆,使用的是长方形的坐标绘制的,正方形坐标时就是圆形

Create_text(x,y, text=‘F’) --字体中心点坐标

create_arc(bbox, **options) – 根据 bbox (x1, y1, x2, y2) 创建一个扇形(PIESLICE)、弓形(CHORD)或弧形(ARC)

style

1. 指定该方法创建的是扇形(PIESLICE)、弓形(CHORD)还是弧形(ARC)

2. 默认创建的是扇形

create_polygon(coords, **options) – 根据 coords 给定的坐标绘制一个多边形

坐标系

由于画布可能比窗口大(带有滚动条的 Canvas 组件),因此 Canvas 组件可以选择使用两种坐标系:

  • 窗口坐标系:以窗口的左上角作为坐标原点

  • 画布坐标系:以画布的左上角作为坐标原点
    将窗口坐标系转换为画布坐标系,可以使用 canvasx() 或 canvasy() 方法:

    def callback(event):
        canvas = event.widget
        x = canvas.canvasx(event.x)
        y = canvas.canvasy(event.y)
        print canvas.find_closest(x, y)
    
    • 1
    • 2
    • 3
    • 4
    • 5

对象显示顺序:

Canvas 组件中创建的画布对象都会被列入显示列表中,

默认情况下新创建的会覆盖旧的画布对象的重叠部分,即位于显示列表上方的画布对象将覆盖下方那个)。当然,显示列表中的画布对象可以被重新排序。

指定画布对象

Canvas 组件提供几种方法让你指定画布对象:

  • Item handles (tkinter自动创建的唯一的画布对象的 ID–整型)
  • Tags ( 类似于text的 Tags但 是仅为画布对象所拥有)
  • ALL (Canvas中所有对象)
  • CURRENT (鼠标指针下的画布对象(如果有的话))

EG: 绘制五角星(outline , fill)

在这里插入图片描述

“2 * PI / 5” 是用弧度的方式表示的。

Note: 关于弧度和度的区别

“度”的定义是,“两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度。(如图1)

“弧度”的定义是:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度。(如图2)

定义相似,区别仅在于角所对的弧长大小不同。1度的对应的弧长是等于圆周长的360分之一,而1弧度的是等于半径。

在这里插入图片描述

它们的关系可用下式表示和计算:

角(弧度)=弧长/半径

圆的周长是半径的 2π倍,所以一个周角(360度)是 2π弧度。

半圆的长度是半径的 π倍,所以一个平角(180度)是 π弧度。

<参考自https://www.jianshu.com/p/2823a0b18278>

在这里插入图片描述

	from tkinter import *
	import math as m
	
	root = Tk()
	
	w = Canvas(root, width=480, height=320, background='red')
	w.pack()
	
	# 圆心(x, y)和半径r
	def draw_star(r, x, y):
	    # 各个点的坐标
	    points = [
	        # 左上角
	        x-int(r * m.sin(2 * m.pi / 5)), \
	        y-int(r * m.cos(2 * m.pi / 5)), \
	        # 右上角
	        x+int(r * m.sin(2 * m.pi / 5)), \
	        y-int(r * m.cos(2 * m.pi / 5)), \
	        # 左下角
	        x-int(r * m.sin(m.pi / 5)), \
	        y+int(r * m.cos(m.pi / 5)), \
	        # 顶点
	        x, \
	        y-r, \
	        # 右下角
	        x+int(r * m.sin(m.pi / 5)), \
	        y+int(r * m.cos(m.pi / 5)), \
	        ]
	
	    star = w.create_polygon(points, fill='yellow')
	
	draw_star(96, 160, 160)
	draw_star(32, 320, 64)
	draw_star(32, 384, 128)
	draw_star(32, 384, 224)
	draw_star(32, 320, 288)
	
	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

在这里插入图片描述

EG: 制作画板

Tips: 通过最小正方形创建小圆点(Canvas 不能直接画点), 绑定鼠标左键 bind(<B1-Motion>, paint)

	from tkinter import *
	import math as m
	
	root = Tk()
	
	w = Canvas(root, width=500, height=400)
	w.pack()
	
	def paint(event):
	    x1, y1 = (event.x - 1), (event.y - 1)
	    x2, y2 = (event.x + 1), (event.y + 1)
	    w.create_oval(x1, y1, x2, y2, fill='red')
	
	# 绑定鼠标左键事件(mouse B1-left,B2-middle,B3-right)
	w.bind('<B3-Motion>', paint)
	
	# 创建一个按钮清除画板
	Button(root, text='CLEAR', command=lambda x=ALL:w.delete(x)).pack(side=BOTTOM)
	Label(root, text='Please hold the mouse button and move!').pack(side=BOTTOM)
	
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

EG: 画哆啦A梦

	''' Draw a Doraemon '''
	
	from tkinter import *
	import math as m
	
	root = Tk()
	
	w = Canvas(root, width=450, height=450, background='white')
	w.pack()
	
	def oval(x1, y1, x2, y2, color):
	    w.create_oval(x1, y1, x2, y2, fill=color)
	
	def line(x1, y1, x2, y2, color):
	    w.create_line(x1, y1, x2, y2, fill=color)
	
	
	def rect(x1, y1, x2, y2, color):
	    w.create_rectangle(x1, y1, x2, y2, fill=color)
	    
	# Head
	oval(140, 90, 320, 270, 'blue')
	# face
	oval(160, 130, 300, 270, 'white')
	# eyes
	oval(200, 100, 230, 140, 'white')
	oval(230, 100, 260, 140, 'white')
	oval(215, 110, 225, 130, 'black')
	oval(235, 110, 245, 130, 'black')
	oval(218, 115, 222, 127, 'white')
	oval(238, 115, 242, 127, 'white')
	# nose
	oval(223, 135, 238, 150, 'red')
	# whisker
	line(175, 150, 210, 160, 'black')
	line(245, 160, 280, 150, 'black')
	line(170, 175, 210, 175, 'black')
	line(245, 175, 285, 175, 'black')
	line(175, 200, 210, 190, 'black')
	line(245, 190, 280, 200, 'black')
	line(230, 150, 230, 220, 'black')
	# mouth
	w.create_arc(165, 100, 300, 220, style=ARC, start=225)
	
	
	# body
	rect(165, 240, 295, 370, 'blue')
	oval(180, 235, 280, 335, 'white')
	w.create_arc(190, 260, 270, 320, fill='', style=ARC, start=180)
	w.create_arc(190, 260, 270, 320, fill='', style=ARC, start=270)
	line(190, 290, 270, 290, 'black')
	
	# neck
	w.create_line(160, 240, 300, 240, width=15, fill='red', capstyle=ROUND)
	# ring
	oval(220, 240, 240, 260, 'yellow')
	w.create_line(220, 250, 240, 250)
	w.create_line(220, 252, 240, 252)
	oval(227, 255, 232, 260, 'black')
	
	# feet
	oval(150, 350, 220, 390, 'white')
	oval(240, 350, 310, 390, 'white')
	w.create_arc(215, 365, 245, 430, style=CHORD, start=45, fill='white')
	line(215, 375, 245, 375, 'white')
	
	# left hand
	w.create_polygon(167, 245, 130, 280, 130, 300, 167, 280, fill='blue')
	oval(110, 280, 140, 310, 'white')
	# right hand
	w.create_polygon(293, 245, 325, 280, 325, 300, 293, 280, fill='blue')
	oval(315, 280, 345, 310, 'white')
	
	# body fixes
	line(165, 270, 165, 290, 'black')
	line(295, 270, 295, 290, 'black')
	
	
	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
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

在这里插入图片描述

Menu

顶级菜单 – 先创建一个菜单实例,然后使用 add() 方法将命令和其它子菜单添加进去.

root = Tk()

menubar = Menu(root)

menubar.add_command(label=‘File’, command=xxx)

NOTE: 由于该组件是底层代码实现,所以不建议你自行通过按钮和其他组件来实现菜单功能。

子菜单 – 创建方法也是大同小异,最主要的区别是它们最后需要添加到主菜单上(而不是窗口上)。

Filemenu=Menu(menubar, tearoff=FALSE) — tearoff表示是否将菜单弹出到单独窗口

弹出菜单 – 创建方法也是一致的,不过需要使用 post() 方法明确的将其显示出来,而且需要把鼠标事件和一个frame绑定

在这里插入图片描述

Menubutton() – 该组件适用于你希望菜单按钮出现在其他位置的时候, 存在于Tkinter 的早期版本

创建一个 Menubutton 组件,并创建一个 Menu 组件与之相关联

在这里插入图片描述

OptionMenu(选择菜单)-- 下拉菜单的改版,它的发明弥补了 Listbox 组件无法实现下拉列表框的遗憾。

将一个列表加到optionmenu中,使用*[list]进行解包

在这里插入图片描述

注意:星号(*)作为形参的时候是起到“打包”的作用,相反,作为实参的时候是起到“解包”的作用。

从两个示例的输出可以看出:

当参数形如 *args 时,传递给函数的任意个实参会按位置打包成一个元组(tuple);

	def fun1(*args):      
	        print(type(args))
        	print(args)
  • 1
  • 2
  • 3

当参数形如 **args 时,传递给函数的任意个 key = value 实参会被包装进一个字典(dict)。

	def fun2(**args):
	        print(type(args))
        	print(args)
  • 1
  • 2
  • 3

有打包就有解包,通过在实参前加一个星号(*)或两个星号(**)来对列表(list)、元组(tuple)或字典(dict)进行解包

	>>> a = [1, 2, 3, 4, 5]
	>>> fun1(*a)
	(1, 2, 3, 4, 5)
	>>> c = {'one':1, 'two':2, 'three':3}
	>>> fun2(**c)
	{'two': 2, 'one': 1, 'three': 3}
	 
	EG:
	from tkinter import *
	
	root = Tk()
	
	menubar = Menu(root) # 创建一个menu实例
	
	def callback():
	    print('Workhuman!')
	
	# 创建层级菜单
	filemenu = Menu(menubar, tearoff=False)
	filemenu.add_command(label='Open', command=callback)
	filemenu.add_command(label='Save', command=callback)
	filemenu.add_separator()
	filemenu.add_command(label='Quit', command=root.quit)
	menubar.add_cascade(label='File', menu=filemenu) # 关联上级菜单
	
	# 层级菜单含有checkbutton
	var = IntVar()
	var1 = IntVar()
	helpmenu = Menu(menubar, tearoff=True)
	helpmenu.add_checkbutton(label='Online Help', variable=var, command=callback)
	helpmenu.add_checkbutton(label='About', variable=var1, command=root.quit)
	menubar.add_cascade(label='Help', menu=helpmenu)
	
	# 右键单击弹出菜单
	popupmenu = Menu(root)
	def popup(event): # 绑定点击事件
	    popupmenu.post(event.x_root, event.y_root)
	
	    # 含有radiobutton
	var2 = IntVar()
	popupmenu.add_radiobutton(label='Copy', variable=var2, value=1, command=callback)
	popupmenu.add_radiobutton(label='Delete', variable=var2, value=2, command=callback)
	popupmenu.add_radiobutton(label='Paste', variable=var2, value=3, command=callback)
	
	frame = Frame(root, width=300, height=200)
	frame.pack()
	frame.bind('<B3-Motion>', popup)
	
	# 创建页面中的菜单键menubutton
	mb = Menubutton(root, text='Click me', relief=RAISED, width=10, height=5)
	mb.pack()
	
	mm = Menu(mb, tearoff=False)
	mm.add_command(label='Who', command=callback)
	mm.add_command(label='Why', command=callback)
	mb.config(menu=mm)
	 
	# 创建可选菜单optionmenu
	cars = [
	    'Fradi',
	    'Audi',
	    'Benz',
	    'BMW',
	    'Bugadi'
	    ]
	var3 = StringVar()
	var3.set(cars[2])
	om = OptionMenu(root, var3, *cars) # 解包
	om.pack()
	
	def getvalue():
	    print(var3.get())
	
	Button(text='Get', command=getvalue).pack()
	
	
	root.config(menu=menubar)
	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
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/735420
推荐阅读
相关标签
  

闽ICP备14008679号