如何在 tkinter 中围绕原点(将是光标)制作线条

How to make lines around the origin(will be cursor) in tkinter

我打算做的是制作 360 条线,每条线都指向不同的角度,并且都围绕光标 所以第 1 行将在角度 1 中,而第 2 行将在角度 2 中 我希望它围绕光标

def redraw(event):
    cv.delete("all")
    length = 100
    xorigin = event.x - 250
    yorigin = event.y - 250


    newx = (xorigin - 500)*numpy.cos(45 * numpy.pi / 360)
    newy = (xorigin - 250)*numpy.sin(45 * numpy.pi / 360)
    cv.create_line(xorigin+250,yorigin+250,newx,newy, fill="red")

我试着把它做成一条线进行测试,但这条线不是我想要的角度 + 原点(光标)有点坏了 所以基本上我想做的是: enter image description here

所以光标会像圆圈一样

我找到了解决办法!我将通读并解释代码(和数学),但如果您想跳过所有这些,底部将提供一个工作示例。


numpy.cosnumpy.sin 使用弧度,而不是度数

这会引起一些混乱:您需要度数,但得到的值不正确,因为这些函数计算的是弧度。那么,要使用弧度函数来计算度数,您需要 multiply your degrees argument by /180。因此,调用带有度数的 sin()cos() 函数将如下所示:

# Calculate the cosine of 45° like this: cos (45 * ( / 180))°
degrees = 45
numpy.cos(degrees*(numpy.pi/180))

# Calculate the sine of 45° like this: sin (45 * ( / 180))°
degrees = 45
numpy.sin(degrees*(numpy.pi/180))

从鼠标位置获取线坐标

让我们把你的线想象成一个直角三角形,其中点A是鼠标的位置,点B是另一个线的末端,anglea是线相对于x-axis的角度,sideh是你要的线draw,而h本身就代表线的长度:

   B
    |\
    | \
    |  \
    |   \ h
  y |    \
    |     \
    |      \
    |_   a° \ 
    |_|______\
        x     A

您已经有了 A(x, y) 坐标:xoriginyoriginB(x, y) 坐标只是从 A 的坐标中减去三角形每条边的长度。

也就是说,Bx = Ax - x, 和 By = Ay - y.

但是我们如何得到xy呢?好吧,我们知道 cos a° = x / h,所以我们可以求解 x,得到x = h * cos a°。对 siny 做同样的事情,我们得到 y = h * sin a°.

在 Python

中应用这些公式

好吧,让我们把这些公式转换成有效的Python!在美妙的计算机想象世界中,直角三角形可以有任意大小的角度测量值,因此我们无需担心给出的角度测量值太大。

为简单起见,我们将创建我们自己的 sin()cos() 函数来自动将度数转换为弧度:

def cos(degrees):
    return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
    return numpy.sin(degrees*(numpy.pi/180))

在这里,我们应用公式 Bx = Ax - x, 和 By = Ay - y,替换 xyh * cos a°h * sin a°,分别为:

newx = xorigin - (length * cos(d))
newy = yorigin - (length * sin(d))

其中 d 是从边 x 开始并顺时针旋转的任意度数。


综合起来

现在来一个演示程序。你在你的问题中提到你想创建一个完整的线圈:好吧,这个程序就是这样做的。它遍历所有度数并在每个角度测量处画一条线,从 1° 开始一直延伸到 360°。

请记住,度数从 x-axis 的左半部分开始,因此角度测量值为 1° 的线将如下所示:

import numpy, tkinter

root = tkinter.Tk()

canvas = tkinter.Canvas(root)
canvas.pack(expand=True, fill="both")

def cos(degrees):
    return numpy.cos(degrees*(numpy.pi/180))
def sin(degrees):
    return numpy.sin(degrees*(numpy.pi/180))

def redraw(event):
    canvas.delete("all")
    length = 100
    xorigin = event.x
    yorigin = event.y

    # Loop through all the degrees of the circle, drawing a line for each one
    for d in range(0, 360):
        newx = xorigin - (length * cos(d))
        newy = yorigin - (length * sin(d))

        canvas.create_line(xorigin, yorigin, newx, newy, fill="red")

canvas.bind("<Motion>", redraw)

root.mainloop()

希望这对您有所帮助,如果您对此答案有任何疑问,请告诉我!