如何获得点击位置的圆形图坐标

时间:2017-01-28 02:17:11

标签: python onclick turtle-graphics

我在python中创建了一个海龟程序,它在位置(0,0)周围创建了一个色轮。这是一个pastebin:http://pastebin.com/xDyddfwa。我希望能够做到的是,能够点击方向盘上的某个位置,并被告知圆圈周围有多少度我点击的颜色。所以基本上,我想要圆形图坐标,而不是笛卡尔坐标。如果您运行了色轮程序,它会提示您输入一个数字。如果输入6,它将绘制一个六色轮。你会看到红色位于右下角。我希望能够点击它,然后得到0.然后,如果我点击黄色,我会得到1,等等。另外,我怎么能将该值存储到变量。 (我在使用onclick()时遇到了麻烦)请帮忙。

2 个答案:

答案 0 :(得分:0)

onclick()仅在您点击乌龟时才有效。使用onscreenclick(callback)在每次点击时执行功能。它会为您(x,y),因此您必须以度数计算angle,然后将角度转换为正确的数字。它并不理想,因为它计算屏幕上每次点击的数量,而不仅仅是颜色。

import turtle
from turtle import *
import colorsys
import math

def arch(radius, degree, width, colour):
    color(colour)
    pd()
    begin_fill()
    circle(radius, degree)
    lt(90)
    fd(width)
    lt(90)
    circle(-radius+width, degree)
    lt(90)
    fd(width)
    lt(90)
    end_fill()
    pu()
    circle(radius, degree)
    pd()

def start():
    pu()
    rt(90)
    fd(200)
    lt(90)

def startover():
    reset()
    main()

def get_number(x, y):
    # inform function to use global variable
    #global k

    angle = 180 - math.degrees(math.atan2(x,y))

    angle %= 360

    number = int(angle*k/360)

    print('Pos:', x, y, 'Angle:', angle, 'Number:', number)

def main():
    # Inform function to use global variable when you use `=`
    # You will need this value in `get_number
    global k

    s = turtle.Screen()
    #t = turtle.Turtle()

    s.colormode(255)
    tracer(False)

    reset()
    start()

    k = int(numinput(""," How many colors?"))

    colorlist = []

    for i in range(k):
        colorlist.append(list(colorsys.hsv_to_rgb(i/k,1,255)))

    print(colorlist)

    for i in range(len(colorlist)):
        for j in range(len(colorlist[i])):
            colorlist[i][j] = int(colorlist[i][j])
        arch(200, 360/k, 100, (colorlist[i]))

    onkey(startover, "a")
    onscreenclick(get_number)
    #listen()

    done()

if __name__ == "__main__":
    main()

编辑: turtle在后​​台使用tkintertkinter更强大 - 即。它具有绘制arcpieslice等功能 - 您可以将鼠标单击指定给画布上的每个对象。

import turtle
from turtle import *
import colorsys

def get_number(event, number):
    #print('widget:', event.widget)
    print('number:', number)

def main():

    s = turtle.Screen()

    s.colormode(255)

    k = int(numinput("","How many colors?"))

    colorlist = []

    for i in range(k):
        color = colorsys.hsv_to_rgb(i/k,1,255)
        color = (int(color[0]), int(color[1]), int(color[2]))
        colorlist.append(color)

    canvas = s.getcanvas()

    for i in range(len(colorlist)):
        # convert (255, 255, 255) into '#ffffff'
        color = s._colorstr(colorlist[i])

        # create `arc`
        part_id = canvas.create_arc(-200, -200, 200, 200, outline=color, start=(i*360/k)-90, extent=360/k, width=100, style='arc')

        # assign button click to this part with `number`
        canvas.tag_bind(part_id, '<Button>', lambda event, number=i:get_number(event, number))

    done()

if __name__ == "__main__":
    main()

effbot.org:The Tkinter Canvas Widget

答案 1 :(得分:0)

我觉得根据OP的代码得出的另一个答案是,在产生不正确的结果时,问题会比必要的更复杂。下面是我尝试简化逻辑并产生正确的值(例如红色为0,黄色为1等,在6段HSB圆上。)我将圆圈旋转了90度,使数学运算更好。此外,结果打印在圆圈的中心:

from turtle import Turtle, Screen
from colorsys import hsv_to_rgb
import math

FONT_SIZE = 18
FONT = ('Arial', FONT_SIZE, 'normal')

RADIUS = 200
WIDTH = 100

last_result = ()  # Also how could I store that value to a variable?

def arch(radius, width, colorlist):

    ''' Creates a color wheel around position (0,0) '''

    degree = 360 / len(colorlist)
    inner_radius = radius - width

    turtle = Turtle(visible=False)
    turtle.penup()
    turtle.setx(radius)
    turtle.setheading(90)

    for color in colorlist:
        turtle.color(color)

        turtle.begin_fill()
        turtle.circle(radius, degree)
        position = turtle.position()
        heading = turtle.heading()
        turtle.left(90)
        turtle.forward(width)
        turtle.left(90)
        turtle.circle(-inner_radius, degree)
        turtle.end_fill()

        turtle.setposition(position)
        turtle.setheading(heading)

def get_number(x, y, turtle, segments):

    '''
    Click somewhere on the wheel, and be told how many degrees around the
    circle the color you clicked. For a six-color wheel, if you click on
    red, you get 0. If you click on yellow, you get 1, etc.
    '''

    global last_result

    if (RADIUS - WIDTH) ** 2 < x ** 2 + y ** 2 < RADIUS ** 2:

        angle = math.degrees(math.atan2(y, x)) % 360

        number = int(angle * segments / 360)

        turtle.undo()
        turtle.write('{} ({:5.1f}\u00b0)'.format(number, angle), align='center', font=FONT)

        last_result = (number, angle)

def main():

    screen = Screen()

    segments = int(screen.numinput('Color Wheel', 'How many colors?'))

    colorlist = [hsv_to_rgb(i / segments, 1.0, 1.0) for i in range(segments)]

    screen.tracer(False)
    arch(RADIUS, WIDTH, colorlist)
    screen.tracer(True)

    magic_marker = Turtle(visible=False)
    magic_marker.penup()
    magic_marker.sety(-FONT_SIZE/2)
    magic_marker.write('', align='center', font=FONT)

    screen.onscreenclick(lambda x, y, t=magic_marker, s=segments: get_number(x, y, t, s))

    screen.mainloop()

if __name__ == '__main__':
    main()

我已经将颜色逻辑更改为0.0到1.0以简化代码并使其仅在您单击色轮本身时响应,而不仅仅是在窗口中的任何位置。

enter image description here