2016-03-01 347 views
1

我在製作一個Rubik的幻燈片遊戲。基本上,4個方格可以移動的動作是右,左,上,下,順時針,逆時針。用tkinter在畫布上旋轉形狀(python 3)

我正在做的第一個按鈕/移動是順時針。按鈕使所有的方塊順時針平移一次,但是我怎樣才能使它每次按下時都能保持移位?

順時針方向移動是第一個功能,然後按順時針方向按鈕調用。

從Tkinter的進口* 從Tkinter的進口TTK

# --- Functions --- 

def clockwise_move(): 
    canvas.coords(square1, 500, 2, 250, 250) 
    canvas.coords(square2, 500, 490, 249, 250) 
    canvas.coords(square3, 2, 2, 249, 249) 
    canvas.coords(square4, 2, 490, 249, 250) 


# --- Setup --- 

main = Tk() 

main.title("Rubik's Slide") 
main.resizable(width=FALSE, height=FALSE) 
main.geometry("700x550") 

# --- Objects --- 

frame = ttk.Frame(main) 
button_frame = ttk.Frame(frame) 
canvas = Canvas(frame, width=500, height=700) 

# squares 
square1 = canvas.create_rectangle(2, 2, 249, 249, fill="red") 
square2 = canvas.create_rectangle(500, 2, 250, 250, fill="white") 
square3 = canvas.create_rectangle(2, 490, 249, 250, fill="blue") 
square4 = canvas.create_rectangle(500, 490, 250, 250, fill="black") 

# buttons 
right = ttk.Button(button_frame, text="Right", command=clockwise_move).grid(column=2, row=1) 
left = ttk.Button(button_frame, text="Left").grid(column=2, row=2) 
up = ttk.Button(button_frame, text="Up").grid(column=3, row=1) 
down = ttk.Button(button_frame, text="Down").grid(column=3, row=2) 
clockwise = ttk.Button(button_frame, text="Clockwise").grid(column=2, row=3) 
counter_clockwise = ttk.Button(button_frame, text="Counterclock").grid(column=3, row=3) 
start = ttk.Button(button_frame, text="Start").grid(column=2, row=4) 
reset = ttk.Button(button_frame, text="Reset").grid(column=3, row=4) 

# frame grid 
frame.grid(column=1, row=1) 
canvas.grid(column=1, row=1) 
button_frame.grid(column=2, row=1) 

# misc settings 
for child in button_frame.winfo_children(): 
    child.grid_configure(padx=10, pady=20) 

main.mainloop() # end of GUI 

回答

1

如果我理解正確,您想獲得什麼,這是我的解決方案。

爲了簡化程序,我刪除了除clockwise之外的所有按鈕。我也簡化了座標。

我的程序的想法是,對於「順時針」轉動,您總是有相同的4個座標,根據順時針方向和根據計數器n(即總是遞增來做一些算術運算以便索引正確的座標)。運算符*基本上將索引元組的每個項目分配給四個參數。在按下按鈕時做某些事情的想法可以通過聽取<Button-1><Leave>事件以及after函數的組合來模擬,該函數將調用調度到函數。

from tkinter import * 
from tkinter import ttk 


after_id = None 

def clockwise_move(e): 
    global after_id, c, n 
    n += 1 

    canvas.coords(square1, *c[n % len(c)]) 
    canvas.coords(square2, *c[(n + 1) % len(c)]) 
    canvas.coords(square3, *c[(n + 2) % len(c)]) 
    canvas.coords(square4, *c[(n + 3) % len(c)]) 

    after_id = e.widget.after(1000, clockwise_move, e) 

def stop(e): 
    e.widget.after_cancel(after_id) 


main = Tk() 

frame = ttk.Frame(main) 
button_frame = ttk.Frame(frame) 
canvas = Canvas(frame, width=500, height=500) 

c = [(0, 0, 250, 250), 
    (250, 0, 500, 250), 
    (250, 250, 500, 500), 
    (0, 250, 250, 500)] 

n = len(c) 

square1 = canvas.create_rectangle(*c[n % len(c)], fill="red") 
square2 = canvas.create_rectangle(*c[(n + 1) % len(c)], fill="yellow") 
square3 = canvas.create_rectangle(*c[(n + 2) % len(c)], fill="blue") 
square4 = canvas.create_rectangle(*c[(n + 3) % len(c)], fill="green") 

clockwise = ttk.Button(button_frame, text="Clockwise") 
clockwise.grid(column=2, row=3) 
clockwise.bind("<Button-1>", clockwise_move) 
clockwise.bind("<Leave>", stop) 

frame.pack() 
canvas.grid(column=1, row=1) 
button_frame.grid(column=2, row=1) 

for child in button_frame.winfo_children(): 
    child.grid_configure(padx=10, pady=20) 

main.mainloop() 

無論如何,通過查看代碼,您將會對發生的事情有更好的感覺。如果沒有,請在網上看看您還沒有很好理解的概念;)

當您停止按下按鈕時可能會有輕微的滯後,因爲事件已經安排完畢...

+0

它爲什麼保持旋轉?我怎麼才能使它只是旋轉一次,而不是再次,直到我再次按下按鈕? – frankehhh

+0

另外,我會如何爲不同的方向呢?我沒有看到運動正在進行 – frankehhh

+0

@frankehhh根據你的問題,我認爲你真的想在按下按鈕時保持旋轉。你可以簡單地刪除這條線'after_id = e.widget.after(1000,clockwise_move,e)',你也可以刪除這條線'clockwise.bind(「,stop)'。另外,你不需要函數'stop'和變量'after_id'。 – nbro

1

還有一些想法是必需的。你如何告訴節目你想移動哪一行,然後向右或向左移動。列也是如此。另一個方法是將正方形Id和該正方形的顏色存儲在字典中並提高顏色。這隻會移動行,但上下類似。

from Tkinter import * 
import ttk 
from functools import partial 

def move_button(row, direction): 
    increment = -1 ## move left 
    if direction == "R": 
     increment = +1 
    this_row=rows_dict[row] 
    ## get current leftmost color 
    square_instance, color=this_row[0] 
    location=colors_list.index(color) 
    location += increment ## next color 
    for each_square_list in rows_dict[row]: ## list=square_id and color 
     if location >= len(colors_list) or location < 0: 
      location = 0 
     next_color=colors_list[location] 
     print "Setting color to", next_color 

     ## update the canvas and dictionary with the new color 
     canvas.itemconfig(each_square_list[0], fill=next_color) 
     each_square_list[1]=next_color 
     location += 1 ## for 2nd/right square 
    print rows_dict 

main = Tk() 

main.title("Rubik's Slide") 
main.resizable(width=FALSE, height=FALSE) 
main.geometry("750x550") 

# --- Objects --- 

frame = ttk.Frame(main) 
button_frame = ttk.Frame(frame) 
canvas = Canvas(frame, width=500, height=700) 

# store color of each square in a dictionary 
# key = row--> list of lists, each square=[ square instance, color]  
rows_dict={} 
colors_list=["white", "red", "blue", "green", "yellow", "orange"] 
## 2X2 square 
square = canvas.create_rectangle(2, 2, 249, 249, fill="red") 
rows_dict[0]=[[square, "red"]] 
square = canvas.create_rectangle(500, 2, 250, 250, fill="blue") 
rows_dict[0].append([square, "blue"]) 
square = canvas.create_rectangle(2, 490, 249, 250, fill="blue") 
rows_dict[1]=[[square, "blue"]] 
square = canvas.create_rectangle(500, 490, 250, 250, fill="green") 
rows_dict[1].append([square, "green"]) 
print "rows_dict", rows_dict 

# buttons 
ttk.Button(button_frame, text="Top row right", command=partial(move_button, 0, "R")).grid(column=2, row=0) 
ttk.Button(button_frame, text="Top row left", command=partial(move_button, 0, "L")).grid(column=3, row=0) 
ttk.Button(button_frame, text="Bottom row right", command=partial(move_button, 1, "R")).grid(column=2, row=1) 
ttk.Button(button_frame, text="Bottom row left", command=partial(move_button, 1, "L")).grid(column=3, row=1) 
Button(button_frame, text="Exit", command=main.quit, bg="orange").grid(row=5, column=2, columnspan=2) 
# frame grid 
frame.grid(column=1, row=1) 
canvas.grid(column=1, row=1) 
button_frame.grid(column=2, row=0, rowspan=2) 

# misc settings 
for child in button_frame.winfo_children(): 
    child.grid_configure(padx=10, pady=20) 

main.mainloop() 
1

這是你想要做的嗎?

import sys 
if sys.version[0] < '3': 
    from Tkinter import * 
else: 
    from tkinter import * 

left_corners = [(0,0), (200,0), (200,200), (0,200)] 
colors = ['red', 'green', 'yellow', 'blue'] 

def rotate_clockwise(): 
    last_color = colors.pop() 
    colors.insert(0, last_color) 
    update() 

def rotate_counterclockwise(): 
    first_color = colors.pop(0) 
    colors.append(first_color) 
    update() 

def update(): 
    for square, color in zip(squares, colors): 
     canvas.itemconfig(square, fill=color) 

root = Tk() 

canvas = Canvas(root, width=400, height=400) 
canvas.grid() 

squares = [] 
for left_corner, color in zip(left_corners, colors): 
    x1, y1 = left_corner 
    x2, y2 = x1+200, y1+200 
    square = canvas.create_rectangle(x1, y1, x2, y2, fill=color) 
    squares.append(square) 

Button(root, text="Rotate 90 degrees clockwise", 
     command=rotate_clockwise).grid() 
Button(root, text="Rotate 90 degrees counter-clockwise", 
     command=rotate_counterclockwise).grid() 

root.title("Rotating test") 
root.mainloop()