Запуск цикла вместе с приложением Tkinter - PullRequest
2 голосов
/ 09 июня 2011

Я учусь в средней школе, у меня маленький вопрос.Мне было поручено написать простую игру в Tkinter, где сосулька падает с потолка, и вы должны избегать ее с помощью мыши.Достаточно просто.Тем не менее, я столкнулся с проблемой.Всякий раз, когда я запускаю цикл в приложении Tkinter, он не открывается.Я попытался с циклом for, который делает паузу каждые 0,5 секунды, используя time.sleep (), и окно открывается, как только цикл заканчивается.Есть ли что-то особенное, что мне нужно сделать, чтобы петли работали в Tkinter?

from Tkinter import *
import time
import random

class App:
    def __init__(self, parent):
        self.frame = Frame(root, bg= '#1987DF', width=800, height=800)
        self.frame.bind("<Motion>", self.motionevent)
        self.frame.pack()
        #self.run()
    def randhex(self):
        b = "#"
        for i in range(1, 7):
            a = random.randint(0, 15)
            if a == 10:
                a = "A"
            elif a == 11:
                a = "B"
            elif a == 12:
                a = "C"
            elif a == 13:
                a = "D"
            elif a == 14:
                a = "E"
            elif a == 15:
                a = "F"
            b = b+str(a)
        return b

    def motionevent(self, event):
        xpos, ypos, bg = event.x, event.y, self.randhex()
        str1 = "X : %d  Y : %d BG : %s" % (xpos, ypos, bg)
        root.title(str1)
        x,y, delta = 100, 100, 10
        self.frame.config(bg=bg)

    def run(self):
        for i in range(0, 10):
            time.sleep(.5)
            print 'i'
            self.frame.config(bg=self.randhex())

root = Tk()
app = App(root)
root.mainloop()

В настоящее время все, что нужно сделать, это изменить фон при перемещении мыши.Когда строка в init , в которой говорится, что self.run () не закомментирована, напечатает «i» 10 раз, после чего откроется окно.Помощь

1 Ответ

6 голосов
/ 09 июня 2011

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

Поскольку цикл уже запущен, вам не нужно создавать другой цикл,Все, что вам нужно сделать, это добавить небольшие задания в очередь событий по одному.По сути, каждое задание - это одна итерация вашего внутреннего цикла.

Например, если вы хотите написать внутренний цикл, подобный этому:

for i in range(10):
    print "i:", i

... вы бы вместо этого добавилисобытие в очередь событий, и каждый раз, когда цикл событий повторяется (или, точнее, каждый раз, когда он завершает обработку любых других событий), он выполняет одну итерацию вашего цикла.Вы делаете это так:

def do_one_iteration(i):
    print "i:", i
    if i < 9:
        root.after_idle(do_one_iteration, i+1)

Затем, после первого вызова do_one_iteration, он поместит следующую итерацию в очередь событий и продолжит делать это, пока не решит, что этосделанный.

Обычно вы звоните do_one_iteration, когда пользователь нажимает кнопку (например, кнопку «Пуск»).Вызовите его один раз, затем он выполнит один бит работы (т. Е. Переместит сосульку вниз на пару пикселей), а затем перенастроится.

В разработке игры у вас может быть функция под названием update_display, которая отвечаетперерисовывать все.Это может, например, вычесть 1 из координаты Y каждой сосульки.Вы можете добавить привязки для стрелок влево и вправо для перемещения игрока (увеличивая или уменьшая координату X), и ваша функция обновления будет использовать эти новые координаты для перерисовки игрока.

Кстати, вы можетезамедлите вашу программу, используя after вместо after_idle для вызова функции после небольшой задержки.Эта задержка может использоваться для управления частотой кадров.Например, предполагая, что обновление происходит почти мгновенно (и, вероятно, это будет в вашем случае), вызов after с аргументом 41 (миллисекунды) дает частоту кадров примерно 24 кадра в секунду (24 кадра при 41 миллисекунде равны 984 миллисекундам, илипримерно 24 кадра в секунду)

Это может показаться сложным, но на практике это действительно довольно легко, если сделать это один или два раза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...