2012-03-12 3 views
0

У меня есть программа, которая повторно рисует холст Tkinter, уничтожая его, а затем снова рисуя. Тем не менее, каждый раз, когда он рисует окно, он перемещает несколько пикселей вправо от экрана. Например, если первый прямоугольник обрамляется в левую сторону экрана, десять или около того рисует его позже, теперь он находится вровень с правой стороной экрана. Что вызывает это и как я могу остановить его?Python Tkinter box, перемещающийся при повторном рисовании

Обратите внимание, что я запускаю все это на Mac, и у меня были проблемы с вещами, которые должны работать в Tkinter, а это не так, поэтому, если вы знаете, что это проблема, скажите мне. Спасибо за любую помощь, и если вам нужна дополнительная информация, не стесняйтесь просить об этом!

После выполнения рекомендации Брайана Окли, я больше не разрушаю рамку, только прямоугольники. Однако теперь у меня проблема, что кадр рисован и остается пустым навсегда ... Я не понимаю, почему.

Код: Я немного поменял рекомендацию Брайана Окли. Теперь я получаю ошибку TclError: invalid command name ".4332933704" в w.create_rectangle(x, y, z, a, fill="white")

def printBoard(time,board): 
    global w 
    global root 
    x=20 
    y=15 
    z=60 
    a=45 
    for i in range(len(board)-3,-1,-1): 
     y+=30 
     a+=30 
     x=20 
     z=60 
     for j in range(len(board[i])): 
      x+=40 
      z+=40 
      if len(board[i][j])==0:  
       w.create_rectangle(x, y, z, a, fill="white") 
      else: 
       w.create_rectangle(x, y, z, a, fill='black') 
    root.after(int(time*1000),tech) 

def tech(): 
    global w 
    w.delete(ALL) 

def output(board,difficulty): 
    global root 
    global w 
    root=Tk() 
    root.lift() 
    root.title('Tetris') 
    w = Canvas(root, width=500, height=750) 
    w.bind_all('<Up>',rotate) 
    w.bind_all('<Left>',left) 
    w.bind_all('<Right>',right) 
    w.bind_all('<Escape>',stop) 
    w.pack() 
    mainloop() 
    global playing 
    playing=True 
    printBoard(sec,board) 
    while playing: 
     play(board) 
     printBoard(sec,board) 
+0

Невозможно сказать, какая ошибка вызывает это поведение, если вы не покажете нам свой код. Холст Tkinter прочный, поэтому проблема почти наверняка лежит в вашем коде. –

+0

Я добавил код. –

+0

@ ChaosPhoenix7 Я думаю, что описанная вами ошибка может возникнуть, если Canvas 'w' не существует. Это произойдет, если ваша программа когда-либо называет 'printBoard' до' output'. (Вы можете проверить это, добавив выражения 'print'.) – gary

ответ

0

Ваша первая проблема заключается в том, что вы переинициализация пе весь графический интерфейс на каждой итерации. Tkinter wan't разработан таким образом. Это даст непредсказуемые результаты. Вы должны создать ровно один экземпляр Tk! и звоните mainloop ровно один раз.

Тот факт, что «поле» перемещается каждый раз, вероятно, связано с этим, если под «полем» вы подразумеваете окно. Некоторые диспетчер ветрогенератора делают каждый раз, когда создается окно, если вы не укажете местоположение.

Кроме того, очень необычно удалять и воссоздавать виджет - по крайней мере, он медленный и неэффективный. Есть команды холста для перемещения объектов, или если вам действительно нужно, вы можете удалить и воссоздать элементы холста.

+0

Я изменил свой код, чтобы следовать вашему предложению. –

1

Я пишу этот ответ после набора исправлений к исходному коду. Единственный способ исправить ваш код - это полностью переписать его, и для этого не нужен этот форум.

Я предлагаю вам прекратить работать над вашей программой и работать через пару обучающих программ на Tkinter (tkdocs и pythonware - это хорошие места для начала). У вас есть фундаментальное непонимание программирования, управляемого событиями. Например, у вас есть код после вызова mainloop, но вызов mainloop должен быть последней логической строкой кода в вашей программе. Это тот факт, что вы пытаетесь создать виджеты после mainloop выходов, которые вызывают самую последнюю ошибку (TclError: недопустимое имя команды «.4332933704»)

Во-вторых, у вас бесконечный цикл в вашей программе. Управляемые событиями программы уже имеют бесконечный цикл в форме цикла событий. Это то, что mainloop есть. Наличие собственного бесконечного цикла - это просто неправильный способ сделать что-то. Ваша программа должна основываться на событиях, а не на закодированном бесконечном цикле.

Если вы хотите вызвать перерисовку каждые N миллисекунд, вы можете использовать метод tkinter after для планирования функции, которая будет вызываться в будущем. Если эта функция выполняет одно и то же (т. Е.: Когда-нибудь в будущем), вы создали простой цикл анимации. Например:

class MyApp(...): 
    def __init__(...): 
     # call it the first time; it will then call 
     # itself several times a second 
     self.redraw() 

    def redraw(self, *args): 
     <redraw everything> 
     self.after(42, self.redraw) 
Смежные вопросы