Python Tkinter 连续线段端点不对齐

1 投票
2 回答
1145 浏览
提问于 2025-04-16 20:10

基本上,我想创建一条连续的线(从用户点击开始,到右键点击结束)。这个功能我已经实现了,但不知为什么,线的两端(椭圆形的点)和线的边缘并没有完全对齐(当你尝试用多个点画一条直线或者画直角时,这个问题就特别明显)。我几乎尝试了所有的方法,感到非常沮丧,所以我在这里发帖看看大家有没有什么建议。

这是代码,你可以试试看,了解我说的问题:

from Tkinter import *

class GUI:
    def __init__(self,root):
        Window = Frame(root)
        self.DrawArea = Canvas(Window)
        self.DrawArea.pack()
        Window.pack()

        self.linewidth = 20

        self.DrawArea.config(cursor="crosshair")
        self.DrawArea.bind("<Button 1>",self.startline)


    def startline(self,event):
        self.startx, self.starty = self.DrawArea.canvasx(event.x),self.DrawArea.canvasy(event.y)

        xa,ya = self.startx-self.linewidth/2 , self.starty+self.linewidth/2
        xb,yb = self.startx+self.linewidth/2 , self.starty-self.linewidth/2

        self.StartPoint = self.DrawArea.create_oval(xa,ya,xb,yb,fill='red',outline='')
        self.Line = None
        self.EndPoint = None

        self.DrawArea.bind("<Motion>",self.updateline)
        self.DrawArea.bind("<Button 3>",self.killline)

    def updateline(self,event):
        if self.EndPoint: self.DrawArea.delete(self.EndPoint)
        if self.Line: self.DrawArea.delete(self.Line)

        x,y = self.DrawArea.canvasx(event.x),self.DrawArea.canvasy(event.y)
        xa,ya = x-self.linewidth/2 , y+self.linewidth/2
        xb,yb = x+self.linewidth/2 , y-self.linewidth/2

        self.Line = self.DrawArea.create_line(self.startx,self.starty,x,y,fill='red',width=self.linewidth)
        self.EndPoint = self.DrawArea.create_oval(xa,ya,xb,yb,fill='red',outline='')

    def killline(self,event):
        self.DrawArea.delete(self.Line)
        self.DrawArea.delete(self.StartPoint)
        self.DrawArea.delete(self.EndPoint)
        self.DrawArea.unbind("<Motion>")


if __name__ == '__main__':
    root = Tk()
    root.title("Line Draw")
    App = GUI(root)
    root.mainloop()

2 个回答

1

在我的屏幕上,以及我用的Python版本(Windows XP上的2.5),如果你使用奇数个像素作为线条的宽度,圆圈和线条就能很好地配合,至少在我尝试过的宽度中是这样的。我觉得这是因为你的坐标并不是数学上理想的零维点,而是对应于像素。所以,最小宽度的点或线是一个像素宽。而你的光标就“住”在这个地方。为了让线条看起来更粗且更平衡,你需要在这个最小宽度的两边各加上相同数量的像素;因此,总宽度必须是奇数个像素。

2

与其在线条的末端画圆圈,你可以使用 capstylejoinstyle 这两个选项来设置线条的样式。

比如说:

self.Line = self.DrawArea.create_line(self.startx,self.starty, x, y, fill='red',
    width=self.linewidth, capstyle=ROUND, joinstyle=ROUND)

撰写回答