2017-01-28 16 views
0

Ich habe ein Turtle-Programm in Python erstellt, das ein Farbrad um die Position (0,0) erstellt. Hier ist ein Pastebin: http://pastebin.com/xDyddfwa. Was ich gerne tun könnte, ist in der Lage zu sein, irgendwo auf das Rad zu klicken, und mir wird gesagt, um wie viele Grad um den Kreis die Farbe, die ich geklickt habe, ist. Im Grunde genommen möchte ich anstelle von kartesischen Koordinaten kreisförmige Koordinaten verwenden. Wenn Sie das Farbradprogramm ausführen, werden Sie aufgefordert, eine Zahl einzugeben. Wenn Sie 6 eingeben, wird ein sechsfarbiges Rad gezeichnet. Sie werden sehen, dass Rot unten rechts ist. Ich möchte in der Lage sein, darauf zu klicken und 0 zu erhalten. Wenn ich dann auf das Gelbe klicke, würde ich 1 usw. bekommen. Wie könnte ich diesen Wert auch in einer Variablen speichern? (Ich habe Probleme mit onclick()) Bitte helfen.So erhalten Sie kreisförmige Koordinaten einer angeklickten Position

+1

immer in Frage gestellt Code und vollständige Fehlermeldung. – furas

+0

um dies außerhalb 'IDLE' auszuführen, brauchen Sie' done() 'oder' hauptroup() '. 'turtle' und' IDLE' benutzen 'tkinter', die' hauptroup() 'benötigen, um zu funktionieren. Wenn Sie in 'IDLE' laufen, dann führt es einen eigenen' hauptrhuf() 'aus und dieser Code funktioniert - aber außerhalb von IDLE wird kein Kreis gezeichnet. – furas

+0

Code besser lesbar zu machen verwenden: leere Zeile vor 'def 'und' if __name__', Leerzeichen nach Komma. Mehr: [PEP 8 - Style Guide für Python-Code] (https://www.python.org/dev/peps/pep-0008/) – furas

Antwort

0

onclick() funktioniert nur, wenn Sie auf Schildkröte klicken. Verwenden Sie onscreenclick(callback), um die Funktion bei jedem Klick auszuführen. Es gibt (x,y) so müssen Sie angle in Grad berechnen und dann Winkel in die richtige Zahl umwandeln. Es ist nicht ideal, weil es die Anzahl für jeden Klick auf dem Bildschirm berechnet, nicht nur für Farben.

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() 

EDIT:turtle verwendet tkinter im Hintergrund, und tkinter ist mächtiger - dh. Es hat Funktionen zum Zeichnen arc, pieslice usw. - und Sie können jedem Objekt auf der Leinwand Mausklick zuordnen.

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

+0

Ich glaube, dass dies falsche Ergebnisse produziert - basierend auf der Beschreibung des OP des Problems Bei einem Rad mit sechs Segmenten sollte die Farbe Rot zwischen 0 Grad und 60 Grad, nicht 120 Grad und 180 Grad liegen, da dies auf die Konsole gedruckt wird. Auch Rot sollte die Nummer 0 sein, nicht 2 und 3, wie es hier ist. – cdlane

+0

@cdlane du hast recht :) Ich habe die Farben nicht geprüft, ich habe Standardsystem mit 0 Grad oben erwartet. Aber mit kleinen Modifikationen funktioniert es besser. – furas

+0

Ich habe ein Beispiel mit 'canvas' von' tkinter' hinzugefügt. – furas

0

Ich fühle mich die andere Antwort, basierend auf dem Code des OP, das Problem komplizierter als nötig macht, während falsche Ergebnisse erzeugen. Unten ist mein Versuch, die Logik zu vereinfachen und korrekte Werte zu erzeugen (z. B. ist Rot 0, Gelb ist 1 usw. auf einem 6-Segment-HSB-Kreis). Ich habe den Kreis um 90 Grad gedreht, um die Mathe besser auszurichten. Außerdem werden die Ergebnisse in der Mitte des Kreises gedruckt:

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() 

ich die Farbe Logik auf 0,0 bis 1,0 geändert haben den Code zu vereinfachen und machte es nur reagieren, wenn Sie auf dem Farbrad klicken selbst, nicht nur irgendwo im Fenster.

enter image description here

+0

Vielen Dank für die Beantwortung meiner Frage! Ich wünschte, ich könnte so programmieren. Hat mir so sehr geholfen! –

+0

Ich habe eine andere Frage. Wie kann ich mit dem Bildschirmclick() aufhören zu hören. Ich möchte in der Lage sein, zweimal zu klicken, diese zwei Zahlen zu erhalten und dann zu einer anderen Funktion oder etwas anderem weiterzugehen.FTR: Ich habe es selbst versucht und recherchiert, konnte aber wie immer nichts finden. Jede weitere Hilfe wäre sehr willkommen. –

+0

@JoshHenderson, wie die meisten Turtle-Event-Handler, liefert 'None', da der Event-Handler es ausschaltet:' screen.onscreenclick (None) 'Dies ist in der Python-Turtle-Dokumentation beschrieben, die mit einer einfachen Websuche leicht zu finden ist. – cdlane

Verwandte Themen