1、Python实现画板功能
import tkinter import wx.stc import tkinter.simpledialog import tkinter.colorchooser import tkinter.filedialog from PIL import Image from PIL import ImageGrab root = tkinter.Tk() root.title('罗式画画') root['width'] = 800 root['height'] = 600 #控制是否允许画图的变量,1为允许,0为不允许 canDraw = tkinter.IntVar(value=0) #控制画图类型的变量,1为曲线,2为直线,3为矩形,4为文本,5为橡皮 what = tkinter.IntVar(value=1) #记录鼠标位置的变量 X = tkinter.IntVar(value=0) Y = tkinter.IntVar(value=0) #前景色、背景色 foreColor = '#000000' backColor = '#FFFFFF' #创建画布,设置尺寸和背景色 image = tkinter.PhotoImage('a.gif') canvas = tkinter.Canvas(root,bg='white',width=800,height=600) canvas.create_image(800,600,image=image) #按下鼠标左键,允许画图,记录鼠标按下的位置 def onLeftButtonDown(event): canDraw.set(1) X.set(event.x) Y.set(event.y) if what.get() == 4: #这是tkinter.Canvas().create_text文本方法,用来输出文本 #需要三个参数 canvas.create_text(event.x,event.y,text=text) #<Button-1>表示鼠标左键单击,其中的1换成3表示右键被单击,为2的时候表示鼠标中键 canvas.bind('<Button-1>',onLeftButtonDown) #记录最后绘制图形的id lastDraw = 0 #按住鼠标左键移动,画图 def onLeftButtonMove(event): global lastDraw print(lastDraw) if canDraw.get() == 0: return if what.get() == 1: #使用当前选择的前景色绘制曲线 canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor) X.set(event.x) Y.set(event.y) elif what.get() == 2: #绘制直线,先删除刚刚画过的直线,再画一条新的线 try: #移动一个点删除一个点 canvas.delete(lastDraw) except Exception as e: pass lastDraw = canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor) elif what.get==3: #绘制矩形,线删除刚刚画过的矩形,再画一个新的矩形 try: canvas.delete(lastDraw) except Exception as e: pass lastDraw = canvas.create_rectangle(X.get(),Y.get(),event.x,event.y,fill=backColor,outline=foreColor) elif what.get()==5: #橡皮,使用背景色填充10*10的矩形区域,相当于擦除图像 canvas.create_rectangle(event.x-5,event.y-5,event.x+5,event.y+5,outline=backColor,fill=backColor) canvas.bind('<B1-Motion>',onLeftButtonMove) #鼠标左键抬不起,不允许画图 # def onLeftButtonUp(event): # if what.get()==2: # #多绘制一条直线 # canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor) # elif what.get()==3: # #多绘制一个矩形 # canvas.create_rectangle(X.get(),Y.get(),event.x,event.y,fill=foreColor) # canDraw.set(0) # global lastDraw # #防止切换图形时误删上次绘制的图形 # lastDraw = 0 # canvas.bind('<ButtonRelease-1>',onLeftButtonUp) #创建菜单 menu = tkinter.Menu(root,tearoff=0) #打开图像文件 #这个位置存在问题(打开图片不完全) def Open(): filename = tkinter.filedialog.askopenfilename(title='Open Image',filetypes=[('image','*.png')]) if filename: global image image = tkinter.PhotoImage(file=filename) canvas.create_image(800,600,image=image) menu.add_command(label='Open',command=Open) def Save(): #获取客户区域位置和尺寸,并截图保存,扩展库pillow left = int(root.winfo_rootx()) top = int(root.winfo_rooty()) width = root.winfo_width()-4 height = root.winfo_height()-4 print(left,top,width,height,sep=',') im = ImageGrab.grab((left,top,left+width,top+height)) #保存绘制的图片 filename = tkinter.filedialog.asksaveasfilename(title='保存图片',filetypes=[('图片文件','*.png')]) if not filename: return if not filename.endswith('.png'): filename = filename + '.png' im.save(filename) menu.add_command(label='Save',command=Save) #添加菜单,清楚所有图像 def Clear(): for item in canvas.find_all(): canvas.delete(item) menu.add_command(label='Clear',command=Clear) #添加分割线 menu.add_separator() #创建子菜单,用来选择绘图类型 menuType = tkinter.Menu(menu,tearoff=0) def drawCurve(): what.set(1) menuType.add_command(label='Curve',command=drawCurve) def drawLine(): what.set(2) menuType.add_command(label='Line',command=drawLine) def drawRectangle(): what.set(3) menuType.add_command(label='Rectangle',command=drawRectangle) def drawText(): global text text = tkinter.simpledialog.askstring(title='Input what you want to draw',prompt='') what.set(4) menuType.add_command(label='Text',command=drawText) menuType.add_separator() #选择前景色 def chooseForeColor(): global foreColor foreColor = tkinter.colorchooser.askcolor()[1] menuType.add_command(label='Choose Foreground Color',command=chooseForeColor) #选择背景色 def chooseBackColor(): global backColor backColor = tkinter.colorchooser.askcolor()[1] menuType.add_command(label='Choose Background Color',command=chooseBackColor) #橡皮 def onErase(): what.set(5) menuType.add_command(label='Erase',command=onErase) menu.add_cascade(label='Type',menu=menuType) #鼠标右键抬起,弹出菜单 def onRighButonUp(event): menu.post(event.x_root,event.y_root) canvas.bind('<ButtonRelease-3>',onRighButonUp) canvas.pack(fill=tkinter.BOTH,expand=tkinter.YES) #启动应用程序 root.mainloop()
2、实现电子时钟 使用Label组件实现显示当前时间和日期 涉及到的知识主要有多线程、无标题栏、半透明、顶端显示、可拖动窗口的设计
''' 实现电子时钟 使用Label组件实现显示当前时间和日期 涉及到的知识主要有多线程、无标题栏、半透明、顶端显示、可拖动窗口的设计 ''' import datetime import threading import time import tkinter app = tkinter.Tk() app.overrideredirect(True) #不显示标题栏 app.attributes('-alpha',0.9) #半透明 app.attributes('-topmost',1) #总是再顶端 app.geometry('110x25+100+100') labelDateTime = tkinter.Label(app) labelDateTime.pack(fill=tkinter.BOTH,expand=tkinter.YES) labelDateTime.configure(bg='gray') X = tkinter.IntVar(value=0) Y = tkinter.IntVar(value=0) canMove = tkinter.IntVar(value=0) still = tkinter.IntVar(value=1) #是否任再运行 def onLeftButtonDown(event): '''当鼠标按下时候,会改变透明度,同时标记可移动''' app.attributes('-alpha',0.4) #开始拖动时增加透明度 X.set(event.x) #鼠标左键按下,记录当前位置 Y.set(event.y) canMove.set(1) #标记窗口可移动 labelDateTime.bind('<Button-1>',onLeftButtonDown) def onLeftButtonUp(event): '''当鼠标左键抬起时,会恢复透明度,同时标记不可移动''' app.attributes('-alpha',0.9) #停止拖动时恢复透明度 canMove.set(0) #鼠标抬起的时,标记窗口不可拖动 labelDateTime.bind('<ButtonRelease-1>',onLeftButtonUp) def onLeftButtonMove(event): '''按下并移动鼠标时,可以更改窗口位置 winfo_x() 表示窗口再桌面上的位置-->开始就是100,100 X.get() 表示 ''' if canMove.get() == 0: return newX = app.winfo_x()+(event.x-X.get()) newY = app.winfo_y()+(event.y-Y.get()) print(app.winfo_x(),app.winfo_y(),sep=',') print(event.x,event.y,sep=',') print(X.get(),Y.get(),sep=',') g = '110x25+'+str(newX)+'+'+str(newY) app.geometry(g) #修改窗口位置 labelDateTime.bind('<B1-Motion>',onLeftButtonMove) def onRightButtonDown(event): still.set(0) #停止更新时间 t.join(0.2) #等待子线程结束 app.destroy() #关闭窗口 labelDateTime.bind('<Button-3>',onRightButtonDown) def nowDateTime(): while still.get() == 1: now = datetime.datetime.now() #获取当前时间日期 s = str(now.year)+'-'+str(now.month)+'-'+str(now.day)+' ' s = s+str(now.hour)+':'+str(now.minute)+':'+str(now.second) labelDateTime['text'] = s time.sleep(0.2) t = threading.Thread(target = nowDateTime) t.daemon = True #如果主进程结束了,t这个线程也跟着结束 t.start() app.mainloop()
3、简易计算器
''' 简易计算器 ''' import re import tkinter import tkinter.messagebox root = tkinter.Tk() #设置窗口大小和位置,300和270之间是小写字母x,不是乘号 root.geometry('300x270+400+100') #不允许改变窗口大小 root.resizable(False,False) #设置窗口标题 root.title('罗式简式计算器') root.attributes('-topmost',1) #放置用来显示表达式和计算结果的文本框,并设置为只读 contentVar = tkinter.StringVar(root,'') #这里的contentEntry里面的值,只要contentVar改变,里面的值就会改变 contentEntry = tkinter.Entry(root,textvariable=contentVar) contentEntry['state'] = 'readonly' contentEntry.place(x=10,y=10,width=280,height=20) #按钮通用代码 def buttonClick(btn): content = contentVar.get() #如果已有内容式以小数点开头的,前面加0 if content.startswith('.'): content = '0' + content #根据不同按钮做出相应的处理 if btn in '0123456789': content+=btn elif btn == '.': lastPart = re.split(r'\+|-|\*|/',content)[-1] if '.' in lastPart: tkinter.messagebox.showerror('错误','小数点太多了') return else: content += btn elif btn=='C': content = '' elif btn=='=': try: #对输入的表达式求值 content = str(eval(content)) except: tkinter.messagebox.showerror('错误','表达式错误') return elif btn in operators: if content.endswith(operators): tkinter.messagebox.showerror('错误','不允许存在连续运算符') return content+=btn elif btn == 'Sqlt': n = content.split('.') if all(map(lambda x:x.isdigit(),n)): content = eval(content)**0.5 else: tkinter.messagebox.showerror('错误','表达式错误') return contentVar.set(content) #放置Clear按钮和‘=’按钮 btnClear = tkinter.Button(root,text='Clear',command=lambda :buttonClick('C')) btnClear.place(x=40,y=40,width=80,height=20) btnCompute = tkinter.Button(root,text='=',command=lambda :buttonClick('=')) btnCompute.place(x=170,y=40,width=80,height=20) #防止10个数字,小数点和计算平方根的按钮 digits = list('0123456789.')+['Sqrt'] index = 0 for row in range(4): for col in range(3): d = digits[index] index += 1 btnDigit = tkinter.Button(root,text=d,command=lambda x=d:buttonClick(x)) btnDigit.place(x=20+col*70,y=80+row*50,width=50,height=20) #放置运算符按钮 operators = ('+','-','*','/','**','//') for index,operator in enumerate(operators): btnOperator = tkinter.Button(root,text=operator,command=lambda x=operator:buttonClick(x)) btnOperator.place(x=230,y=80+index*30,width=50,height=20) root.mainloop()
4、桌面放大镜
''' 桌面放大镜 ''' import tkinter from PIL import ImageGrab,ImageTk #创建应用主程序窗口,铺满整个屏幕,并删除标题栏 root = tkinter.Tk() screenWidth = root.winfo_screenwidth() screenHeight = root.winfo_screenheight() print(screenWidth,screenHeight,sep=',') root.geometry(str(screenWidth)+'x'+str(screenHeight)+'+0+0') root.overrideredirect(True) #不允许改变窗口大小 root.resizable(False,False) #创建画布,显示全屏截图,以便后面再全屏截图上进行区域截图并进行放大 canvas = tkinter.Canvas(root,bg='white',width=screenWidth,height=screenHeight) image = ImageTk.PhotoImage(ImageGrab.grab()) canvas.create_image(screenWidth//2,screenHeight//2,image=image) #右键退出桌面放大器程序 def onm ouseRightClick(event): root.destroy() canvas.bind('<Button-3>',onMouseRightClick) #截图窗口半径 radius = 20 def onm ouseMove(event): global lastIm,subIm try: canvas.delete(lastIm) except: pass #获取鼠标位置 x = event.x y = event.y #第二次截图,放大3倍,再鼠标当前位置左上方显示 subIm = ImageGrab.grab((x-radius,y-radius,x+radius,y+radius)) subIm = subIm.resize((radius*6,radius*6)) subIm = ImageTk.PhotoImage(subIm) lastIm = canvas.create_image(x-0,y-70,image=subIm) # canvas.update() #绑定鼠标移动事件处理函数 canvas.bind('<Motion>',onMouseMove) #把画布对象canvas放置到窗体上,两个方向都填满窗口,且自适应窗口大小的改变 canvas.pack(fill=tkinter.BOTH,expand=tkinter.YES) #启动消息主循环 root.mainloop()
标签:canvas,tkinter,get,Python,画板,放大镜,command,root,event From: https://www.cnblogs.com/buchijiuminvhai/p/17029245.html