Понимание Tkinter после ()

Прежде всего, взгляните на мою предыдущую тему здесь: Tkinter понимает основной цикл

Следуя совету оттуда, в программировании с графическим интерфейсом следует любой ценой избегать бесконечных циклов, чтобы виджеты реагировали на ввод пользователя.

Вместо использования:

while 1:
    ball.draw()
    root.update()
    time.sleep(0.01)

Мне удалось использовать self.canvas.after(1, self.draw) внутри моей функции draw().

Итак, мой код теперь выглядит так:

# Testing skills in game programming

from Tkinter import *

root = Tk()
root.title("Python game testing")
root.resizable(0, 0)
root.wm_attributes("-topmost", 1)

canvas = Canvas(root, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
root.update()

class Ball:
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
        self.canvas.move(self.id, 245, 100)

        self.canvas_height = canvas.winfo_height()
        self.x = 0
        self.y = -1

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)

        pos = self.canvas.coords(self.id)
        if pos[1] <= 0:
            self.y = 1
        if pos[3] >= self.canvas_height:
            self.y = -1

        self.canvas.after(2, self.draw)


ball = Ball(canvas, "red")
ball.draw()

root.mainloop()

Однако время внутри self.canvas.after() не работает должным образом... Если установлено в 1, оно очень быстрое! Если он установлен на 10, 5 или даже 2, это слишком медленно! У меня не было этой проблемы при использовании вышеуказанного цикла while в моем коде, поскольку time.sleep() работало как надо!


ИЗМЕНИТЬ:

Теперь я могу сообщить, что время внутри функции after Tkinter не работает должным образом на моем планшете с Windows 8.1 и на моем ноутбуке с Windows 8.1, в то время как на том же ноутбуке при запуске Ubuntu через виртуальную машину оно работает работать как надо.


person midkin    schedule 20.03.2015    source источник
comment
Время в sleep указано в секундах, а в after — в миллисекундах. С after(10,...) вроде так же быстро, как и с sleep(0.01). В чем именно проблема?   -  person tobias_k    schedule 21.03.2015
comment
Это не то! Я набираю self.canvas.after(1, self.draw), и он отвечает так, как должен (1 миллисекунда), затем я ввожу 2 миллисекунды, и он отвечает, как я использовал 20... Я не вижу никаких изменений, если я использую 2, 5 или 10... как 1 миллисекунда может быть такой быстрой, а 2 такой медленной... эта функция просто не работает так, как должна... С другой стороны, time.sleep() работает идеально   -  person midkin    schedule 21.03.2015
comment
Не могу воспроизвести. Я, конечно, вижу разницу, ввожу ли я after(2,...) или after(20,...).   -  person tobias_k    schedule 21.03.2015
comment
Действительно? Так для вас 2 в два раза медленнее, чем 1???? оо   -  person midkin    schedule 21.03.2015
comment
Да, 2 примерно в два раза медленнее 1, т.е. мячу требуется примерно в два раза больше времени на один проход.   -  person tobias_k    schedule 21.03.2015
comment
Только что измерил, что мячу требуется менее 2 секунд, чтобы перевернуться вверх ногами при использовании 1 миллисекунды и 12 секунд при использовании 2 !!!   -  person midkin    schedule 21.03.2015
comment
2 секунды за 1 мс? Для меня это занимает около 1/2 секунды при такой настройке! Чего и следовало ожидать, так как мяч перемещается на один пиксель за итерацию, а высота кадра составляет 500 пикселей. Кажется, что-то действительно странное с твоей стороны...   -  person tobias_k    schedule 21.03.2015
comment
я использую win8.1 в планшете ... я попробую это на своем ноутбуке и отвечу! :О   -  person midkin    schedule 21.03.2015
comment
на моем ноутбуке прямо сейчас 14 секунд при использовании 1 миллисекунды ... боже мой !!! Я тоже запускаю его на своем линуксе ..   -  person midkin    schedule 21.03.2015
comment
Теперь я могу сообщить, что время внутри функции after Tkinter не работает должным образом на моем планшете с win8.1 и на моем ноутбуке с win8.1, в то время как на том же ноутбуке при запуске ubuntu через виртуальную машину оно работает как надо! !! :О   -  person midkin    schedule 21.03.2015
comment
Похоже, это относится к устройствам @midkin, возможно, интерпретатор/tkinter не был установлен должным образом или одна из его зависимостей...   -  person Annonymous    schedule 06.04.2015
comment
Спасибо за ответ, есть предложения, как это исправить?   -  person midkin    schedule 06.04.2015


Ответы (2)


Время в time.sleep указано в секундах, а в after() — в миллисекундах. time.sleep(0.01) совпадает с self.canvas.after(10, self.draw). Если after(2, func) был слишком медленным, но after(1, func) был слишком быстрым, вы можете попробовать sleep(0.0005), тогда after(1, func) дает задержку в 1,5 миллисекунды, но это едва заметно. В любом случае, играйте со временем, пока пауза не станет правильной.

person Evan Quiney    schedule 25.08.2015

Скорость объекта (холста) и скорость часов/цикла следует рассматривать как две разные вещи, ИМХО. Следовательно, вы можете выйти из цикла через 2 мс или даже больше, например, 10...25...

...
self.canvas.after(2, self.draw)
... # loop this after 2 ms.

в то время как изменение скорости с точки зрения «сколько пикселей»:

pos = self.canvas.coords(self.id)
    if pos[1] <= 0:
        self.y = 20
    if pos[3] >= self.canvas_height:
        self.y = -20

поэтому регулируя эти значения, и:

self.canvas.move(self.id, 245, 100)

может позволить вам точно настроить положение и скорость вашей красной точки. Надеюсь, поможет

person Lorenzo Bassetti    schedule 29.08.2019