黑板模拟器是一个多线程控制尝试,需要做到通过tkinter实现对鼠标的控制和监督。鼠标在移动时会有一个线程来检测鼠标的位置,计算窗口的位置,计算出鼠标在窗口中的位置,结合canvas画布实现对黑板的涂改。
黑板模拟器的功能比较单一,只有一个画白线的功能,但是这是一个多线程控制技术的尝试。之后的绝大多数发明都会用到这样的技术,因为这样的交互会更加方便,效果会更好。
首先展示功能页面:
?展示一下使用效果:
教你如何用python制作黑板模拟器 python项目小发明
接下来讲解其实现原理:
前端代码:
class basedesk():#底板
def __init__(self, master):
self.master = master
self.master.title("黑板模拟器")
self.master.configure(bg='#B1FFF9')
self.master.geometry("1000x600")
mainwindow(self.master)
class mainwindow():#主界面
def __init__(self, master):
self.master = master
self.window = tk.Frame(self.master, bg='#e5ffe5')
self.window.place(x=0,y=0,width=1000,height=600)
self.window.showname_label=tk.Label(self.window,text="黑板模拟器",fg='#26734d', bg='#ffe5ff',font=("Helvetic",60,"bold"),relief=RAISED).place(x=0, y=10,width=1000, height=150)
self.window.enter_btn=tk.Button(self.window,text="开始",bg='#ffffe5',fg='#333399',font=("Helvetic", 60, "bold"),command=self.changetofunction).place(x=360, y=300,width=250, height=150)
def changetofunction(self,):
self.window.destroy()
functionwindow(self.master)
class functionwindow():
def __init__(self, master):
self.master = master
self.init_x=None
self.init_y=None
self.events=[]
self.boardlock=True
self.checklock=0
self.window = tk.Frame(self.master, bg='#e5f9ff')
self.window.place(x=0, y=0, width=1000, height=600)
self.init_canvas()
self.window.enter_btn=tk.Button(self.window,text="清除",bg='#ffffe5',fg='#333399',font=("Helvetic", 60, "bold"),command=self.clean).place(x=360, y=440,width=250, height=150)
鼠标跟踪函数:
def onMouseEvent(event):
return event.Position
def mouse_detector():
global MOUSE_POS
hm = pyHook.HookManager()
hm.MouseAll = onMouseEvent
while True:
MOUSE_POS=list(PyMouse().position())
time.sleep(0.02)
这两个函数用于返回鼠标的位置,用到了pyHook的库。通过一个while循环实现监听,达到对鼠标的位置判断。
点击后鼠标跟踪函数:
def mouse_detector(self):
global MOUSE_POS
self.x = MOUSE_POS[0] - 160 - self.master.winfo_x()
self.y = MOUSE_POS[1] - 82 - self.master.winfo_y()
record=[self.x, self.y]
while self.boardlock:
self.x=MOUSE_POS[0]-160-self.master.winfo_x()
self.y = MOUSE_POS[1] - 82 - self.master.winfo_y()
if record!=[self.x, self.y]:
self.events.append([self.init_x, self.init_y, self.x, self.y])
self.window.angle_canvas.destroy()
self.init_canvas()
time.sleep(0.00001)
record = [self.x, self.y]
self.boardlock = True
当鼠标点击黑板时,需要对鼠标位置进行canvas内部监听以便绘制游离线(即没有确定具体绘制方案的线),在本设计中,黑板元素的变化主要是通过删除重绘画板实现的。这部分的while循环会判断鼠标的位置是否改变,如果没改变则不对画板进行更新操作。
黑板点击调用函数:
def key(self,event):
if self.checklock==0:
self.checklock = 1 - self.checklock
self.init_x = event.x
self.init_y = event.y
boardthread = threading.Thread(target=self.mouse_detector)
boardthread.start()
else:
self.checklock = 1 - self.checklock
self.boardlock = False
self.events.append([self.init_x, self.init_y, self.x, self.y])
当鼠标对黑板进行点击时,会调用此函数。这部分函数主要可以根据当前的状态来选择合适的函数,self.checklock变量有0和1两种数值,不同的数值对应不同的状态和功能,分为开始绘制和绘制完两种状态。self.boardlock变量则可以实现对画板内部while循环的控制。
初始化画布:
def init_canvas(self):
self.window.angle_canvas = tk.Canvas(self.window, bg='#336600')
self.window.angle_canvas.place(x=150,y=50,width=700,height=300)
self.window.angle_canvas.bind("<Button-1>", self.key)
if self.events!=[]:
if self.checklock==0:
for i,item in enumerate(self.events):
if i==len(self.events)-1:
break
self.window.angle_canvas.create_line(item,fill='white')
else:
for i, item in enumerate(self.events):
self.window.angle_canvas.create_line(item, fill='white')
self.events = self.events[:-1]
这部分对黑板进行更新,更新分为开始绘制和绘制完两种状态。
清除按键调用函数:
def clean(self):
if self.checklock==1:
return
self.window.angle_canvas.destroy()
self.events = []
self.init_canvas()
这部分代码是清除案件的调用函数。
最后展示完整代码:
#黑板模拟器
from tkinter import *
from tkinter import messagebox
import tkinter as tk
from pymouse import PyMouse
import pyHook
import threading
import time
import os
MOUSE_POS=None
def onMouseEvent(event):
return event.Position
def mouse_detector():
global MOUSE_POS
hm = pyHook.HookManager()
hm.MouseAll = onMouseEvent
while True:
MOUSE_POS=list(PyMouse().position())
time.sleep(0.02)
class basedesk():#底板
def __init__(self, master):
self.master = master
self.master.title("黑板模拟器")
self.master.configure(bg='#B1FFF9')
self.master.geometry("1000x600")
mainwindow(self.master)
class mainwindow():#主界面
def __init__(self, master):
self.master = master
self.window = tk.Frame(self.master, bg='#e5ffe5')
self.window.place(x=0,y=0,width=1000,height=600)
self.window.showname_label=tk.Label(self.window,text="黑板模拟器",fg='#26734d', bg='#ffe5ff',font=("Helvetic",60,"bold"),relief=RAISED).place(x=0, y=10,width=1000, height=150)
self.window.enter_btn=tk.Button(self.window,text="开始",bg='#ffffe5',fg='#333399',font=("Helvetic", 60, "bold"),command=self.changetofunction).place(x=360, y=300,width=250, height=150)
def changetofunction(self,):
self.window.destroy()
functionwindow(self.master)
class functionwindow():
def __init__(self, master):
self.master = master
self.init_x=None
self.init_y=None
self.events=[]
self.boardlock=True
self.checklock=0
self.window = tk.Frame(self.master, bg='#e5f9ff')
self.window.place(x=0, y=0, width=1000, height=600)
self.init_canvas()
self.window.enter_btn=tk.Button(self.window,text="清除",bg='#ffffe5',fg='#333399',font=("Helvetic", 60, "bold"),command=self.clean).place(x=360, y=440,width=250, height=150)
def mouse_detector(self):
global MOUSE_POS
self.x = MOUSE_POS[0] - 160 - self.master.winfo_x()
self.y = MOUSE_POS[1] - 82 - self.master.winfo_y()
record=[self.x, self.y]
while self.boardlock:
self.x=MOUSE_POS[0]-160-self.master.winfo_x()
self.y = MOUSE_POS[1] - 82 - self.master.winfo_y()
if record!=[self.x, self.y]:
self.events.append([self.init_x, self.init_y, self.x, self.y])
self.window.angle_canvas.destroy()
self.init_canvas()
time.sleep(0.00001)
record = [self.x, self.y]
self.boardlock = True
def key(self,event):
if self.checklock==0:
self.checklock = 1 - self.checklock
self.init_x = event.x
self.init_y = event.y
boardthread = threading.Thread(target=self.mouse_detector)
boardthread.start()
else:
self.checklock = 1 - self.checklock
self.boardlock = False
self.events.append([self.init_x, self.init_y, self.x, self.y])
def init_canvas(self):
self.window.angle_canvas = tk.Canvas(self.window, bg='#336600')
self.window.angle_canvas.place(x=150,y=50,width=700,height=300)
self.window.angle_canvas.bind("<Button-1>", self.key)
if self.events!=[]:
if self.checklock==0:
for i,item in enumerate(self.events):
if i==len(self.events)-1:
break
self.window.angle_canvas.create_line(item,fill='white')
else:
for i, item in enumerate(self.events):
self.window.angle_canvas.create_line(item, fill='white')
self.events = self.events[:-1]
def clean(self):
if self.checklock==1:
return
self.window.angle_canvas.destroy()
self.events = []
self.init_canvas()
if __name__ == '__main__':#主函数
thread = threading.Thread(target=mouse_detector)
thread.start()
root = tk.Tk()
root.resizable(False, False)
basedesk(root)
root.mainloop()
os._exit(0)
|