2016-04-14 19 views
2

Yakınım var ama iki sorun var. Biri, döndürülmüş karenin son konumu (artık ortada değil). İkincisi, (..) listesinin bir kopyasını oluşturmama rağmen, orijinal köşe liste mutasyonlarımdır.Tkinter Canvas'da Kare Döndürme

Her zamanki gibi çok takdir edilen herhangi bir yardım.

from Tkinter import * 
import math 


WIDTH = 400 
HEIGHT = 400 
CANVAS_MID_X = WIDTH/2 
CANVAS_MID_Y = HEIGHT/2 
SIDE = WIDTH/4 

root = Tk() 
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 
canvas.pack() 

vertices = [ 
        [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2], 
        [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2], 
        [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2], 
        [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2]] 

def rotate(points, angle): 
    new_points = list(points) 
    rad = angle * (math.pi/180) 
    cos_val = math.cos(rad) 
    sin_val = math.sin(rad) 
    for coords in new_points: 
     x_val = coords[0] 
     y_val = coords[1] 
     coords[0] = x_val * cos_val - y_val * sin_val 
     coords[1] = x_val * sin_val + y_val * cos_val 
    return new_points 

def draw_square(points): 
    canvas.create_polygon(points, fill="red") 

def test(): 
    print "vertices: ", vertices, "should be: ", "[[150, 150], [250, 150], [250, 250], [150, 250]]" 


new_square = rotate(vertices, 30) 
draw_square(new_square) 
test() 
mainloop() 
+0

Sorunlarınızı net bir şekilde açıkladığınız ve bir [kaydı] gönderme gönderdiğiniz için teşekkür ederiz! –

cevap

2

İlk sorunun nedeni, kullandığınız formülün kaynak çevresinde döndürülmesidir. Merkezinin etrafındaki kareyi döndürmek istediğinizi farz ediyorum. Bunu yapmak için, kareyi yalnızca merkezini kökeni çevirir, döndürür, sonra çevirirsiniz.

ikinci sorunu list(points)yapar yapıyor yeni dış liste oluşturmak olduğunu, ancak points içindeki listeleri için yeni liste oluşturmak değil gelmez. Bu iç listeler için yeni listeler oluşturan derin bir kopya oluşturmanın yolları vardır, ancak bunu gerçekten burada yapmanız gerekmez. Sadece döndürülen köşe noktalarından yeni bir liste oluşturun.

Kodunuzun sürümümü, orijinal kareyi mavi olarak çizer, böylece döndürülen karenin doğru konumda kaldığını görebiliriz.

from Tkinter import * 
import math 

WIDTH = 400 
HEIGHT = 400 
CANVAS_MID_X = WIDTH/2 
CANVAS_MID_Y = HEIGHT/2 
SIDE = WIDTH/4 

root = Tk() 
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 
canvas.pack() 

vertices = [ 
    [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2], 
    [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2], 
    [CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2], 
    [CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2], 
] 

def rotate(points, angle, center): 
    angle = math.radians(angle) 
    cos_val = math.cos(angle) 
    sin_val = math.sin(angle) 
    cx, cy = center 
    new_points = [] 
    for x_old, y_old in points: 
     x_old -= cx 
     y_old -= cy 
     x_new = x_old * cos_val - y_old * sin_val 
     y_new = x_old * sin_val + y_old * cos_val 
     new_points.append([x_new + cx, y_new + cy]) 
    return new_points 

def draw_square(points, color="red"): 
    canvas.create_polygon(points, fill=color) 

def test(): 
    old_vertices = [[150, 150], [250, 150], [250, 250], [150, 250]] 
    print "vertices: ", vertices, "should be: ", old_vertices 
    print vertices == old_vertices 

draw_square(vertices, "blue") 

center = (CANVAS_MID_X, CANVAS_MID_Y) 
new_square = rotate(vertices, 30, center) 
test() 
draw_square(new_square) 

mainloop() 

Ayrıca kodunuzda birkaç küçük değişiklik yaptım.

BTW, muhtemelen diğer ithalat önce

from __future__ import division 

yapmalıdır. Bu, Python'a doğru bölümü kullanmasını söyler. Bu olmadan, SIDE/2 tamsayı bölümü yapar. Bu burada çalışıyor, ancak SIDE tek bir sayı ise, doğru olmayacak.


Yerine

from Tkinter import * 

yapma alışkanlığı çıkmaya çalışmalısınız,

import Tkinter as tk 

yapmak ve sonra böyle Tkinter işlevleri çağırmak:

canvas = tk.Canvas(root, bg="black", height=HEIGHT, width=WIDTH) 

Bu biraz daha yazarak, ancak kodun okunmasını ve bakımını kolaylaştırır ve kodunuz Tkinter'in tanımladığı adlardan birini yanlışlıkla kullandığında oluşabilecek hataları önler. FWIW, from Tkinter import * yapıyor, ad alanınıza 170 addan fazla isim aktarıyor. Bu dağınıklığa ihtiyacın yok!

+0

Love it! Teşekkürler. Bu aşamada benim öğrenmemde, bu tür "temellerin ötesinde" cevabı gerçekten çok faydalıdır. – Robin