在 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.

到目前为止我尝试了什么:

有人知道我怎样才能摆脱神器吗?

谢谢!

您可以在 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 看起来仍然更好,但现在它只影响线的末端,正如它应该的那样。