我在python中创建了一个海龟程序,它在位置(0,0)周围创建了一个色轮。这是一个pastebin:http://pastebin.com/xDyddfwa。我希望能够做到的是,能够点击方向盘上的某个位置,并被告知圆圈周围有多少度我点击的颜色。所以基本上,我想要圆形图坐标,而不是笛卡尔坐标。如果您运行了色轮程序,它会提示您输入一个数字。如果输入6,它将绘制一个六色轮。你会看到红色位于右下角。我希望能够点击它,然后得到0.然后,如果我点击黄色,我会得到1,等等。另外,我怎么能将该值存储到变量。 (我在使用onclick()时遇到了麻烦)请帮忙。
答案 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
在后台使用tkinter
,tkinter
更强大 - 即。它具有绘制arc
,pieslice
等功能 - 您可以将鼠标单击指定给画布上的每个对象。
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以简化代码并使其仅在您单击色轮本身时响应,而不仅仅是在窗口中的任何位置。