• Python Chapter 9: 使用Tkinter进行GUI程序设计 Part 4


    10. 弹出菜单

     1 # Program 9.14
     2 from tkinter import *
     3 
     4 class PopupMenuDemo:
     5     def __init__(self):
     6         window = Tk()
     7         window.title("Popup Menu Demo")
     8 
     9         self.menu = Menu(window, tearoff = 0)
    10         self.menu.add_command(label = "Draw a line", command = self.displayLine)
    11         self.menu.add_command(label = "Draw an oval", command = self.displayOval)
    12         self.menu.add_command(label = "Draw a rectangle", command = self.displayRect)
    13         self.menu.add_command(label = "Clear", command = self.clearCanvas)
    14 
    15         self.canvas = Canvas(window, width = 200, height = 100, bg = "white")
    16         self.canvas.pack()
    17 
    18         self.canvas.bind("<Button-3>", self.popup)
    19 
    20         window.mainloop()
    21 
    22     def displayRect(self):
    23         self.canvas.create_rectangle(10, 10, 190, 90, tags = "rect")
    24 
    25     def displayOval(self):
    26         self.canvas.create_oval(10, 10, 190, 90, tags = "oval")
    27 
    28     def displayLine(self):
    29         self.canvas.create_line(10, 10, 190, 90, tags = "line")
    30         self.canvas.create_line(10, 90, 190, 10, tags = "line")
    31 
    32     def clearCanvas(self):
    33         self.canvas.delete("rect", "oval", "line")
    34 
    35     def popup(self, event):
    36         self.menu.post(event.x_root, event.y_root)
    37 
    38 PopupMenuDemo()

    9-13) 用self.menu存储Menu类对象是因为后续方法中会需要访问此menu,故将其放在类的数据域中

       self.menu.add_command(label, command)给一个菜单栏添加具体命令

    18) self.canvas.bind(string, command)将对象self.canvas与命令command绑定起来,调用此回调函数的条件由string描述,此处"<Button-3>"代表当在Canvas内点击鼠标右键时(更多的string选项在后续的章节中进行介绍)

    36) 当在self.canvas中点击鼠标右键会调用popup()函数,其中self.menu.post(x, y)将菜单menu显示在坐标为(x, y)的地方,此处event代表事件对象(此处即为点击鼠标右键),event.x_root与event.y_root分别代表此事件发生的x坐标与y坐标(此处即为在画布中点击右键处的x,y坐标)。menu.post(x, y)是设计弹出菜单的关键

    11. 鼠标、按键事件和绑定

    前面例子使用小构件的bind方法将事件与回调处理器绑定:

    widget.bind(event, handler)

    其中event所代表的的事件应用引号括起来表示成字符串,具体事件有以下选项:

    事件 描述
    <Bi-Motion> 当鼠标左键按住小构件且移动鼠标时事件发生
    <Button-i> Button-1、Button-2、Button-3分别表明左键、中键和右键,单击时触发事件,且Tkinter会自动抓取鼠标指针的位置
    <ButtonReleased-i>

    当释放鼠标左中右键时触发事件

    <Double-Button-i> 当双击鼠标左中右键时触发事件
    <Enter> 当鼠标光标进入小构件时触发事件
    <Key> 当单机一个键时触发事件
    <Leave> 当鼠标光标离开小构件时事件发生
    <Return> 当单机“Enter”键时事件发生,此处亦可将Return替换为键盘上的任意键("A"、"B"、"Down“、“Right”等)
    <Shift+A> 当单机"Shift+A"键时事件发生,可以将Alt、Shift、Control和其他键任意组合
    <Triple-Button-i> 当三次单机鼠标左中右键时事件发生

    与此同时,每个事件也对应了诸多属性,采用event.properties调用这些属性值:

    事件属性 描述
    char 对<Key>事件有效,得到从键盘输入的字符
    keycode 对<Key>事件有效,得到从键盘输入字符的统一码(有时是ASCII码)
    keysym 对<Key>事件有效,得到从键盘输入字符的符号(其实就是字符)
    num num=1/2/3表示按下的是鼠标哪个键
    widget 触发这个事件的小构件对象
    x、y 当前鼠标在小构件中以像素为单位的位置
    x_root、y_root 当前鼠标相对于屏幕左上角的以像素为单位的位置

    下面是一个使用小构件绑定事件及事件属性的例子:

     1 # Program 9.15
     2 from tkinter import *
     3 
     4 class MouseKeyEventDemo:
     5     def __init__(self):
     6         window = Tk()
     7         window.title("Event Demo")
     8         canvas = Canvas(window, bg = "white", width = 200, height = 100)
     9         canvas.pack()
    10 
    11         canvas.bind("<Button-1>", self.processMouseEvent)
    12 
    13         canvas.bind("<Key>", self.processKeyEvent)
    14         canvas.focus_set()
    15 
    16         window.mainloop()
    17 
    18     def processMouseEvent(self, event):
    19         print("clicked at ", event.x, event.y)
    20         print("Position in the screen", event.x_root, event.y_root)
    21         print("Which button is clicked? ", event.num)
    22 
    23     def processKeyEvent(self, event):
    24         print("keysym? ", event.keysym)
    25         print("char? ", event.char)
    26         print("keycode? ", event.keycode)
    27 
    28 MouseKeyEventDemo()

    11)将canvas绑定<Button-1>即左键点击事件并调用processMouseEvent方法

    13)将canvas绑定<Key>即键盘输入事件并调用processKeyEvent方法

    14)canvas.focus_set()在画布上设置焦点从而从键盘上获取输入(其实我心里是???焦点跟这有啥关系)

    19-21、24-26) 调用了event事件的x/y/x_root/y_root/num/keysym/char/keycode等一系列属性

     1 # Program 9.16
     2 from tkinter import *
     3 
     4 class EnlargeShrinkCircle:
     5     def __init__(self):
     6         self.radius = 50
     7 
     8         window = Tk()
     9         window.title("Control Circle Demo")
    10         self.canvas = Canvas(window, bg = "white", width = 200, height = 200)
    11         self.canvas.pack()
    12         self.canvas.create_oval(100 - self.radius, 100 - self.radius, 100 + self.radius, 100 + self.radius, tags = "oval")
    13 
    14         self.canvas.bind("<Button-1>", self.increaseCircle)
    15         self.canvas.bind("<Button-3>", self.decreaseCircle)
    16 
    17         window.mainloop()
    18 
    19     def increaseCircle(self, event):
    20         self.canvas.delete("oval")
    21         if self.radius < 100:
    22             self.radius += 2
    23         self.canvas.create_oval(100 - self.radius, 100 - self.radius, 100 + self.radius, 100 + self.radius, tags = "oval")
    24 
    25     def decreaseCircle(self, event):
    26         self.canvas.delete("oval")
    27         if self.radius > 2:
    28             self.radius -= 2
    29         self.canvas.create_oval(100 - self.radius, 100 - self.radius, 100 + self.radius, 100 + self.radius, tags = "oval")
    30 
    31 EnlargeShrinkCircle()

    14-15) 添加点击鼠标左键、右键事件至self.canvas,并分别与increaseCircle和decreaseCircle方法绑定

    19-29) 在increaseCircle与decreaseCircle中,先调用canvas对象的delete方法清除原先的圆,再更改self.radius更新半径,最后重新调用canvas对象create_oval方法绘制新的圆

    12. 动画

     1 # Program 9.17
     2 from tkinter import *
     3 
     4 class AnimationDemo:
     5     def __init__(self):
     6         window = Tk()
     7         window.title("Animation Demo")
     8 
     9         width = 250
    10         canvas = Canvas(window, bg = "white", width = 250, height = 50)
    11         canvas.pack()
    12 
    13         x = 0
    14         canvas.create_text(x, 30, text = "Message moving?", tags = "text")
    15 
    16         dx = 3
    17         while True:
    18             canvas.move("text", dx, 0)
    19             canvas.after(100)
    20             canvas.update()
    21             if x < 
    22                 x += dx
    23             else:
    24                 x = 0
    25                 canvas.delete("text")
    26                 canvas.create_text(x, 30, text = "Message moving?", tags = "text")
    27 
    28         window.mainloop()
    29 
    30 AnimationDemo()

    14) 调用canvas对象的create_text方法,create_text(x, y, text, tags)其中x, y为创建消息的坐标,text为消息内容,tags为其标签

    18) 调用canvas对象的move方法,move(tags, dx, dy)其中tags为待移动的标签,dx为横向的坐标移动值(右正左负),dy为纵向的坐标移动值(下正上负)

    19-20) canvas.after(100)使程序暂停100ms,canvas.update()重新显示画布

    21-26) 通过变量x监测消息的当前位置,若超过width则将原消息删掉,在初始位置新建消息并更新变量x=0

     1 # Program 9.18
     2 from tkinter import *
     3 
     4 class ControlAnimation:
     5     def __init__(self):
     6         window = Tk()
     7         window.title("Control Animation Demo")
     8 
     9         self.width = 250
    10         self.canvas = Canvas(window, bg = "white", width = self.width, height = 50)
    11         self.canvas.pack()
    12 
    13         frame = Frame(window)
    14         frame.pack()
    15         btStop = Button(frame, text = "Stop", command = self.stop)
    16         btStop.pack(side = LEFT)
    17         btResume = Button(frame, text = "Resume", command = self.resume)
    18         btResume.pack(side = LEFT)
    19         btFaster = Button(frame, text = "Faster", command = self.faster)
    20         btFaster.pack(side = LEFT)
    21         btSlower = Button(frame, text = "Slower", command = self.slower)
    22         btSlower.pack(side = LEFT)
    23 
    24         self.x = 0
    25         self.sleepTime = 100
    26         self.canvas.create_text(self.x, 30, text = "Message moving?", tags = "text")
    27 
    28         self.dx = 3
    29         self.isStopped = False
    30         self.animate()
    31 
    32         window.mainloop()
    33 
    34     def stop(self):
    35         self.isStopped = True
    36 
    37     def resume(self):
    38         self.isStopped = False
    39         self.animate()
    40 
    41     def faster(self):
    42         if self.sleepTime > 5:
    43             self.sleepTime -= 20
    44 
    45     def slower(self):
    46         self.sleepTime += 20
    47 
    48     def animate(self):
    49         while not self.isStopped:
    50             self.canvas.move("text", self.dx, 0)
    51             self.canvas.after(self.sleepTime)
    52             self.canvas.update()
    53             if self.x < self.
    54                 self.x += self.dx
    55             else:
    56                 self.x = 0
    57                 self.canvas.delete("text")
    58                 self.canvas.create_text(self.x, 30, text = "Message moving?", tags = "text")
    59 
    60 ControlAnimation()

    25) 将移动的间隔时间声明为self.sleepTime,方便后续方法中访问这个值

    15-22) 新建四个按钮,分别绑定四个方法,从而实现消息移动的停止、继续、加速、减速功能

    29) self.isStopped 参数决定图像是否继续移动,这一点在animate()方法中的while not self.isStopped中凸显出来

    48-58)self.animate()是整个程序的核心,负责消息的移动

    13. 滚动条

     1 # Program 9.19
     2 from tkinter import *
     3 
     4 class ScrollText:
     5     def __init__(self):
     6         window = Tk()
     7         window.title("Scroll Text Demo")
     8 
     9         frame1 = Frame(window)
    10         frame1.pack()
    11         scrollbar = Scrollbar(frame1)
    12         scrollbar.pack(side = LEFT, fill = Y)
    13         text = Text(frame1, width = 40, height = 10, wrap = WORD, yscrollcommand = scrollbar.set)
    14         text.pack()
    15         scrollbar.config(command = text.yview)
    16 
    17         window.mainloop()
    18 
    19 ScrollText()

    11) 创建一个Scrollbar对象,其父容器为frame1

    12) 将scrollbar放在文本的左端

    13) 新建一个文本对象Text(frame, width, height, wrap, yscrollcommand),其中yscrollcommand填Scrollbar对象.set,即可将此文本与滚动条对象绑定

    15) scrollbar.config(command),其中command为text.yview,将文本对象与滚动条绑定为纵向滑动

    其运行结果如下图:

    14. 标准对话框

     1 # Program 9.20
     2 import tkinter.messagebox
     3 import tkinter.simpledialog
     4 import tkinter.colorchooser
     5 
     6 tkinter.messagebox.showinfo("showinfo", "This is an info msg")
     7 
     8 tkinter.messagebox.showwarning("showwarning", "This is a warning")
     9 
    10 tkinter.messagebox.showerror("showerror", "This is an error")
    11 
    12 isYes = tkinter.messagebox.askyesno("askyesno", "Continue?")
    13 print(isYes)
    14 
    15 isOK = tkinter.messagebox.askokcancel("askokcancel", "OK?")
    16 print(isOK)
    17 
    18 isYesNoCancel = tkinter.messagebox.askyesnocancel("askyesnocancel", "Yes, No, Cancel?")
    19 print(isYesNoCancel)
    20 
    21 name = tkinter.simpledialog.askstring("askstring", "Enter your name")
    22 print(name)
    23 
    24 age = tkinter.simpledialog.askinteger("askinteger", "Enter your age")
    25 print(age)
    26 
    27 weight = tkinter.simpledialog.askfloat("askfloat", "Enter your weight")
    28 print(weight)

    2-4) 弹窗的一些模块,使用时需要import

    6-10) tkinter.messagebox.show(info/warning/error)(str1, str2) 创建信息/警告/错误弹窗,其中str1为该弹窗标题,str2为该弹窗的内容,三种不同的弹窗还会配上系统为信息/警告/错误预置的图标

    12-18) tkinter.messagebox.ask(yesno/okcancel/yesnocalcel) (str1, str2)创建三种类型的弹窗,且皆有返回值。当三个例子中点击(yes/ok/yes)时返回值为True,当三个例子中点击(no/cancel/no)时返回值为False,当在第三个例子中点击cancel时返回值为None(python中类似null的东西)

    21-28) tkinter.simpledialog.ask(string/integer/float) 创建三种类型弹窗,其中包含一输入框分别向用户请求一个字符串/整数/浮点数,返回值即为用户输入的内容,若用户点击了Cancel则返回值为None

    所有对话框都是模态窗口,意味着对话框消失程序将不再继续(??不懂)

    第9章 使用Tkinter进行GUI程序设计 到此结束

  • 相关阅读:
    中国身份证号码验证
    防止盗链下载问题
    Microsoft .NET Pet Shop 4 架构与技术分析
    常用操作封装类
    ASP.NET 2.0页面框架的几处变化
    普通字符串与HTML相互转换的小经验
    HttpWebRequest实现读取天气预报信息
    事务回滚 c# .net代码
    CAJViewer,AdobeReader等阅读器实现金山词霸屏幕取词功能
    01背包问题动态规划详解
  • 原文地址:https://www.cnblogs.com/fsbblogs/p/9695880.html
Copyright © 2020-2023  润新知