这里和大家一起复习用户图形界面Tkinter喵~ 在Jupyter Notebook环境下打开是比较好的选择,可以每段代码单独运行

用户界面基本框架

不管你写什么,必须要有Code 1这三类语句:

# Code 1
from tkinter import * #引入Tkinter

root = Tk() #创建根窗口(窗体初始化),第一个T一定要大写嗷

root.mainloop() #进入窗口消息循环(窗体主循环)

窗口初步入门

学会简单设置窗口标题,窗口尺寸

# Code 2
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!') #设置窗口标题
root.geometry('300x200') #使得窗口大小为宽300,高200

root.mainloop()

认识控件与布局

认识各个控件,并熟记常用控件名以便作业使用
认识三种布局方法,掌握Pack与Grid方法,知道Place方法

控件认识初步

必须必须知道的!

Button 按钮

Entry 输入框

Label 标签

Text (多行)文本框

Message 消息

RadioButton 单选框

CheckButton 复选框

Listbox 列表框

学有余力可了解

Frame框架;Combobox组合框;Menu菜单;Scale滑块;Scrollabelar滚动条;Toplevel新建窗体容器

布局认识初步

必须必须知道的!

pack() 一般自上而下居中布局

grid() 表格类布局

重要 place可以与'grid'或'pack'之间的一个混用,但pack和grid不可以混用

学有余力可了解

place() 把窗口当画布一样使用

# Code 3
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('300x200')

label1=Label(root,text='我是标签1') #定义标签,参数1为在root窗口,参数2设定text='要显示的内容'
label2=Label(root,text='我是标签2') #<实例名> = 控件(父容器,可选参数)
label3=Label(root,text='我是标签3') #label3 = Label(root,text='我是标签3') 

label1.pack() #运用pack方法进行布局
label2.pack() #<实例名>.布局方法(可选参数)
label3.pack() #label3.pack()

root.mainloop()
# Code 4
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('300x200')

label1=Label(root,text='我是标签1') #<实例名> = 控件(父容器,可选参数)
label2=Label(root,text='我是标签2') #label2 = Label(root,text='我是标签2') 
label3=Label(root,text='我是标签3')
label4=Label(root,text='我是标签4')

label1.grid(column=0,row=0) #运用grid方法进行布局,放在第1列(首列),第1行(首行)
label2.grid(column=1,row=1) #<实例名>.布局方法(可选参数); 放在第2列,第2行
label3.grid(column=1,row=2) #label3.grid(column=1,row=2); 放在第2列,第3行
label4.grid(column=2,row=1) #放在第3列,第2行

'''
grid()方法常用的有这些参数:
column 控件实例的起始列,最左边为第0列。
columnspan 控件实例所跨越的列数,默认为1列。
row 控件实例的起始行,最上面为第0行。
rowspan 控件实例所跨越的行数,默认为1行。
'''

root.mainloop()

学会使用控件

控件创建与布局

控件一般放在'窗体初始化'与'窗体主循环'之间

常用格式为:

<实例名> = 控件(父容器,可选参数)

<实例名>.布局方法(可选参数)

就如Code 3&4的例子所示,上面已用注释的形式给出,可用于参考

父容器与你想让该控件出现在哪个容器实例上相关。

# Code 5
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('300x200')

label=Label(root) #新建Label控件,如果效果奇怪是正常的
button = Button(root) #新建Button控件
entry = Entry(root) #新建Entry控件

label.pack() #控件布局们
button.pack()
entry.pack()

root.mainloop()

控件的属性与参数

如Code 5,我们已经有了一些控件,但label似乎没有显示,且button是个空空的按钮,那是因为我们没有定义他们的文字属性(显示什么),那么其使用方法常为

<实例名> = 控件(父容器,可选参数)

同样Code 3&4的例子所示,上面已用注释的形式给出,可用于参考。

常见的共同属性

略,在实际作业与测试中不常用,可自行查表。但你需要掌握一些特殊属性

文本输入/输出相关控件的特殊属性

标签(Label)和消息(Message)

首先我们认识的是Label与Message,通常,Label用于单行,Message用于多行。其有特殊属性text,通过添加text参数,我们可以让其显示文字。

(如想了解其它参数,可以查表喵)

但是message并不常用,同时不能和messagebox搞混了,所以就用label吧!

此外,我们可以改变显示文字,有两种方法,一是<实例名>.configure()方法,另一种是var.set()方法,稍后给出示例。

# Code 6
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('400x400')

label1=Label(root,text='我是标签1') #定义标签,参数1为在root窗口,参数2设定text='要显示的内容'
label2=Label(root,text='我是标签2') #<实例名> = 控件(父容器,可选参数)
label3=Label(root,text='我是标签3') #label3 = Label(root,text='我是标签3') 
message1=Message(root,text='这是一段文字1,它会自动换行(如果超出了长度的话)',width=99) #width参数用来限制每一行文本的宽度,可以不用掌握
message2=Message(root,text='这是一段文字2,它会自动换行(如果超出了长度的话)',width=45)
message3=Message(root,text='这是一段文字3,它会自动换行(如果超出了长度的话)',width=200)

label1.pack() #运用pack方法进行布局
label2.pack() #<实例名>.布局方法(可选参数)
label3.pack() #label3.pack()
message1.pack()
message2.pack()
message3.pack()

root.mainloop()

接下来,假如我们想改变文本显示的内容,我们可以这样做(后面就只使用label了):

A. configure方法

控件实例的configure()/config()方法改变属性text的值,从而改变其显示的文字。

B. var.set方法

标签显示Tkinter里的类变量,StringVar。如果变量被修改,标签文本将自动更新。这里原理可能与面向对象编程中的“类”有关

先定义内部类型变量var = StringVar(),然后用textvariable属性与这个变量联系/绑定起来,即textvariable=var,用var.set()方法更新var的值

不懂不要紧,我们来看例子:

# Code 7
# configure方法

from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('400x400')

label1=Label(root,text='我是标签1') 
label2=Label(root,text='我是标签2') 
label3=Label(root,text='我是标签3') 

label1.configure(text='OMG现在标签1发生了变化!')

label1.pack() 
label2.pack() 
label3.pack() 

root.mainloop()
# Code 8
# var.set方法

from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('400x400')

var_label2 = StringVar() #定义一个可变字符串var_label2,注意需要在label2绑定之前先定义

label1=Label(root,text='我是标签1') 
label2=Label(root,text='我是标签2',textvariable=var_label2) #通过textvariable属性把label2与var_label2这个可变字符串绑定起来
label3=Label(root,text='我是标签3') 

var_label2.set('OMG现在标签2发生了变化!') #为label2设定新字符串

label1.pack() 
label2.pack() 
label3.pack() 

root.mainloop()

文本框(Text)

这里只介绍常用的几个方法,如对其他的感兴趣可自行查阅,其效果类似于编辑文本文档,你可试运行Code 9进行尝试

<实例名>.delete() 删除文本

<实例名>.get() 获取文本

<实例名>.insert() 插入文本

其中对于每个方法的属性,有:

<实例名>.delete(起始位置,可选终止位置)

<实例名>.get(起始位置,可选终止位置)

<实例名>.insert(位置,可选字符串)

注: 文本框的位置参数常为浮点数,如0.0表示第0行第0列,而END表示末尾

# Code 9
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('400x600')

label1=Label(root,text='我是标签1') 
text1=Text(root,height=25,width=30) #新建一个文本框,高20,宽30,实际操作时可不用考虑宽度与高度

label1.pack()
text1.pack() #进行放置

'''
command指令在后续按钮与函数中会提到
但你可以尝试读懂后面的代码并学习
'''

def text_delete(): #定义不含参变量函数text_delete
    text1.delete(0.0,END) #从0行0列开头删除到末尾

def text_get():
    text_input = text1.get(0.0,END) #从0行0列开头获取到末尾
    label1.configure(text=text_input) #改变标签1

def text_insert():
    text1.insert(END,"我是大聪明\n") #在末尾追加文本,\n表示换行

button_delete = Button(text='清空文本框',command=text_delete) #点击后触发text_delete函数
button_get = Button(text='获取文本框信息至标签1',command=text_get)
button_insert = Button(text='在文本框末尾追加"我是大聪明"',command=text_insert)

button_delete.pack()
button_get.pack()
button_insert.pack()

root.mainloop()

输入框(Entry)

单单纯纯的接受文本输入的控件一枚吖,使用方法和Text差不多

<实例名>.get() 取值方法,参数不适用

<实例名>.delete(起始位置,终止位置) 删除方法

例如,清空输入框的操作

entry1.delete(0,END)

# Code 10
from tkinter import * 
root = Tk() 

root.title('窝是窗口名!')
root.geometry('400x600')

label1=Label(root,text='我是标签1') 
entry1=Entry(root) #新建一个输入框
text1=Text(root) 

label1.pack()
entry1.pack()
text1.pack() #进行放置

'''
command指令在后续按钮与函数中会提到
但你可以尝试读懂后面的代码并学习
'''

def entry_delete(): #定义不含参变量函数entry_delete
    entry1.delete(0,END) #从第0个字符开始删除到末尾

def entry_get():
    entry_input = entry1.get() #获取输入框内容
    label1.configure(text=entry_input) #改变标签1

def entry_insert():
    entry_input = entry1.get()
    text1.insert(END,entry_input+'\n') #在末尾追加文本,\n表示换行

button_delete = Button(text='清空文本框',command=entry_delete) #点击后触发text_delete函数
button_get = Button(text='获取文本框信息至标签1',command=entry_get)
button_insert = Button(text='在文本框末尾追加输入框的内容',command=entry_insert)

button_delete.pack()
button_get.pack()
button_insert.pack()

root.mainloop()

按钮(Button)

按钮(Button)主要是为响应鼠标单击事件触发运行程序所设的,故其除控件共有属性外,command属性是最为重要的属性

通常,将按钮要触发执行的程序以函数形式预先定义,然后可用以下两种方法调用函数

直接调用,不含参函数

直接调用,参数表达式为command = 函数名
不加括号,不能传递参数,但对于任何你要进行计算的,你都可以使用.get()方法获取输入框里的内容/值

如Code 10中这段代码:

button_delete = Button(text='清空文本框',command=entry_delete)

其含义为“定义一个button_delete,赋予Button的控件属性,显示文本为'清空文本框',响应后执行'entry_delete'函数”点击后触发text_delete函数

所以,你需要事先定义'entry_delete'函数

def entry_delete:
      pass

一切如Code 10所示,同时,我们给出课程案例Code 11以供参考,如果有不懂的,可以翻阅前面的代码说明,应该是比较清楚的

# Code 11
from tkinter import *

def calculate_plus():
    a = eval(entry1.get())  # 获取通过get方法得到输入框ent1中的值
    b = eval(entry2.get())  # 获取通过get方法得到输入框ent2中的值
    result = "{:.2f} + {:.2f} = {:.2f}\n".format(a, b, a + b)  # 生成计算式
    txt.insert(END, result)  # 将结果插入到文本框中
    entry1.delete(0, END)
    entry2.delete(0, END)

root = Tk()
root.title("加法器")
root.geometry('500x500')

label1 = Label(root, text="请输入两个数,按下面按钮进行加法计算")
label1.pack()

entry1 = Entry(root)
entry1.pack()

entry2 = Entry(root)
entry2.pack()

button1 = Button(root, text = "加法", command = calculate_plus)
button1.pack()

txt = Text(root)
txt.pack()

root.mainloop()
调用匿名函数lambda

这里涉及到函数章节的lambda函数(匿名函数),这里仅简单回顾

<函数名> = lambda <参数列表>: <表达式>

lambda函数与正常函数一样,等价于下面形式:

def <函数名>(<参数列表>):
        return <表达式>

例如 Code 12

基于lambda函数,我们可以传递参数了,这里同样给出课程案例Code 13

# Code 12

#匿名函数示例
calculate_plus = lambda a,b : a+b #定义匿名函数,有两个参数a与b,返回a+b
print(calculate_plus(1,3))

#普通函数示例
def calculate_plus_2(a,b):
    result = a+b
    return result
print(calculate_plus_2(2,4))
# Code 13
from tkinter import *

def calculate_plus(a,b):
    a = eval(a)
    b = eval(b)
    result = "{:.2f} + {:.2f} = {:.2f}\n".format(a, b, a + b)  # 生成计算式
    txt.insert(END, result)  # 将结果插入到文本框中
    entry1.delete(0, END)
    entry2.delete(0, END)

root = Tk()
root.title("加法器")
root.geometry('500x500')

label1 = Label(root, text="请输入两个数,按下面按钮进行加法计算")
label1.pack()

entry1 = Entry(root)
entry1.pack()

entry2 = Entry(root)
entry2.pack()

button1 = Button(root, text="加法", command=lambda: calculate_plus(entry1.get(),entry2.get()))
button1.pack()

txt = Text(root)
txt.pack()

root.mainloop()

接下来给出课程上的综合案例Code 14,可以尝试读懂,给出这段代码的初衷只是想让大家注意参数的global全局声明

思考:面对有参数需要传递的情形一定要使用匿名函数吗?不是这样的,可以在函数定义里使用.get()方法获取值,并之后再使用if elif等判断

# Code 14(本代码复制的课程代码未修改)
from tkinter import *

total = 0

def run1(operator):
    global total

    a = eval(ent1.get())
    start_line = "{} {} {} = ".format(total, operator, a)
    txt.insert(END,start_line)

    if operator == "+":
        total += a
    elif operator == "-":
        total -= a
    elif operator == "*":
        total *= a
    elif operator == "/":
        total /= a

    s = "{}\n".format(total)
    txt.insert(END,s)
    ent1.delete(0,END)

root = Tk()
root.title("计算器")
root.geometry("500x500")

label1 = Label(root, text = "请输入一个数,按下面按钮进行加减乘除计算")
label1.pack()

ent1 = Entry(root)
ent1.pack()

button1 = Button(root, text = "加法", command = lambda :run1("+"))
button1.pack()

button2 = Button(root, text = "减法", command = lambda :run1("-"))
button2.pack()

button3 = Button(root, text = "乘法", command = lambda :run1("*"))
button3.pack()

button4 = Button(root, text = "除法", command = lambda :run1("/"))
button4.pack()

txt = Text(root)
txt.pack()

root.mainloop()

单选框(Radiobutton)与复选框(Checkbutton)

其实,这两个选择框对我来说是比较难的,接下来我们一个一个慢慢看

单选按钮(Radiobutton)是为响应互相排斥的若干单选项的单击事件以触发运行自定义函数所设

单选框(Radiobutton)

部分特有属性:

text 显示文本

command 响应函数名

variable 实例变量(用于分组)

value 实例变量值(用于组内编号)

响应函数名“command=函数名”的用法与Button相同,函数名最后也不要加括号。

值为Tkinter里的类变量,StringVar/IntVar。如果选项被选中,变量值会自动跟新。

先定义/声明内部类型变量var = IntVar()var=StringVar(),然后用variable属性与这个变量联系/绑定起来,即variable=var,之后在所调用的函数中可用var.get()方法获取实例变量的value值

不懂不要紧,我们来看两个课堂案例:

# Code 15
from tkinter import *

def What_is_my_selection():
    choice_dict = {0:'甲',1:'乙',2:'丙'}
    s = "您选了{}项".format(choice_dict.get(what_I_chose.get())) #利用var.get()获取value值,带回字典做出判断
    label.configure(text = s)
  
root = Tk()

root.title("单选GUI")
root.geometry("200x200")

label = Label(root,text='请选择一项,这里会自动更新结果')
label.pack()

what_I_chose = IntVar()

# 定义单选框,在root框架下,显示文本为'甲',实例变量(分组)为what_I_chose,选中后返回值0,选中后触发What_is_my_selection函数
radiobutton1 = Radiobutton(root, text="甲", variable=what_I_chose, value=0, command = What_is_my_selection)
radiobutton1.pack()

radiobutton2 = Radiobutton(root, text="乙", variable=what_I_chose, value=1, command = What_is_my_selection)
radiobutton2.pack()

radiobutton3 = Radiobutton(root, text="丙", variable=what_I_chose, value=2, command = What_is_my_selection)
radiobutton3.pack()

root.mainloop()
# Code 16 多组单选框
from tkinter import *

def say_hello():
    string1 = string2 = ""

    if var_sex.get() == 1:
        string1 = '男'
    elif var_sex.get() == 2:
        string1 = '女'

    if var_grade.get() == 1:
        string2 = "大一"
    elif var_grade.get() == 2:
        string2 = "大二"
    elif var_grade.get() == 3:
        string2 = "大三"
    elif var_grade.get() == 4:
        string2 = "大四"
   
    string_output = "hello,来自{}的{}同学".format(string2,string1)
    label2.configure(text = string_output)

root = Tk()

root.title("多组单选GUI")
root.geometry("300x300")

label = Label(root, text = "请选择性别和年级")
label.pack()

var_sex = IntVar()
var_grade = IntVar()

# 定义单选框,在root框架下,显示文本为'男',实例变量(分组)为var_sex,选中后返回值var_sex=1
# 冷知识,你并不需要写那么多radiobutton,你可以简化为你知道的名字,如本代码所示
rdb1 = Radiobutton(root, text="男", variable=var_sex, value=1)
rdb1.pack()

rdb2 = Radiobutton(root, text="女", variable=var_sex, value=2)
rdb2.pack()

# 定义单选框,在root框架下,显示文本为'大一',实例变量(分组)为var_grade,选中后返回值var_grade=1
rdb3 = Radiobutton(root, text="大一", variable=var_grade, value=1)
rdb3.pack()

rdb4 = Radiobutton(root, text="大二", variable=var_grade, value=2)
rdb4.pack()

rdb5 = Radiobutton(root, text="大三", variable=var_grade, value=3)
rdb5.pack()

rdb6 = Radiobutton(root, text="大四", variable=var_grade, value=4)
rdb6.pack()

button1 = Button(root, text = "提交", command = say_hello)
button1.pack()

label2 = Label(root, text = "")
label2.pack()

root.mainloop()
复选框(Checkbutton)

复选按钮(Checkbutton)是为返回多个选项值的交互控件,通常并不直接触发函数的执行

部分特有属性:

text 显示文本

command 响应函数名

variable 实例变量(用于分组)

onvalue 被选中后的返回值

offvalue 未选中默认返回值

响应函数名“command=函数名”的用法与Radionutton相同,函数名最后也不要加括号。

值为Tkinter里的类变量,StringVar/IntVar。如果选项被选中,变量值会自动跟新。

先定义/声明内部类型变量var = IntVar()var=StringVar(),然后用variable属性与这个变量联系/绑定起来,即variable=var,之后在所调用的函数中可用var.get()方法获取实例变量的value值

不懂不要紧,我们继续来看两个课堂案例:

# Code 17
from tkinter import *

def run():

    if (var_football.get() == 0 and var_basketball.get() == 0 and var_swim.get() == 0 and var_track.get() == 0):
        string_output = "您没有选择任何爱好项目"

    else:
        s1 = s2 = s3 = s4 = ""
        if var_football.get() == 1:
            s1 = "足球"
        if var_basketball.get() == 1:
            s2 = "篮球"
        if var_swim.get() == 1:
            s3 = "游泳"
        if var_track.get() == 1:
            s4 = "田径"

        string_output = "您选择了{}{}{}{}".format(s1, s2, s3, s4)  #想让元素之间出现'和'或'、'吗'? 可以尝试列表+分割方法

    lb2.config(text = string_output)


root = Tk()

root.title("复选GUI")
root.geometry("400x200")

lb1 = Label(root, text = "请选择您的爱好项目:")
lb1.pack()

var_football = IntVar()
var_basketball = IntVar()
var_swim = IntVar()
var_track = IntVar()

# 定义复选框,在root框架下,显示文本为'足球',实例变量(分组)为var_football,选中后返回值onvalue=1,清除选中返回值0
ch1 = Checkbutton(root, text = "足球", variable = var_football, onvalue = 1, offvalue = 0)
ch2 = Checkbutton(root, text = "篮球", variable = var_basketball, onvalue = 1, offvalue = 0)
ch3 = Checkbutton(root, text = "游泳", variable = var_swim, onvalue = 1, offvalue = 0)
ch4 = Checkbutton(root, text = "田径", variable = var_track, onvalue = 1, offvalue = 0)

ch1.pack()
ch2.pack()
ch3.pack()
ch4.pack()

btn = Button(root, text = "Submit", command = run)
btn.pack()

lb2 = Label(root, text = '')
lb2.pack()

root.mainloop()

子窗体(Toplevel)

用Toplevel可新建一个显示在最前面的子窗体。其通式为:

<子体实例名>=Toplevel(根窗体)

子窗体与根窗体类似,也可设置title、geometry等属性,并在上面布局其他控件。

关闭窗体程序运行的方法通常用<实例名>.destroy(),而不建议用<实例名>.quit()

用Toplevel所创建的子窗体是'非模式(Modeless)'的窗体,虽然初建时子窗体在最前面,但根窗体上的控件实例也是可以被操作的。

而'模式(Modal)'对话框,就是所弹出的对话框必须应答,在关闭之前无法操作其后面的其他窗体

常见的模式对话框有消息对话框输入对话框、文件选择对话框、颜色选择对话框等(应试掌握前两个即可)

消息对话框

首先,引入messagebox包,可使用表8-8中所列的消息对话框函数。执行这些函数,可弹出模式消息对话框,并根据用户的响应返回一个布尔型值。其通式为:

消息对话框函数(<title=标题文本>, <message=消息文本>, [其他参数])

名称方法
确认取消对话框askokcancel()
是否对话框askquestion(), askyesno()
重试取消对话框askretrycancel()
是否和取消对话框askyesnocancel()
错误消息框showerror()
信息提示框showinfo()
警告框showwarning()

让我们来看2个引入示例,然后看1个课程案例:

# Code 18
from tkinter import *
from tkinter import messagebox

# 使用 from tkinter import messagebox
messagebox.showinfo("信息", "这是一个信息对话框")
# Code 19
from tkinter import *
import tkinter.messagebox

# 使用 import tkinter.messagebox
tkinter.messagebox.showinfo("信息", "这是一个信息对话框")
# Code 20
from tkinter import *
import tkinter.messagebox

def run():
    answer = tkinter.messagebox.askokcancel("请选择","请选择确定或取消")
    if answer == True:
        lb.configure(text = "已确认")
    else:
        lb.configure(text = "已取消")

root = Tk()
root.title("消息对话框")
root.geometry("200x200")

lb = Label(root, text = "")
lb.pack()

btn = Button(root, text = "弹出对话框", command = run)
btn.pack()

root.mainloop()

输入对话框

首先,引入simpledialog包,可弹出输入对话框,用以接收用户的简单输入,其实与消息对话框感觉类似

其通式为:

输入对话框(<title=标题文本>, <message=消息文本>)

输入对话框通常有askstring()askinteger()askfloat()三种函数,分别用于接收字符串、整数和浮点数类型的输入

让我们来看2个引入示例,然后看1个课程案例:

# Code 21
from tkinter import *
from tkinter import simpledialog

# 使用 from tkinter import messagebox
simpledialog.askstring("输入对话框", "我能接收文本")
# Code 22
from tkinter import *
from tkinter.simpledialog import *

# 使用 import tkinter.messagebox
tkinter.simpledialog.askstring("输入对话框", "我能接收文本")
# Code 23
from tkinter import *
from tkinter.simpledialog import *

root=Tk()
root.title('复读机')
root.geometry('300x50')

def fuduji():
    s = askstring("请输入","请输入一串文字")
    lb.configure(text = s)

lb = Label(root, text = "")
lb.pack()

btn = Button(root, text = "弹出输入对话框", command = fuduji)
btn.pack()

root.mainloop()

事件响应

用tkinter可将用户事件与自定义函数绑定,用键盘或鼠标的动作事件来响应触发自定义函数的执行。其通式为:

控件实例.bind(<事件代码>,<函数名>)

可以达到用鼠标左右键按同一个按钮却触发不同函数的效果

其中,事件代码通常以半角小于号“<”和大于号“>”界定,包括事件和按键等2~3个部分,它们之间用减号分隔,比如:

toplevel.bind('<Button-3>',myfunc)

但我们作业没用过这个,窝也没捣鼓过这玩意儿,所以这里简单给出怎么用,以及几个课程案例:

将控件实例绑定到键盘事件和部分光标位置不落在具体控件实例上的鼠标事件时,还需要设置该实例执行focus_set()方法获得焦点,才能对事件持续响应。例如toplevel. focus_set()

所调用的自定义函数若需要利用鼠标或键盘的响应值,可将event作为参数,通过event的属性获取

常用的事件有:
, 单击鼠标左键
, 单击鼠标中键
, 单击鼠标右键

# Code 24
from tkinter import *

def show(event):
    s = event.keysym
    lb.configure(text = s)

root = Tk()
root.title("按键实验")
root.geometry("200x200")

lb = Label(root, text = "请按键", font=('黑体',48))
lb.bind("<Key>",show)
lb.focus_set()
lb.pack()

root.mainloop()
# Code 25
from tkinter import *

def show1(event):
    lb.configure(text = "哦,你点的是左键")

def show3(event):
    lb.configure(text = "哦,你点的是右键")

root = Tk()
root.title("按键实验1")
root.geometry("200x200")

lb = Label(root, text = "")
lb.pack()

btn = Button(root, text = "按钮")
btn.bind("<ButtonPress-1>",show1)
btn.bind("<ButtonPress-3>",show3)
btn.focus_set()
btn.pack()

root.mainloop()
# Code 26
from tkinter import *

def show(event):
    s ='光标位于x=%s,y=%s'%(str(event.x),str(event.y))
    lb.configure(text = s)
root = Tk()
root.title("鼠标实验")
root.geometry("200x200")
lb = Label(root, text = "请单击窗体")
lb.pack()
root.bind("<Button-1>",show)
root.focus_set()

root.mainloop()

作业参考

最后,给出个人在这几次作业中的参考代码,方便大家交流学习,肯定不是最优化代码,可以一起探讨,互相进步:
劳斯们写的答案也在后面附上(未校对,仅识别),以供参考

# Code 27
# Homework 1
'''
【作业要求】用户登录界面设计
具体要求:实现用户登录功能。输入用户名和密码,点击登录按钮,在标签中输出登录结果。正确用户名为:aaa,密码为aaa
'''

from tkinter import *
root = Tk()
root.title ('用户登录界面')

def login():
    username = lb_user_entry.get()
    password = lb_pwd_entry.get()
    if username == 'aaa':
        if password == 'aaa':
            lb_user_tip.config(text = '登录成功')
        else:
            lb_user_tip.config(text = '密码不正确!')
    else:
        lb_user_tip.config(text = '用户名不存在!')
        
lb_user_tip = Label(root,text='用户名:')
lb_user_tip.grid(column=0,row=0)

lb_user_entry = Entry(root)
lb_user_entry.grid(column=1,columnspan=2,row=0)

lb_pwd_tip = Label(root,text='密码:')
lb_pwd_tip.grid(column=0,row=1)

lb_pwd_entry = Entry(root)
lb_pwd_entry.grid(column=1,columnspan=2,row=1)

bt_login = Button(root, text='登录',command=login)
bt_login.grid(column=1,row=2)

lb_user_tip = Label(root,text='')
lb_user_tip.grid(column=1,row=3)

root.mainloop()
# Code 28
# Homework 1 参考答案
'''
【重点】
标签、输入框、按钮控件的使用
Grid布局方式
标签文本的改变
'''

from tkinter import *

root = Tk()
root.title("用户登录界面设计")

def run():
    user = ent1.get()
    password = ent2.get()

    if user != 'aaa': 
        lb3.configure(text="用户名不存在")
    else:
        if password != 'aaa':
            lb3.configure(text="密码不正确")
        else:
            lb3.configure(text="登录成功")

lb1 = Label(root, text="用户名:")
lb1.grid(row=0, column=0)

ent1 = Entry(root)
ent1.grid(row=0, column=1)

lb2 = Label(root, text="密码:")
lb2.grid(row=1, column=0)

ent2 = Entry(root)
ent2.grid(row=1, column=1)

btn1 = Button(root, text="登录", command=run)
btn1.grid(row=2, column=1)

lb3 = Label(root, text="")
lb3.grid(row=3, column=1)

root.mainloop()
# Code 29
# Homework 2
'''
【作业要求】新水果统计GUI
仿照第9次作业水果统计B,实现在输入框中输入一种水果,输入参数为一种水果的名字onefruit 
•可选值为: '香蕉','草莓','苹果','梨子','西瓜','芒果','葡萄' 
•在文本框中输出该水果出现的次数
'''

from tkinter import *
from random import choice

root = Tk()
root.title('水果统计')
root.geometry('500x500')

def random_fruit():
    from random import choice
    Fruit_Types=['香蕉','草莓','苹果','梨子','西瓜','芒果','葡萄']
    Fruit_Dic={}
    for count in range(100):
        Kind = choice(Fruit_Types)
        Fruit_Dic[Kind] = Fruit_Dic.get(Kind,0) + 1
    result_fruit = ent_fruit_name.get()
    result_count = Fruit_Dic.get(result_fruit,0)
    result_str = ('随机100次,有{}个{}\n'.format(result_count,result_fruit))
    txt.insert(END,result_str)
    ent_fruit_name.delete(0,END)
    
lb_tips = Label(root,text='''请在输入框中输入任意水果名\n
只有香蕉,草莓,苹果,梨子,西瓜,芒果,葡萄\n
其它的卖完了┗|`O′|┛ 嗷~~''')

ent_fruit_name = Entry(root)
butt_submit = Button(root,text='提交',command = random_fruit)
txt = Text(root)

lb_tips.pack()
ent_fruit_name.pack()
butt_submit.pack()
txt.pack()

root.mainloop()
# Code 30
# Homework 2 参考答案
'''
【重点】
标签、输入框、按钮、文本框的使用
Pack布局方式
文本框的内容插入
'''

from random import choice
from tkinter import *

def countOneFruit():
    onefruit = ent1.get()
    fruit_list = ['香蕉', '草莓', '苹果', '梨子', '西瓜', '芒果', '葡萄']
    fruit_dict = {}
    N = 100

    for i in range(N):
        fruit = choice(fruit_list)
        fruit_dict[fruit] = fruit_dict.get(fruit, 0) + 1

    oneFruitCount = fruit_dict.get(onefruit, 0)
    s = "随机100次,共得到{}个{}\n".format(oneFruitCount, onefruit)
    txt1.insert(END, s)
    ent1.delete(0, END)

root = Tk()
root.title("水果统计")

lb1 = Label(root, text="请在输入框中输入任意水果名:")
lb1.pack()

ent1 = Entry(root)
ent1.pack()

btn1 = Button(root, text='提交', command=countOneFruit)
btn1.pack()

txt1 = Text(root)
txt1.pack()

root.mainloop()
# Code 29
# Homework 3
'''
【作业要求】收银台A
要求在PPT中已给出
'''

from tkinter import *

root = Tk()
root.title('(会员制餐厅V1)自助点餐')
root.geometry('300x300')

def check():
    global Need_Paid
    Menu = {'汉堡包':'12','蛋挞':'7','猪肉卷':'10','饮料':'5'}
    ordered = []
    Need_Paid = 0
    if Var1.get() == 1:
        ordered.append('汉堡包')
    if Var2.get() == 1:
        ordered.append('蛋挞')
    if Var3.get() == 1:
        ordered.append('猪肉卷')
    if Var4.get() == 1:
        ordered.append('饮料')
            
    food_str = '和'.join(ordered)
    for food in ordered:
        Need_Paid += int(Menu.get(food))
    
    tip2_text='你点了{},一共{}元'.format(food_str,Need_Paid)
    txt_tip2.configure(text=tip2_text)
    
def payoff():
    income = ent_dollar.get()
    money = int(income) - Need_Paid
    tip3_text='收您{}元,找您{}元'.format(income,money)
    txt_tip3.configure(text=tip3_text)

Var1 = IntVar()
Var2 = IntVar()
Var3 = IntVar()
Var4 = IntVar()

txt_tip1 = Label(root,text='您好,请问需要点神马?')

box1 = Checkbutton(root,text='汉堡包:12 CNY',variable=Var1,onvalue=1,offvalue=0)
box2 = Checkbutton(root,text='蛋挞:7 CNY',variable=Var2,onvalue=1,offvalue=0)
box3 = Checkbutton(root,text='猪肉卷:10 CNY',variable=Var3,onvalue=1,offvalue=0)
box4 = Checkbutton(root,text='饮料:5 CNY',variable=Var4,onvalue=1,offvalue=0)
butt_checkin = Button(root,text='OK!',command = check)

txt_tip2 = Label(root,text='')
ent_dollar = Entry(root)
butt_payoff = Button(root,text='付款',command = payoff)
txt_tip3 = Label(root,text='')

txt_tip1.pack()
box1.pack()
box2.pack()
box3.pack()
box4.pack()
butt_checkin.pack()
txt_tip2.pack()
ent_dollar.pack()
butt_payoff.pack()
txt_tip3.pack()

root.mainloop()
# Code 31
# Homework 3 参考答案
'''
【重点】
如何调用所学知识进行编程
'''

from tkinter import *

root = Tk()
root.title("自助点餐")
root.geometry("400x400")

lb1 = Label(root, text="您好,请问需要什么?")
lb1.pack()

checkvar1 = IntVar()
checkvar2 = IntVar()
checkvar3 = IntVar()
checkvar4 = IntVar()

cb1 = Checkbutton(root, text="汉堡包: 12元", variable=checkvar1, onvalue=1, offvalue=0)
cb1.pack()

cb2 = Checkbutton(root, text="蛋挞: 7元", variable=checkvar2, onvalue=1, offvalue=0)
cb2.pack()

cb3 = Checkbutton(root, text="猪肉卷: 10元", variable=checkvar3, onvalue=1, offvalue=0)
cb3.pack()

cb4 = Checkbutton(root, text="饮料: 5元", variable=checkvar4, onvalue=1, offvalue=0)
cb4.pack()

def run1(event):
    s1 = s2 = s3 = s4 = ""
    money = 0
    if checkvar1.get() == 1:
        money += 12
        s1 = "汉堡包"
    if checkvar2.get() == 1:
        money += 7
        s2 = "蛋挞"
    if checkvar3.get() == 1:
        money += 10
        s3 = "猪肉卷"
    if checkvar4.get() == 1:
        money += 5
        s4 = "饮料"
    if money == 0:
        s = "您什么都没点,不用付钱"
    else:
        s = "您点了{}{}{}{}共{}元".format(s1, s2, s3, s4, money)
    lb1.configure(text=s)

btn1 = Button(root, text="OK")
btn1.bind("<1>", run1)
btn1.pack()

lb1 = Label(root, text="")
lb1.pack()

ent1 = Entry(root)
ent1.pack()

def run3(event):
    s1 = s2 = s3 = s4 = ""
    money = 0
    if checkvar1.get() == 1:
        money += 12
        s1 = "汉堡包"
    if checkvar2.get() == 1:
        money += 7
        s2 = "蛋挞"
    if checkvar3.get() == 1:
        money += 10
        s3 = "猪肉卷"
    if checkvar4.get() == 1:
        money += 5
        s4 = "饮料"
    pay = eval(ent1.get())
    if money == 0:
        s = "您什么都没点,不用付钱"
    else:
        if pay >= money:
            s = "收您{}元,找零{}元".format(pay, pay - money)
        else:
            s = "收您{}元,请再付{}元".format(pay, money - pay)
    lb2.configure(text=s)

btn2 = Button(root, text="付款")
btn2.bind("<1>", run3)
btn2.pack()

lb2 = Label(root, text="")
lb2.pack()

root.mainloop()
# Code 32
# Homework 4
'''
【作业要求】收银台B
右键点击“OK”按钮,弹出会员付款界面,输入会员码(会员码为:abcdefg)
如果会员码正确,最后金额打8折
如果会员码不正确,原价输出
'''

from tkinter import *
from tkinter.simpledialog import *

root = Tk()
root.title('(会员制餐厅V2)自助点餐')
root.geometry('300x300')

def VIP(event):
    check(None)
    code = askstring('沃趣!VIP付款界面','请输入会员核验码:')
    if code == 'abcdefg':
        Need_Paid_discounted = Need_Paid * 0.8
        tip2_text='你点了{},一共{:.2f}元,折扣价为{:.2f}元'.format(food_str,Need_Paid,Need_Paid_discounted)
        txt_tip2.configure(text=tip2_text)

def check(event):
    global Need_Paid
    global food_str
    Menu = {'汉堡包':'12','蛋挞':'7','猪肉卷':'10','饮料':'5'}
    ordered = []
    Need_Paid = 0
    if Var1.get() == 1:
        ordered.append('汉堡包')
    if Var2.get() == 1:
        ordered.append('蛋挞')
    if Var3.get() == 1:
        ordered.append('猪肉卷')
    if Var4.get() == 1:
        ordered.append('饮料')
            
    food_str = '和'.join(ordered)
    for food in ordered:
        Need_Paid += int(Menu.get(food))
    tip2_text='你点了{},一共{:.2f}元'.format(food_str,Need_Paid)
    txt_tip2.configure(text=tip2_text)
    
def payoff():
    income = ent_dollar.get()
    money = int(income) - Need_Paid
    tip3_text='收您{}元,找您{}元'.format(income,money)
    txt_tip3.configure(text=tip3_text)

Var1 = IntVar()
Var2 = IntVar()
Var3 = IntVar()
Var4 = IntVar()

txt_tip1 = Label(root,text='您好,请问需要点神马?')

box1 = Checkbutton(root,text='汉堡包:12 CNY',variable=Var1,onvalue=1,offvalue=0)
box2 = Checkbutton(root,text='蛋挞:7 CNY',variable=Var2,onvalue=1,offvalue=0)
box3 = Checkbutton(root,text='猪肉卷:10 CNY',variable=Var3,onvalue=1,offvalue=0)
box4 = Checkbutton(root,text='饮料:5 CNY',variable=Var4,onvalue=1,offvalue=0)

butt_checkin = Button(root,text='OK!')
butt_checkin.bind("<ButtonPress-1>",check)
butt_checkin.bind("<ButtonPress-3>",VIP)

txt_tip2 = Label(root,text='')
ent_dollar = Entry(root)
butt_payoff = Button(root,text='付款',command = payoff)
txt_tip3 = Label(root,text='')

txt_tip1.pack()
box1.pack()
box2.pack()
box3.pack()
box4.pack()
butt_checkin.pack()
txt_tip2.pack()
ent_dollar.pack()
butt_payoff.pack()
txt_tip3.pack()

root.mainloop()
# Code 33
# Homework 4 参考答案
'''
【重点】
如何调用所学知识进行编程
'''

from tkinter import *
from tkinter.simpledialog import askstring

root = Tk()
root.title("自助点餐")
root.geometry("400x400")

lb1 = Label(root, text="您好,请问需要什么?")
lb1.pack()

checkvar1 = IntVar()
checkvar2 = IntVar()
checkvar3 = IntVar()
checkvar4 = IntVar()

cb1 = Checkbutton(root, text="汉堡包: 12元", variable=checkvar1, onvalue=1, offvalue=0)
cb1.pack()

cb2 = Checkbutton(root, text="蛋挞: 7元", variable=checkvar2, onvalue=1, offvalue=0)
cb2.pack()

cb3 = Checkbutton(root, text="猪肉卷: 10元", variable=checkvar3, onvalue=1, offvalue=0)
cb3.pack()

cb4 = Checkbutton(root, text="饮料: 5元", variable=checkvar4, onvalue=1, offvalue=0)
cb4.pack()

def run1(event):
    s1 = s2 = s3 = s4 = ""
    money = 0
    if checkvar1.get() == 1:
        money += 12
        s1 = "汉堡包"
    if checkvar2.get() == 1:
        money += 7
        s2 = "蛋挞"
    if checkvar3.get() == 1:
        money += 10
        s3 = "猪肉卷"
    if checkvar4.get() == 1:
        money += 5
        s4 = "饮料"
    if money == 0:
        s = "您什么都没点,不用付钱"
    else:
        s = "您点了{}{}{}共{}元".format(s1, s2, s3, s4, money)
    lb1.configure(text=s)

def run2(event):
    s1 = s2 = s3 = s4 = ""
    money = 0
    if checkvar1.get() == 1:
        money += 12
        s1 = "汉堡包"
    if checkvar2.get() == 1:
        money += 7
        s2 = "蛋挞"
    if checkvar3.get() == 1:
        money += 10
        s3 = "猪肉卷"
    if checkvar4.get() == 1:
        money += 5
        s4 = "饮料"
    youhuima = askstring("会员付款界面", "请输入会员码")
    if youhuima == "abcdefg":
        discount = round(money * 0.8, 1)
        s = "您点了{}{}{}{}共{}元,折扣价为{}元".format(s1, s2, s3, s4, money, discount)
    else:
        s = "您点了{}{}{}{}共{}元".format(s1, s2, s3, s4, money)
    lb1.configure(text=s)

def run3(event):
    s1 = s2 = s3 = s4 = ""
    money = 0
    if checkvar1.get() == 1:
        money += 12
        s1 = "汉堡包"
    if checkvar2.get() == 1:
        money += 7
        s2 = "蛋挞"
    if checkvar3.get() == 1:
        money += 10
        s3 = "猪肉卷"
    if checkvar4.get() == 1:
        money += 5
        s4 = "饮料"
    pay = eval(ent1.get())
    if money == 0:
        s = "您什么都没点,不用付钱"
    else:
        if pay >= money:
            s = "收您{}元,找零{}元".format(pay, pay - money)
        else:
            s = "收您{}元,请再付{}元".format(pay, money - pay)
    lb2.configure(text=s)

btn1 = Button(root, text="OK")
btn1.bind("<1>", run1)
btn1.bind("<3>", run2)  # 绑定"单击鼠标右键"
btn1.pack()

lb1 = Label(root, text="")
lb1.pack()

ent1 = Entry(root)
ent1.pack()

btn2 = Button(root, text="付款")
btn2.bind("<1>", run3)
btn2.pack()

lb2 = Label(root, text="")
lb2.pack()

root.mainloop()
最后修改:2025 年 02 月 07 日
如果觉得我的文章对你有用,请随意赞赏