Python有很多GUI库,tkinter作为一款入门级的图形库,基本具备了图形界面的大部分元素,如果结合ttk、Pmw库使用的话,其功能就得到了扩展,使用这些库基本能构建简单的图形界面应用。但是,tkinter唯一美中不足的是它的性能问题,它不具备如QT等一些第三方库的性能,在同一应用程序中设计了关于获取系统性能的一些功能,tkinter就显得非常慢(参加Python高手养成关于系统性能查看器制作的内容),虽然其性能可以通过不同的方法得到提升,但这是后话,我们后续章节进行讨论。今天结合一个实例,带大家一起见识一下tkinter的基本使用方法。
【课题内容】
使用tkinter制作一个带有菜单的绘图工具,菜单中选择绘制图形的内容(程序中我们建立了绘制圆、椭圆、矩形、直线等图形的方法),还可以使用菜单命令清除绘制的图形界面,菜单提供帮助信息(主要显示如何绘制图形的方法),菜单弹出框显示应用程序版本信息。
【界面分析】
界面基本功能如下图
图形界面布局
图形绘制效果如下
使用程序绘制的图形
点击清空画板后图形消失
画板清空效果
菜单其他内容如下
界面帮助信息
【编码设计】
程序主要难点有四个
如何通过菜单控制绘制不同的图形(我们使用布尔变量值控制绘制不同的图形)获取鼠标起始位置和释放鼠标位置,然后在两点之间绘制相应图片(在这里使用函数绑定鼠标点击和鼠标释放的事件,然后获取事件中鼠标的位置信息)在Canvas中显示帮助信息,如何清除(结合菜单控制清除内容是个不错的选择)如何将上述内容封装到画图类中(类的封装,实测封装效果不太好,欢迎大家留言讨论哦)下面,我们对这个绘图类进行编码
#!/usr/bin/env python# coding:utf-8import mathfrom tkinter import *from tkinter import messageboxfrom tkinter import simpledialogclass Painter(Tk):def __init__(self, startX=0, startY=0, curX=0, curY=0, endX=0, endY=0, line=False, rect=False, oval=False, arc=False, circle=False, polygon=False): Tk.__init__(self, ) self.title('绘图工具v1.0') self.geometry('800x600') self.resizable(width=False, height=False) # 布尔值指定画相应的图形 self.line = line self.rect = rect self.oval = oval self.arc = arc self.circle = circle self.polygon = polygon # 鼠标位置信息参数 self.startX = startX self.startY = startY self.curX = curX self.curY = curY self.endX = endX self.endY = endY # 初始化控件 self.createWidgets() def createWidgets(self): self.menubar = Menu(self) self.canvasmenu = Menu(self.menubar, tearoff=False) self.canvasmenu.add_command(label='椭圆', command=self.create_oval) self.canvasmenu.add_command(label='圆', command=self.create_circle) self.canvasmenu.add_command(label='圆弧', command=self.create_arc) self.canvasmenu.add_command(label='矩形', command=self.create_rect) self.canvasmenu.add_command(label='多边形', command=self.create_polygon) self.canvasmenu.add_command(label='直线', command=self.create_line) self.canvasmenu.add_separator() self.canvasmenu.add_command(label='清空画板', command=self.clean) self.canvasmenu.add_separator() self.canvasmenu.add_command(label='退出', command=self.destroy) self.menubar.add_cascade(label='绘图', menu=self.canvasmenu) self.settingmenu = Menu(self.menubar, tearoff=False) self.settingmenu.add_command(label='设置图形样式...', command=self.settings) self.menubar.add_cascade(label='设置', menu=self.settingmenu) self.helpmenu = Menu(self.menubar, tearoff=False) self.helpmenu.add_command(label="关于...", command=self.about) self.helpmenu.add_command(label='使用帮助', command=self.helps) self.menubar.add_cascade(label='帮助', menu=self.helpmenu) self.config(menu=self.menubar) self.canvas = Canvas(self, width=500, height=400,) self.canvas.bind('', self.getStartInfo) self.canvas.bind('', self.getEndInfo) self.canvas.bind('', self.getCurInfo) self.canvas.pack(side=TOP, expand=YES, fill=BOTH) def getStartInfo(self, event): self.startX = event.x self.startY = event.y def getCurInfo(self, event): self.curX = event.x self.curY = event.y def getEndInfo(self, event): self.endX = event.x self.endY = event.y if self.line == True: self.canvas.create_line( self.startX, self.startY, self.endX, self.endY, fill='blue') elif self.rect == True: self.canvas.create_rectangle(self.startX, self.startY, self.endX, self.endY, fill='red', tags="rect") elif self.oval == True: self.canvas.create_oval(self.startX, self.startY, self.endX, self.endY, fill='green', tags='oval') elif self.arc == True: self.canvas.create_arc(self.startX, self.startY, self.endX, self.endY, start=0, extent=90, width=2, fill="yellow", tags="arc") elif self.circle == True: x = self.startX y = self.startY r = math.sqrt((self.endX - x) ** 2 + (self.endY - y) ** 2) self.canvas.create_oval( x - r, y - r, x + r, y + r, fill='pink', tags='circle') elif self.polygon == True: n = simpledialog.askinteger("输入", "您要绘制几边形(大于3的整数):", initialvalue=3, minvalue=3, maxvalue=50) pass def create_oval(self): self.oval = True self.rect = False self.line = False self.arc = False self.circle = False self.polygon = False def create_rect(self): self.rect = True self.line = False selfer.oval = False self.arc = False self.circle = False self.polygon = False def create_line(self): self.line = True self.rect = False self.oval = False self.arc = False self.circle = False self.polygon = False def create_arc(self): self.arc = True self.line = False self.rect = False self.oval = False self.circle = False self.polygon = False def create_circle(self): self.circle = True self.line = False self.rect = False self.oval = False self.arc = False self.polygon = False def create_polygon(self): self.polygon = True self.circle = False self.line = False self.rect = False self.oval = False self.arc = False def helps(self): self.canvas.delete('all') self.canvas.create_text(400, 300, text='\t\t【画图步骤】\n \ 1.从菜单栏中选择想要绘制的图形,移动鼠标至绘图区内;\n \ 2.使用鼠标在主窗口绘图区中单击,选择图e形起始点;\n \ 3.单击后不要松开鼠标,继续拖动至所绘制图形结束点;\n \ 4.松开鼠标即可画出相应的图形\n \ ***单击菜单"【绘图】-【清空画板】"后此信息消失***', fill='red', font=('微软雅黑', 18)) def settings(self): print('开发中...') def clean(self): self.update() self.canvas.delete('all') @staticmethod def about(): messagebox.showinfo('关于...', '绘图工具v1.0')if __name__ == "__main__": Painter().mainloop()
详细缩进看下图源代码
导入模块
类的初始化
类中创建组件
类方法绘制图形
布尔变量控制绘制图形开关
程序其余部分
【总 结】
程序效果上图所示,源代码已经粘贴到上面了,个人觉得布尔变量控制上还可以重构,而且对于多边形的绘制,暂时没有实现,主要是想通过simpledialog中获得多边形的边数,但是弹出的对话框如下图
弹出获取多边形边数的对话框
在输入边数后点击“OK”按钮,对话框并没有消失,且点击主窗口中Canvas区域后,多边形对话框又会弹出来,可能这是simpledialog.askinteger的一个bug吧,如果要获取输入,看来只能自定义一个控件了,感兴趣的朋友又没好办法,欢迎大家留言讨论。后续,我试图对这个界面进行扩展,如自定义绘制图形的填充格式、鼠标移动时显示临时绘制轨迹、对个别图形进行删除(暂时是全部清除)等等……欢迎留言关注。
转载请注明出处(百家号:Python高手养成)