-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
192 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,191 +1,139 @@ | ||
import wx | ||
from tkinter import * | ||
from tkinter import messagebox | ||
from tkinter.colorchooser import askcolor | ||
|
||
win_width = 800 | ||
win_height = 650 | ||
bgcolor = '#ffffff' | ||
|
||
# 原参考代码:https://blog.csdn.net/weixin_44252933/article/details/122296987 | ||
|
||
BUFFERED = True # 使用缓冲法,即 double buffered | ||
# BUFFERED = False # 使用直接法 | ||
|
||
class Myline(): | ||
"""笔画类,包含笔迹的颜色、粗细、样式、数据点""" | ||
def __init__(self, color, thick, style, datas): | ||
self.pen_msg = (color, thick, style) | ||
self.datas = datas | ||
|
||
class SimpleSketchWindow(wx.Window): | ||
"""画板缓冲窗口""" | ||
def __init__(self, *args, **kw): | ||
super().__init__(*args, **kw, size=(800,600)) | ||
|
||
self.cur_pos = (0,0) # 当前鼠标位置 | ||
self.cur_line = [] # 当前笔画 [(x1, y1), (x2, y2), ... ,(xn,yn)] | ||
self.lines = [] # 所有笔画 [line1, line2, ..., line m] | ||
|
||
self.pen_color = 'BLACK' # 笔迹颜色 | ||
self.pen_thick = 4 # 笔迹粗细 | ||
self.pen_style = wx.PENSTYLE_SOLID # 笔类型 | ||
|
||
# 设置缓存区 | ||
if BUFFERED: | ||
self.buffer = None | ||
self.InitBuffer() | ||
|
||
# 设置背景颜色 | ||
self.SetBackgroundColour('white') | ||
# 设置鼠标图标为“铅笔” | ||
self.SetCursor(wx.Cursor(wx.CURSOR_PENCIL)) | ||
|
||
# 绑定事件 | ||
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) | ||
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) | ||
self.Bind(wx.EVT_MOTION, self.OnMotion) | ||
self.Bind(wx.EVT_PAINT, self.OnPaint) # 触发时机:窗口大小变换 | ||
self.Bind(wx.EVT_SIZE, self.OnSize) | ||
|
||
|
||
|
||
|
||
|
||
def InitBuffer(self): | ||
"""初始化缓冲区""" | ||
if BUFFERED: | ||
# 设置缓冲区与窗口的大小一致 | ||
size = self.GetClientSize() | ||
self.buffer = wx.Bitmap(*size) | ||
# 第一个参数为None,相当于初始化 buffer | ||
dc = wx.BufferedDC(None, self.buffer) | ||
else: | ||
# 直接获得当前窗口的设别上下文 | ||
dc = wx.ClientDC(self) | ||
|
||
# 默认的绘画:绘制已存在的笔迹 | ||
self.DefaultDrawing(dc) | ||
|
||
# 添加你的绘画 | ||
self.DoMyDrawing(dc) | ||
|
||
def DefaultDrawing(self, dc:wx.DC): | ||
"""默认绘画""" | ||
|
||
# 设置背景颜色 | ||
dc.SetBackground(wx.Brush(self.GetBackgroundColour())) | ||
dc.Clear() # 使用当前背景刷来清除设备上下文。 | ||
|
||
# 绘制所有的笔画 | ||
self.DrawAllLines(dc) | ||
|
||
def DrawAllLines(self, dc:wx.DC): | ||
"""绘制所有的直线""" | ||
for line in self.lines: | ||
# 设置笔画 | ||
pen = wx.Pen(*line.pen_msg) | ||
dc.SetPen(pen) | ||
# 绘制直线 | ||
for i in range(1, len(line.datas)): | ||
coord = (line.datas[i-1].x, line.datas[i-1].y, | ||
line.datas[i].x, line.datas[i].y) | ||
dc.DrawLine(*coord) | ||
|
||
def DoMyDrawing(self, dc:wx.DC): | ||
"""需要继承此类,然后重构此函数""" | ||
pass | ||
|
||
# ==================================================================== | ||
# 事件响应函数 | ||
# ==================================================================== | ||
def OnSize(self, event): | ||
"""响应窗口大小改变""" | ||
|
||
# 每次窗口大小变换,都需要重新设置缓冲区大小 | ||
self.InitBuffer() | ||
|
||
print("OnSize") | ||
event.Skip() | ||
|
||
def OnPaint(self, event): | ||
"""响应Paint Event""" | ||
|
||
if BUFFERED: | ||
wx.BufferedPaintDC(self, self.buffer) | ||
else: | ||
dc = wx.PaintDC(self) | ||
# 重新绘制 | ||
self.DefaultDrawing(dc) | ||
self.DoMyDrawing(dc) | ||
|
||
print("OnPaint") | ||
event.Skip() | ||
|
||
def OnLeftDown(self, event:wx.MouseEvent): | ||
"""鼠标左键按下,记录起始坐标""" | ||
|
||
# 获得当前鼠标位置 | ||
self.cur_pos = event.GetPosition() | ||
# 新笔画的起点 | ||
self.cur_line = [] | ||
self.cur_line.append(self.cur_pos) | ||
|
||
print("Left Down: (%d, %d)" % (self.cur_pos.x, self.cur_pos.y)) | ||
event.Skip() | ||
|
||
def OnLeftUp(self, event:wx.MouseEvent): | ||
"""鼠标左键松开,记录当前笔画""" | ||
|
||
if len(self.cur_line) > 1: | ||
self.lines.append(Myline( | ||
self.pen_color, self.pen_thick, self.pen_style, self.cur_line)) | ||
|
||
print("Left Up: (%d, %d)" % (self.cur_pos.x, self.cur_pos.y)) | ||
event.Skip() | ||
|
||
def OnMotion(self, event:wx.MouseEvent): | ||
"""鼠标移动(左键拖动)""" | ||
if event.Dragging() and event.LeftIsDown(): | ||
# 更新鼠标的坐标 | ||
pre_pos = self.cur_pos | ||
self.cur_pos = event.GetPosition() | ||
self.cur_line.append(self.cur_pos) | ||
# 设置缓冲区 | ||
if BUFFERED: | ||
# 设置缓冲区,当dc销毁时,将 buffer 复制到当前窗口上 | ||
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) | ||
else: | ||
# 直接获得当前窗口的设别上下文 | ||
dc = wx.ClientDC(self) | ||
# 绘制直线 | ||
pen = wx.Pen(self.pen_color, self.pen_thick, self.pen_style) | ||
dc.SetPen(pen) | ||
coord = (pre_pos.x, pre_pos.y, self.cur_pos.x, self.cur_pos.y) | ||
dc.DrawLine(*coord) | ||
|
||
print("Drawing:", coord) | ||
|
||
event.Skip() | ||
|
||
|
||
class SketchWindow(SimpleSketchWindow): | ||
|
||
def __init__(self, *args, **kw): | ||
super().__init__(*args, **kw) | ||
|
||
def DoMyDrawing(self, dc: wx.DC): | ||
"""绘制自定义内容""" | ||
|
||
|
||
|
||
class Paint(Frame): | ||
"""一个经典的GUI写法""" | ||
|
||
def __init__(self, master=None): | ||
"""初始化方法""" | ||
super().__init__(master) # 调用父类的初始化方法 | ||
self.x = 0 | ||
self.y = 0 | ||
self.fgcolor = 'black' | ||
self.lastdraw = 0 | ||
self.start_flag = False | ||
self.master = master | ||
self.pack() | ||
self.createWidget() | ||
|
||
def createWidget(self): | ||
"""创建画图区域""" | ||
self.drawpad = Canvas(self, width=win_width, height=win_height, bg=bgcolor) | ||
self.drawpad.pack() | ||
# 创建按钮 | ||
self.btn_start = Button(self, name='start', text='开始') | ||
self.btn_start.pack(side='left', padx=10) | ||
self.btn_pen = Button(self, name='pen', text='画笔') | ||
self.btn_pen.pack(side='left', padx=10) | ||
self.btn_rect = Button(self, name='rect', text='矩形') | ||
self.btn_rect.pack(side='left', padx=10) | ||
self.btn_clear = Button(self, name='clear', text='清屏') | ||
self.btn_clear.pack(side='left', padx=10) | ||
self.btn_erasor = Button(self, name='erasor', text='橡皮擦') | ||
self.btn_erasor.pack(side='left', padx=10) | ||
self.btn_line = Button(self, name='line', text='直线') | ||
self.btn_line.pack(side='left', padx=10) | ||
self.btn_line_arrow = Button(self, name='line_arrow', text='箭头直线') | ||
self.btn_line_arrow.pack(side='left', padx=10) | ||
self.btn_color = Button(self, name='color', text='颜色') | ||
self.btn_color.pack(side='left', padx=10) | ||
self.btn_quit = Button(self, name='quit', text='退出') | ||
self.btn_quit.pack(side='left', padx=10) | ||
# 绑定事件 | ||
self.btn_line.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_line_arrow.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_rect.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_pen.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_erasor.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_clear.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_color.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.btn_quit.bind('<Button-1>', self.eventManager) # 点击按钮事件 | ||
self.master.bind('<KeyPress-r>', self.hotKey) # 绑定快捷键 | ||
self.master.bind('<KeyPress-g>', self.hotKey) # 绑定快捷键 | ||
self.master.bind('<KeyPress-b>', self.hotKey) # 绑定快捷键 | ||
self.master.bind('<KeyPress-y>', self.hotKey) # 绑定快捷键 | ||
self.master.bind('<KeyPress-q>', self.hotKey) # 绑定快捷键 | ||
self.drawpad.bind('<ButtonRelease-1>', self.stopDraw) # 左键释放按钮 | ||
|
||
def eventManager(self, event): | ||
name = event.widget.winfo_name() | ||
print(name) | ||
self.start_flag = True | ||
if name == 'line': | ||
# 左键拖动 | ||
self.drawpad.bind('<B1-Motion>', self.myline) | ||
elif name == 'line_arrow': | ||
self.drawpad.bind('<B1-Motion>', self.myline_arrow) | ||
elif name == 'rect': | ||
self.drawpad.bind('<B1-Motion>', self.myrect) | ||
elif name == 'pen': | ||
self.drawpad.bind('<B1-Motion>', self.mypen) | ||
elif name == 'erasor': | ||
self.drawpad.bind('<B1-Motion>', self.myerasor) | ||
elif name == 'clear': | ||
self.drawpad.delete('all') | ||
elif name == 'color': | ||
c = askcolor(color=self.fgcolor, title='请选择颜色') | ||
print(c) # c的值 ((128.5, 255.99609375, 0.0), '#80ff00') | ||
self.fgcolor = c[1] | ||
elif name == 'quit': | ||
quit() | ||
|
||
def startDraw(self, event): | ||
self.drawpad.delete(self.lastdraw) | ||
if self.start_flag: | ||
self.start_flag = False | ||
self.x = event.x | ||
self.y = event.y | ||
|
||
def stopDraw(self, event): | ||
self.start_flag = True | ||
self.lastdraw = 0 | ||
|
||
def myline(self, event): | ||
self.startDraw(event) | ||
self.lastdraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor) | ||
|
||
def myline_arrow(self, event): | ||
self.startDraw(event) | ||
self.lastdraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, arrow=LAST, fill=self.fgcolor) | ||
|
||
def myrect(self, event): | ||
self.startDraw(event) | ||
self.lastdraw = self.drawpad.create_rectangle(self.x, self.y, event.x, event.y, outline=self.fgcolor) | ||
|
||
def mypen(self, event): | ||
self.startDraw(event) | ||
print('self.x=', self.x, ',self.y=', self.y) | ||
self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor) | ||
self.x = event.x | ||
self.y = event.y | ||
|
||
def myerasor(self, event): | ||
self.startDraw(event) | ||
print('self.x=', self.x, ',self.y=', self.y) | ||
self.drawpad.create_line(self.x, self.y, event.x, event.y, fill='white') | ||
self.x = event.x | ||
self.y = event.y | ||
|
||
def hotKey(self, event): | ||
c = event.char | ||
if c == 'r': | ||
self.fgcolor = 'red' | ||
elif c == 'g': | ||
self.fgcolor = 'green' | ||
elif c == 'b': | ||
self.fgcolor = 'blue' | ||
elif c == 'y': | ||
self.fgcolor = 'yellow' | ||
|
||
class SketchFrame(wx.Frame): | ||
|
||
def __init__(self): | ||
super().__init__(parent=None, id=-1, | ||
title="白板", | ||
size=(800,600) | ||
) | ||
|
||
|
||
self.sketch = SketchWindow(parent=self, id=-1) | ||
|
||
# 窗口居中 | ||
self.Center() | ||
|
||
|
Oops, something went wrong.