2016-03-01 350 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()