在 tkinter 上画一条粗曲线 Canvas
Draw a THICK curve on a tkinter Canvas
我想使用 tkinter Canvas 对象在屏幕上绘制手写体。使用 example code from the tkdocs website,当我使用 20 的大线宽时,我得到以下绘图工件:
然而,对于小线宽,一切都很好:
这是完整的 Python 代码:
from tkinter import *
from tkinter import ttk
class Sketchpad(Canvas):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.bind("<Button-1>", self.save_posn)
self.bind("<B1-Motion>", self.add_line)
def save_posn(self, event):
self.lastx, self.lasty = event.x, event.y
def add_line(self, event):
self.create_line((self.lastx, self.lasty, event.x, event.y))
self.save_posn(event)
root = Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
sketch = Sketchpad(root)
sketch.grid(column=0, row=0, sticky=(N, W, E, S))
root.mainloop()
我正在使用 Python 3.8.
到目前为止我尝试了什么:
- 不同的连接样式没有效果
- smooth 参数无效
- 不值得一提的各种不成功的肮脏黑客和解决方法
有人知道我怎样才能摆脱神器吗?
谢谢!
您可以在 create_line()
中使用 capstyle='round'
:
self.create_line((self.lastx, self.lasty, event.x, event.y), width=20, capstyle='round')
您正在为每个 <B1-Motion>
事件创建一条新线,而不是向每个新点延伸一条线。因此,每条新的线都不知道之前的线,也没有努力很好地连接所有点。对于较细的线条,您不会注意到这一点,但如果您仔细观察,您实际上也可以在您显示的细线的弯曲处看到它。
您可以使用圆形帽样式使问题不可见,因为大写填满了行之间的所有 space,但对我来说,只创建一条线并通过创建更新其坐标会更有意义<Button-1>
上的一行并在 <B1-Motion>
上扩展它:
from tkinter import *
from tkinter import ttk
class Sketchpad(Canvas):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.bind("<Button-1>", self.new_line)
self.bind("<B1-Motion>", self.add_to_line)
def new_line(self, event):
self.points = [event.x, event.y]
self.line = self.create_line(event.x, event.y, event.x, event.y, width=20, capstyle=ROUND)
def add_to_line(self, event):
self.points.extend([event.x, event.y])
self.coords(self.line, *self.points)
root = Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
sketch = Sketchpad(root)
sketch.grid(column=0, row=0, sticky=(N, W, E, S))
root.mainloop()
请注意,使用圆形 capstyle
看起来仍然更好,但现在它只影响线的末端,正如它应该的那样。
我想使用 tkinter Canvas 对象在屏幕上绘制手写体。使用 example code from the tkdocs website,当我使用 20 的大线宽时,我得到以下绘图工件:
然而,对于小线宽,一切都很好:
这是完整的 Python 代码:
from tkinter import *
from tkinter import ttk
class Sketchpad(Canvas):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.bind("<Button-1>", self.save_posn)
self.bind("<B1-Motion>", self.add_line)
def save_posn(self, event):
self.lastx, self.lasty = event.x, event.y
def add_line(self, event):
self.create_line((self.lastx, self.lasty, event.x, event.y))
self.save_posn(event)
root = Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
sketch = Sketchpad(root)
sketch.grid(column=0, row=0, sticky=(N, W, E, S))
root.mainloop()
我正在使用 Python 3.8.
到目前为止我尝试了什么:
- 不同的连接样式没有效果
- smooth 参数无效
- 不值得一提的各种不成功的肮脏黑客和解决方法
有人知道我怎样才能摆脱神器吗?
谢谢!
您可以在 create_line()
中使用 capstyle='round'
:
self.create_line((self.lastx, self.lasty, event.x, event.y), width=20, capstyle='round')
您正在为每个 <B1-Motion>
事件创建一条新线,而不是向每个新点延伸一条线。因此,每条新的线都不知道之前的线,也没有努力很好地连接所有点。对于较细的线条,您不会注意到这一点,但如果您仔细观察,您实际上也可以在您显示的细线的弯曲处看到它。
您可以使用圆形帽样式使问题不可见,因为大写填满了行之间的所有 space,但对我来说,只创建一条线并通过创建更新其坐标会更有意义<Button-1>
上的一行并在 <B1-Motion>
上扩展它:
from tkinter import *
from tkinter import ttk
class Sketchpad(Canvas):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.bind("<Button-1>", self.new_line)
self.bind("<B1-Motion>", self.add_to_line)
def new_line(self, event):
self.points = [event.x, event.y]
self.line = self.create_line(event.x, event.y, event.x, event.y, width=20, capstyle=ROUND)
def add_to_line(self, event):
self.points.extend([event.x, event.y])
self.coords(self.line, *self.points)
root = Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
sketch = Sketchpad(root)
sketch.grid(column=0, row=0, sticky=(N, W, E, S))
root.mainloop()
请注意,使用圆形 capstyle
看起来仍然更好,但现在它只影响线的末端,正如它应该的那样。