• Python Gui之tkinter(下)


     

    6.Radiobutton单按按钮

    Radiobutton控件用于选择同一组单选按钮中的一个。Radiobutton可以显示文本,也可以显示图像。

     

    7.Checkbutton复选按钮

    Checkbutton控件用于选择多个按钮的情况。Checkbutton可以显示文本,也可以显示图像。

    1. '''经典的Gui类的写法,使用面向对象的方法'''
    2. from tkinter import *
    3. from tkinter import messagebox
    4. class Application(Frame):
    5. '''一个经典的Gui的类的写法'''
    6. def __init__(self,master=None):
    7. super().__init__(master) #super()代表的是父类的定义,而不是父类对象
    8. self.master = master
    9. self.pack()
    10. self.createWideget()
    11. def createWideget(self):
    12. '''创建组件'''
    13. self.codeHobby = IntVar();
    14. self.videoHobby = IntVar()
    15. print(self.codeHobby.get()) #默认值是0
    16. self.r1 = Checkbutton(root, text="敲代码", onvalue=1, variable=self.codeHobby, offvalue=0)
    17. self.r2 = Checkbutton(root, text="看视频", onvalue=1, variable=self.videoHobby, offvalue=0)
    18. self.r1.pack(side="left");self.r2.pack(side="left")
    19. Button(root, text="确定",command=self.confirm).pack(side="left")
    20. def confirm(self):
    21. # messagebox.showinfo("测试","选择性别:"+self.v.get())
    22. if self.videoHobby.get()==1:
    23. messagebox.showinfo("测试", "看视频,都是正常人有的爱好!你喜欢看什么类型?")
    24. if self.codeHobby.get() == 1:
    25. messagebox.showinfo("测试","抓到野生程序员一只")
    26. if self.videoHobby.get()==1 and self.codeHobby.get() == 1:
    27. messagebox.showinfo("测试","你真卷啊这都要卷")
    28. if __name__ == '__main__':
    29. root = Tk()
    30. root.geometry("500x400+200+300")
    31. root.title("测试Radiobutton组件")
    32. app = Application(master=root)
    33. root.mainloop()

    5.canvas画布

    canvas(画布)是一个矩形区域,可以放置图形、图像、组件等。本节我们简单介绍canvas的使用,更加详细和深入的内容将在后面的“图形绘制”章节讲解。

    1. '''经典的Gui类的写法,使用面向对象的方法'''
    2. import random
    3. from tkinter import *
    4. from tkinter import messagebox
    5. class Application(Frame):
    6. '''一个经典的Gui的类的写法'''
    7. def __init__(self,master=None):
    8. super().__init__(master) #super()代表的是父类的定义,而不是父类对象
    9. self.master = master
    10. self.pack()
    11. self.createWideget()
    12. def createWideget(self):
    13. '''创建组件'''
    14. self.canvas = Canvas(self,width=300, height=200, bg="green")
    15. self.canvas.pack()
    16. #画一条直线
    17. line = self.canvas.create_line(10,10,30,20,40,50)
    18. #画一个矩形
    19. rect = self.canvas.create_rectangle(50,50,100,100)
    20. #画一个托全,坐标两双。为椭圆的边界矩形左上角和底部右下角
    21. oval = self.canvas.create_oval(50,50,100,100)
    22. global photo
    23. photo = PhotoImage(file="img/2.gif")
    24. self.canvas.create_image(150,170,image=photo)
    25. Button(self, text="画10个矩形", command=self.draw50Recg).pack(side="left")
    26. def draw50Recg(self):
    27. for i in range(0,10):
    28. x1 = random.randrange(int(self.canvas["width"])/2)
    29. y1 = random.randrange(int(self.canvas["height"]) / 2)
    30. x2 = x1 + random.randrange(int(self.canvas["width"]) / 2)
    31. y2 = y1 + random.randrange(int(self.canvas["height"]) / 2)
    32. self.canvas.create_rectangle(x1,y1,x2,y2)
    33. if __name__ == '__main__':
    34. root = Tk()
    35. root.geometry("500x400+200+300")
    36. root.title("测试canvas")
    37. app = Application(master=root)
    38. root.mainloop()

    6.布局管理器

    一个GUI应用程序必然有大量的组件,这些组件如何排布?这时候,就需要使用tkinter提供的布局管理器帮助我们组织、管理在父组件中子组件的布局方式。tkinter提供了三种管理器:pack、grid、place

    1.grid布局管理器

    grid表格布局,采用表格结构组织组件。子组件的位置由行和列的单元格来确定,并且可以跨行和跨列,从而实现复杂的布局。

    1. '''经典的Gui类的写法,使用面向对象的方法'''
    2. from tkinter import *
    3. from tkinter import messagebox
    4. class Application(Frame):
    5. '''一个经典的Gui的类的写法'''
    6. def __init__(self,master=None):
    7. super().__init__(master) #super()代表的是父类的定义,而不是父类对象
    8. self.master = master
    9. self.pack()
    10. self.createWideget()
    11. def createWideget(self):
    12. '''创建组件'''
    13. self.labe01 = Label(self, text="用户名")
    14. self.labe01.grid(row=0, column=0)
    15. self.entry01 = Entry(self)
    16. self.entry01.grid(row=0,column=1)
    17. Label(self,text="用户名为手机号").grid(row=0,column=2)
    18. Label(self, text="密码").grid(row=1, column=0)
    19. Entry(self, show="*").grid(row=1, column=1)
    20. Button(self, text="登录").grid(row=2, column=1, sticky=EW)
    21. Button(self, text="取消").grid(row=2, column=2, sticky=E)
    22. if __name__ == '__main__':
    23. root = Tk()
    24. root.geometry("400x100+200+300")
    25. root.title("测试grid布局")
    26. app = Application(master=root)
    27. root.mainloop()

    实现计算器软件界面

    2.Pack布局管理器

    pack按照组件的创建顺序将子组件添加到父组件中,按照垂直或者水平的方向自然排布。如果不指定任何选项,默认在父组件中自顶向下垂直添加组件。pack是代码量最少,最简单的一种,可以用于快速生成界面。

    1. #coding = utf-8
    2. #测试pack布局管理
    3. from tkinter import *
    4. root = Tk();root.geometry("700x220")
    5. #Frame是一个矩形区域,就是用来放置其它子组件
    6. f1 = Frame(root)
    7. f1.pack()
    8. f2 = Frame(root);f2.pack()
    9. btnText = ("流行风","中国风","日本风","重金属","轻音乐")
    10. for txt in btnText:
    11. Button(f1,text=txt).pack(side="left",padx="10")
    12. for i in range(1,20):
    13. Label(f2,width=5,height=10,borderwidth=1,relief="solid",bg="black" if i%2==0 else "white").pack(side="left",padx=2)
    14. root.mainloop()

    3.place布局器

    place布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。

    1. from tkinter import *
    2. root = Tk();root.geometry("500x300")
    3. root.title("布局管理place");root["bg"]="white"
    4. f1 = Frame(root,width=200,height=200,bg="green")
    5. f1.place(x=30,y=30)
    6. Button(root,text="小赵").place(relx=0.2,x=100,y=20,relwidth=0.2,relheight=0.5)
    7. Button(f1,text="小蒋").place(relx=0.2,rely=0.7)
    8. Button(f1,text="小余").place(relx=0.5,rely=0.2)
    9. root.mainloop()

     

    扑克牌游戏(自己添加图片)

    1. '''扑克牌游戏的界面设计'''
    2. from tkinter import *
    3. class Application(Frame):
    4. '''一个经典的Gui的类的写法'''
    5. def __init__(self,master=None):
    6. super().__init__(master) #super()代表的是父类的定义,而不是父类对象
    7. self.master = master
    8. self.pack()
    9. self.createWideget()
    10. def createWideget(self):
    11. '''通过place布局器实现扑克牌位置控制'''
    12. # self.photo = PhotoImage(file="")
    13. # self.puke1 = Label(self.master,image=self.photo)
    14. # self.pike1.place(x=10,y=50)
    15. self.photos = [PhotoImage(file=""+str(i+1)+".gif") for i in range(10)]
    16. self.pukes = [Label(self.master,image=self.photos[i]) for i in range(10)]
    17. for i in range(10):
    18. self.pukres[i].place(x=10+i*40,y=50)
    19. #为所有的Lable增加事件处理
    20. self.pikes[0].bind_class("Label","",self.chupai)
    21. def chupai(self,event):
    22. print(event.widget.winfo_geometry())
    23. print(event.widget.winfo_y())
    24. if event.widget.winfo_y() ==50:
    25. event.widget.place(y=30)
    26. else:
    27. event.widget.place(y=50)
    28. if __name__ == '__main__':
    29. root = Tk()
    30. root.geometry("200x200+200+300")
    31. app = Application(master=root)
    32. root,mainloop()

    7.事件处理

    一个GUI应用整个生命周期都处在一个消息循环(eventloop)中。它等待事件的发生,并作出相应的处理。

    Tkinter提供了用以处理相关事件的机制.处理函数可被绑定给各个控件的各种事件。widget.bind(event,handler)如果相关事件发生,handler函数会被触发,事件对象event会传递给handler函数.

     
    

    1. #测试键盘和鼠标事件
    2. from tkinter import *
    3. root = Tk();root.geometry("530x300")
    4. c1 = Canvas(root,width=200,height=200,bg="green")
    5. c1.pack()
    6. def mouseTest(event):
    7. print("鼠标左键单击位置(相当于父容器):{0},{1}".format(event.x,event.y))
    8. print("鼠标左键单击位置(相当于屏幕):{0},{1}".format(event.x_root, event.y_root))
    9. print("事件绑定的组件:{0}".format(event.widget))
    10. def testDrag(event):
    11. c1.create_oval(event.x,event.y,event.x+1,event.y+1)
    12. def keyboardTest(event):
    13. print("键的keycode:{0},键的char:{1},键的keysym:{2}".format(event.keycode,event.char,event.keysym))
    14. def press_a_test(event):
    15. print("press a")
    16. def release_a_test(event):
    17. print("release a")
    18. c1.bind("",mouseTest)
    19. c1.bind("",testDrag)
    20. root.bind("",keyboardTest)
    21. root.bind("",press_a_test)
    22. root.bind("",release_a_test)
    23. root.mainloop()

     

    1.lambda表达式

    lambda表达式定义的是一个匿名函数,只适合简单输入参数,简单计算返回结果,不适合功能复杂情况。lambda定义的匿名函数也有输入、也有输出,只是没有名字。语法格式如下:lambda参数值列表:表达式参数值列表即为输入。表达式计算的结构即为输出。

    我们写一个最简单的案例:add3args=lambdax,y,z:x+y+z#print(add3args(10,20,30))

    上面的lambda表达式相当于如下函数定义:defadd3args(x,y,z):returnx+y+zlambda

    表达式的参数值列表可以为如下内容:

    我们在平时使用时,注意lambda只是一个匿名函数(没有名字的函数),功能不强,不要过度使用;

    1. #测试command属性绑定事件,测试lambda表达式帮助传参
    2. from tkinter import *
    3. root = Tk();root.geometry("270x50")
    4. def mouseTest1():
    5. print("command方式,简单情况:不涉及获取event对象,可以使用")
    6. def mouserTest2(a,b):
    7. print("a={0},b={1}".format(a,b))
    8. Button(root,text="测试command1",command=mouseTest1).pack(side="left")
    9. Button(root,text="测试command2",command=lambda:mouserTest2("gaoqi","xixi")).pack(side="left")
    10. root.mainloop()

     

    2.多种事件绑定方式汇总

    1.组件对象的绑定

    1.通过command属性绑定(适合简单不需获取event对象)Button(root,text=”登录”,command=login)

    2.通过bind()方法绑定(适合需要获取event对象)c1=Canvas();c1.bind(“”,drawLine)

    2.组件类的绑定

    调用对象的bind_class函数,将该组件类所有的组件绑定事件:w.bind_class(“Widget”,”event”,eventhanler)

    比如:btn01.bind_class(“Button”,””,func)

    1. #多种事件绑定方法
    2. from tkinter import *
    3. root = Tk();root.geometry("270x30")
    4. def mouseTest(event):
    5. print("bind()方式绑定,可以获取event对象")
    6. print(event.widget)
    7. def mouseTest2(a,b):
    8. print("a={0},b={1}".format(a,b))
    9. print("commmand方式绑定,不能直接获取event对象")
    10. def mouseTest3(event):
    11. print("右键单击事件,绑定给所有按钮!!!")
    12. print(event.widget)
    13. b1 =Button(root, text="测试bind()绑定")
    14. b1.pack(side="left")
    15. #bind方式绑定事件
    16. b1.bind("",mouseTest)
    17. #command属性直接绑定事件
    18. b2 =Button(root, text="测试command2",command=lambda:mouseTest2("gaoqi","xixi"))
    19. b2.pack(side="left")
    20. #给所有的Button按钮都绑定右键单击事件
    21. b1.bind_class("Button","",mouseTest3)
    22. root.mainloop()
     
    

     

    8.其它组件

    1.OptionMenu选择项

    OptionMenu(选择项)用来做多选一,选中的项会在顶部显示。

    基本用法:

    1. #optionmenu的使用测试
    2. from tkinter import *
    3. root = Tk(); root.geometry("200x100")
    4. v = StringVar(root)
    5. v.set("信息收集模块")
    6. om = OptionMenu(root, v, "子域名","IP","whois","端口","股权穿透")
    7. om["width"] = 10
    8. om.pack()
    9. def test1():
    10. print("[+]开始收集............",v.get())
    11. #v.set("IP“) #直接修改了optionmenu中选中的值
    12. Button(root, text="确定", command=test1).pack()
    13. root.mainloop()
     
    

     

    2.Scale移动滑块

    Scale(移动滑块)用于在指定的数值区间,通过滑块的移动来选择值。

    1. #使用Scale移动滑块的使用测试
    2. from tkinter import *
    3. root = Tk(); root.geometry("400x150")
    4. def test1(value):
    5. print("滑块的值",value)
    6. newFont = ("宋体",value)
    7. a.config(font=newFont)
    8. s1 = Scale(root, from_=10, to = 50, length=200, orient=HORIZONTAL, command=test1)
    9. s1.pack()
    10. a= Label(root,text="字体放大器",width=10,height=1, bg="black", fg="white")
    11. a.pack()
    12. root.mainloop()

    3.颜色选择框

    颜色选择框可以帮助我们设置背景色、前景色、画笔颜色、字体颜色等等。

    1. #askcolor颜色选择框测试
    2. from tkinter import *
    3. from tkinter.colorchooser import *
    4. root = Tk(); root.geometry("400x150")
    5. def test1():
    6. s1 =askcolor(color="red",title="选择背景色")
    7. root.config(bg=s1[1])
    8. Button(root,text="选择背景色",command=test1).pack()
    9. root.mainloop()

    4.文件对话框

    文件对话框帮助我们实现可视化的操作目录、操作文件。最后,将文件、目录的信息传入到程序中。文件对话框包含如下一些常用函数:

     
    

    1. '''文件对话框获取文件名'''
    2. from tkinter import *
    3. from tkinter.filedialog import *
    4. root = Tk(); root.geometry("400x100")
    5. def test1():
    6. f = askopenfile(title="上传文件",initialdir="C:/",filetypes=[("视频文件","mp4")])
    7. show["text"] = f
    8. Button(root,text="选择编辑的视频文件",command=test1).pack()
    9. show = Label(root,width=40,height=3,bg="green")
    10. show.pack()
    11. root.mainloop()

     
    

     

    1. '''文件对话框获取文件名'''
    2. from tkinter import *
    3. from tkinter.filedialog import *
    4. root = Tk(); root.geometry("400x100")
    5. def test1():
    6. with askopenfile(title="上传文件",initialdir="桌面",filetypes=[("文本文件",".txt")]) as f:
    7. show["text"] = f.read().encode("UTF-8")
    8. Button(root,text="选择读取的文本文件",command=test1).pack()
    9. show = Label(root,width=40,height=3,bg="green")
    10. show.pack()
    11. root.mainloop()
     
    

     

    5简单对话框

    simpledialog(简单对话框)包含如下常用函数:

    参数中,title表示窗口标题;prompt是提示信息;命名参数kw为各种选项:initialvalue(初始值)、minvalue(最小值)、maxvalue(最大值)。

    1. '''简单对话框'''
    2. from tkinter.simpledialog import *
    3. root = Tk();root.geometry("400x100")
    4. def test1():
    5. a = askstring(title="输入域名",prompt="请输入需要收集的主域名",initialvalue=18) #minvalue=1,maxvalue=150
    6. #askstring,askfloat框使用方法一样
    7. show["text"]=a
    8. Button(root,text="消息收集模块-----请输入目标",command=test1).pack()
    9. show = Label(root,width=40, height=3, bg="green")
    10. show.pack()
    11. root.mainloop()

    6.通用消息框

    messagebox(通用消息框)用于和用户简单的交互,用户点击确定、取消。如下列出了messagebox的常见函数:

    1. '''通用消息框'''
    2. from tkinter import *
    3. from tkinter.messagebox import *
    4. root = Tk();root.geometry("400x100")
    5. a1 = showinfo(title="信息收集",message="[+]---------------")
    6. print(a1)
    7. root.mainloop()

    7.ttk子控模块

    我们再前面学的组件是tkinter模块下的组件,整体风格较老较丑。为了弥补这点不足,推出了ttk组件。ttk组件更加美观、功能更加强大。使用Combobox替代了原来的Listbox、新增了LabeledScale(带标签的Scale)、Notebook(多文档窗口)、Progressbar(进度条)、Treeview(数)等组件。使用ttk组件与使用普通的Tkinter组件并没有多大的区别,只要导入ttk模块即可。

    ttk子模块的官方文档:https://docs.python.org/3.7/library/tkinter.ttk.html

    9.菜单

    GUI程序通常都有菜单,方便用户的交互。我们一般将菜单分为两种:1.主菜单主菜单通常位于GUI程序上方。例如:

    1.主菜单主菜单通常位于GUI程序上方。例如:

    1. '''设计功能菜单那'''
    2. from tkinter import *
    3. from tkinter.messagebox import *
    4. from tkinter.filedialog import *
    5. root = Tk(); root.geometry("400x400")
    6. #创建主菜单栏
    7. menubar = Menu(root)
    8. #创建子菜单
    9. menuFile = Menu(menubar)
    10. menuEile = Menu(menubar)
    11. menuHelp = Menu(menubar)
    12. #将子菜单加入到主菜单栏
    13. menubar.add_cascade(label="信息收集模块",menu=menuFile)
    14. menubar.add_cascade(label="渗透模块",menu=menuEile)
    15. menubar.add_cascade(label="内网模块",menu=menuHelp)
    16. filename=""
    17. def openFile():
    18. global filename
    19. with askopenfile(title="打开文件") as f:
    20. content = f.read()
    21. w1.insert(INSERT,content)
    22. filename = f.name
    23. print(f.name)
    24. def saveFile():
    25. with open(filename,"w") as f:
    26. content = w1.get(1.0,END)
    27. f.write(content)
    28. def exit():
    29. root.quit()
    30. #添加菜单项
    31. menuFile.add_command(label="打开",accelerator="^O",command=openFile)
    32. menuFile.add_command(label="保存",command=saveFile)
    33. #添加分割线
    34. menuFile.add_separator()
    35. menuFile.add_command(label="退出",command=exit)
    36. #将主菜单加到根窗口
    37. root["menu"] = menubar
    38. w1 = Text(root,width=50,height=30)
    39. w1.pack()
    40. root.mainloop()
     
    

    2.快捷菜单(上下文菜单)通过鼠标右键单击某个组件对象而弹出的菜单,一般是与该组件相关的操作。

    比如:剪切、复制、粘贴、属性等。创建快捷菜单步骤如下:

    1.创建菜单menubar=tk.Menu(root)menubar.add_command(label=”字体”)

    2.绑定鼠标右键单击事件deftest(event):menubar.post(event.x_root,event.y_root)#在鼠标右键单击坐标处显示菜单root.bind(“”,test)

    1. """开发记事本软件的菜单
    2. """
    3. from tkinter.filedialog import *
    4. from tkinter.colorchooser import *
    5. class Application(Frame):
    6. def __init__(self, master=None):
    7. super().__init__(master) # super()代表的是父类的定义,而不是父类对象
    8. self.master = master
    9. self.textpad = None # textpad表示Text文本框对象
    10. self.pack()
    11. self.createWidget()
    12. def createWidget(self):
    13. # 创建主菜单栏
    14. menubar = Menu(root)
    15. # 创建子菜单
    16. menuFile = Menu(menubar)
    17. menuEdit = Menu(menubar)
    18. menuHelp = Menu(menubar)
    19. # 将子菜单加入到主菜单栏
    20. menubar.add_cascade(label="文件(F)", menu=menuFile)
    21. menubar.add_cascade(label="编辑(E)", menu=menuEdit)
    22. menubar.add_cascade(label="帮助(H)", menu=menuHelp)
    23. # 添加菜单项
    24. menuFile.add_command(label="新建", accelerator="ctrl+n", command=self.newfile)
    25. menuFile.add_command(label="打开", accelerator="ctrl+o", command=self.openfile)
    26. menuFile.add_command(label="保存", accelerator="ctrl+s",command=self.savefile)
    27. menuFile.add_separator() # 添加分割线
    28. menuFile.add_command(label="退出", accelerator="ctrl+q",command=self.exit)
    29. # 将主菜单栏加到根窗口
    30. root["menu"] = menubar
    31. # 增加快捷键的处理
    32. root.bind("",lambda event:self.newfile())
    33. root.bind("",lambda event:self.openfile())
    34. root.bind("",lambda event:self.savefile())
    35. root.bind("",lambda event:self.exit())
    36. #文本编辑区
    37. self.textpad = Text(root, width=50, height=30)
    38. self.textpad.pack()
    39. # 创建上下菜单
    40. self.contextMenu = Menu(root)
    41. self.contextMenu.add_command(label="背景颜色", command=self.openAskColor)
    42. #为右键绑定事件
    43. root.bind("",self.createContextMenu)
    44. def newfile(self):
    45. self.textpad.delete("1.0", "end") # 把text控件中所有的内容清空
    46. self.filename= asksaveasfilename(title="另存为",initialfile="未命名.txt",
    47. filetypes=[("文本文档","*.txt")],
    48. defaultextension=".txt")
    49. self.savefile()
    50. def openfile(self):
    51. self.textpad.delete("1.0","end") # 把text控件中所有的内容清空
    52. with askopenfile(title="打开文本文件") as f:
    53. self.textpad.insert(INSERT,f.read())
    54. self.filename = f.name
    55. def savefile(self):
    56. with open(self.filename,"w") as f:
    57. c = self.textpad.get(1.0,END)
    58. f.write(c)
    59. def exit(self):
    60. root.quit()
    61. def openAskColor(self):
    62. s1 = askcolor(color="red",title="选择背景色")
    63. self.textpad.config(bg=s1[1])
    64. def createContextMenu(self,event):
    65. # 菜单在鼠标右键单击的坐标处显示
    66. self.contextMenu.post(event.x_root, event.y_root)
    67. if __name__ == '__main__':
    68. root = Tk()
    69. root.geometry("450x300+200+300")
    70. root.title("Darling的简易记事本")
    71. app = Application(master=root)
    72. root.mainloop()

    10.将python模块打包成exe

    我们可以使用pyinstaller 模块实现将 python项目打包成exe文件。操作步骤如下:

    1.安装pyinstaller模块

    在pycharm 中操作:file-->setting-->Project: xx -->project interpretor,再点击+即可。

     

    2.在pycharm的Terminal 终端输入如下命令:

    pyinstaller -F  xxx.py

    【注】相关参数如下:

    --icon=图标路径(pyinstaller -F --icon=my.ico XxXX.py)

    -F打包成一个exe文件

    -w使用窗口,无控制台

    -c使用控制台,无窗口

    -D创建一个目录,里面包含exe 以及其他一些依赖性文件

    3.在项目的dist目录下可以看到生成了exe文件,直接在windows系统中使用即司。

    1. """开发画图软件的菜单
    2. """
    3. from tkinter.filedialog import *
    4. from tkinter.colorchooser import *
    5. #窗口的宽度和高度
    6. win_width=900
    7. win_height=450
    8. class Application(Frame):
    9. def __init__(self, master=None,bgcolor="#000000"):
    10. super().__init__(master) # super()代表的是父类的定义,而不是父类对象
    11. self.master = master
    12. self.bgcolor=bgcolor
    13. self.x = 0
    14. self.y = 0
    15. self.fgcolor = "#ff0000"
    16. self.lastDraw = 0 # 表示最后绘制的图形的id
    17. self.startDrawFlag = False
    18. self.pack()
    19. self.createWidget()
    20. def createWidget(self):
    21. # 创建绘图区
    22. self.drawpad = Canvas(root,width=win_width,height=win_height*0.9,bg=self.bgcolor)
    23. self.drawpad.pack()
    24. #创建按钮
    25. btn_start = Button(root,text="开始",name="start")
    26. btn_start.pack(side="left",padx="10")
    27. btn_pen = Button(root,text="画笔",name="pen")
    28. btn_pen.pack(side="left",padx="10")
    29. btn_rect = Button(root,text="矩形",name="rect")
    30. btn_rect.pack(side="left",padx="10")
    31. btn_clear = Button(root,text="清屏",name="clear")
    32. btn_clear.pack(side="left",padx="10")
    33. btn_erasor = Button(root,text="橡皮擦",name="erasor")
    34. btn_erasor.pack(side="left",padx="10")
    35. btn_line = Button(root,text="直线",name="line")
    36. btn_line.pack(side="left",padx="10")
    37. btn_lineArrow = Button(root,text="箭头直线",name="lineArrow")
    38. btn_lineArrow.pack(side="left",padx="10")
    39. btn_color = Button(root,text="颜色",name="color")
    40. btn_color.pack(side="left",padx="10")
    41. #事件处理
    42. btn_pen.bind_class("Button","<1>",self.eventManager)
    43. self.drawpad.bind("",self.stopDraw)
    44. #增加颜色切换的快捷键
    45. root.bind("",self.kuaijiejian)
    46. root.bind("",self.kuaijiejian)
    47. root.bind("",self.kuaijiejian)
    48. def eventManager(self,event):
    49. name = event.widget.winfo_name()
    50. print(name)
    51. if name=="line":
    52. self.drawpad.bind("",self.myline)
    53. elif name=="lineArrow":
    54. self.drawpad.bind("",self.mylineArrow)
    55. elif name=="rect":
    56. self.drawpad.bind("",self.myRect)
    57. elif name=="pen":
    58. self.drawpad.bind("",self.myPen)
    59. elif name=="erasor":
    60. self.drawpad.bind("",self.myErasor)
    61. elif name=="clear":
    62. self.drawpad.delete("all")
    63. elif name=="color":
    64. c = askcolor(color=self.fgcolor,title="选择画笔颜色")
    65. #[(255,0,0),"#ff0000"]
    66. self.fgcolor = c[1]
    67. def stopDraw(self,event):
    68. self.startDrawFlag = False
    69. self.lastDraw = 0
    70. def startDraw(self,event):
    71. self.drawpad.delete(self.lastDraw)
    72. if not self.startDrawFlag:
    73. self.startDrawFlag = True
    74. self.x = event.x
    75. self.y = event.y
    76. def myline(self,event):
    77. self.startDraw(event)
    78. self.lastDraw = self.drawpad.create_line(self.x,self.y,event.x,event.y,fill=self.fgcolor)
    79. def mylineArrow(self,event):
    80. self.startDraw(event)
    81. self.lastDraw = self.drawpad.create_line(self.x,self.y,event.x,event.y,arrow=LAST,fill=self.fgcolor)
    82. def myRect(self,event):
    83. self.startDraw(event)
    84. self.lastDraw = self.drawpad.create_rectangle(self.x,self.y,event.x,event.y,outline=self.fgcolor)
    85. def myPen(self,event):
    86. self.startDraw(event)
    87. self.drawpad.create_line(self.x,self.y,event.x,event.y,fill=self.fgcolor)
    88. self.x = event.x
    89. self.y = event.y
    90. def myErasor(self,event):
    91. self.startDraw(event)
    92. self.drawpad.create_rectangle(event.x-4,event.y-4,event.x+4,event.y+4,fill=self.bgcolor)
    93. self.x = event.x
    94. self.y = event.y
    95. def kuaijiejian(self,event):
    96. if event.char =="r":
    97. self.fgcolor = "#ff0000"
    98. elif event.char =="g":
    99. self.fgcolor = "#00ff00"
    100. elif event.char =="y":
    101. self.fgcolor = "#ffff00"
    102. if __name__ == '__main__':
    103. root = Tk()
    104. root.geometry(str(win_width)+"x"+str(win_height)+"+200+300")
    105. root.title("Darling的画图软件")
    106. app = Application(master=root)
    107. root.mainloop()

  • 相关阅读:
    GateWay——向其他服务传递参数数据(思路)
    [Python]多态、类方法、类属性
    报错处理:Nginx端口被占用
    连接查询
    Python使用scapy库监听指定的网卡数据并转发
    读书随笔《围城》——就近日某高校高价引进海龟博士有感
    福建三明大型工程机械3D扫描测量工程零件开模加工逆向抄数-CASAIM中科广电
    【MATLAB第35期】基于MATLAB的2023年改进的进化算法优化LSTM时间序列预测模型思路
    Python3的pytesseract和Tesseract-ocr的使用以及自己训练数据集的方法
    SpringBoot SpringBoot 基础篇(第一篇) 第1章 SpringBoot 入门 1.2 开发环境
  • 原文地址:https://blog.csdn.net/qq_52074678/article/details/128178056