首页 > 编程语言 >Python实现画板、电子时钟、计算器、桌面放大镜

Python实现画板、电子时钟、计算器、桌面放大镜

时间:2023-01-09 12:23:49浏览次数:49  
标签:canvas tkinter get Python 画板 放大镜 command root event

 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

相关文章

  • docker安装并运行python文件
    1、使用docker安装python环境,并运行python程序文件 首先,创建目录:/home/python/python-docker-app并进入python-docker-app目录下,创建dockerfile文件命令:vimdock......
  • Python+Selenium
    python+Selenium学习Selenium组件SeleniumIDE:是一个测试集成开发环境,可以结合FF录制脚本,并对脚本编辑和调试特点:1.很容易在页面上就行录制​2.能自动通......
  • Python-列表
    列表中的每一个元素都是可变的。这意味着我们可以在列表中添加、删除、修改元素。 列表中的元素是有序的。Weekday=['Monday','Tuesday','Wednesday','Thursday','F......
  • Python_sqlite3与sqlite数据库交互
    基础功能importsqlite3#sqlite一个文件就是一个库#连接test.db数据库,没有就创建conn=sqlite3.connect('test.db')#创建一个cursorcur=conn.cursor()#......
  • Python-字符串
    用单引号,双引号,三引号创建字符串。不同数据类型是不能够合并的,必须转换为同一类型num=1string='1'num2=int(string)print(num+num2)   加号(+)用于字......
  • Python语言——实现登陆界面的跳转
    Python语言——实现登陆界面的跳转importtkinter'''实现登陆界面的跳转'''defenter():root=tkinter.Tk()root.title('信息界面')root['width']=......
  • python爬虫如何爬取招聘数据
    互联互通的时代,几乎任何行业有关的数据都可以在网络上查到,那么作为大数据公司,如何借用爬虫实现公开数据抓取数据就显得尤为重要,下面就是有关招聘信息等数据的抓取代码案例可......
  • Python爬虫
    参考网址https://blog.csdn.net/qq_35709559/article/details/84859927爬虫示例:将百度的图片下载到本地'''1.找到图片的url2.发送请求获取响应3.保存图片(流媒体......
  • 2023.1-09 python基础
    列表常用方法append增加一个元素a.append('aaaa')extend增加多个a.extend([1,2,3,4,5,6])index检索,个人理解类似于findprint(a.index("is"))inset指定位置插入......
  • Python笔记——列表一:列表简介(Python编程:从入门到实践)
    一、列表是什么列表:由一系列按特定顺序排列的元素组成(列表是有序集合)。表示:用方括号[]来表示,并用逗号来分隔其中的元素。访问:访问列表元素,可指出列表的名称,再指出......