Ящик Python Tkinter, перемещающийся после перерисовки - PullRequest
0 голосов
/ 12 марта 2012

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

Обратите внимание, что я запускаю все это на 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)

Ответы [ 2 ]

1 голос
/ 12 марта 2012

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

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

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

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

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)
0 голосов
/ 12 марта 2012

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

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

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

...