Форум сайта python.su
Предполагается, что по щелчку мышкой оба предмета начнут двигаться, но двигается только один.
Прошу пояснить мою ошибку.
from tkinter import * from time import sleep from threading import Thread root=Tk() root.title ('Многопоточность') c = Canvas(width=2250, height=2250,bg='green') c.pack() treug=c.create_polygon(110, 110, 110, 160, 150, 135) krug=c.create_oval(40, 140, 100, 200) def potok1(): def dvig1(event): n=0 while True: c.move(treug, -1, 0) c.update() sleep(0.02) n=n+1 c.bind("<ButtonPress-1>", dvig1) def potok2(): def dvig2(event): n=0 while True: c.move(krug, 1, 0) c.update() sleep(0.02) n=n+1 c.bind("<ButtonPress-1>", dvig2) th1=Thread(target=potok1) th2=Thread(target=potok2) th1.start() th2.start() root.mainloop()
Офлайн
Konstantin1984+потому что в c.bind функция дополнительно не привязывается, а перепривязывается другая
что по щелчку мышкой оба предмета начнут двигаться, но двигается только один.
Прошу пояснить мою ошибку.
Офлайн
А какие тогда следует внести изменения, чтобы программа корректно заработала?
Офлайн
Konstantin1984+
какие следует внести изменения?
stackoverflow
Если посмотреть в документацию на функцию bind, то мы увидим, что у неё есть параметр add. Вот что написано про него в документации:
Перевод:
Необязательный параметр. Может быть равным либо ‘', либо ’+'. Передача пустой строки означает, что новая связь заменит все связи с событием, установленные ранее. Передача ‘+’ означает, что функция будет добавлена к списку функций, связанных с указанным событием.
По умолчанию add='', Поэтому новая функция заменяет предыдущую.
Вот минимальный пример связывания нескольких функций с одним событием:
button.bind(“<Button>”, handler1)
button.bind(“<Button>”, handler2, ‘+’)
Отредактировано Alex.Pro. (Дек. 29, 2024 20:38:54)
Офлайн
Без указанных правок двигался только круг, с правками двигается только треугольник, одновременного движения нет.
Офлайн
Konstantin1984+Видно, что привязки изменились.
двигался только круг, с правками двигается только треугольник
Офлайн
Ещё одна глупая идея: а что, если к событию привязать не какую-то функцию (движения об'екта), а функцию потока (внутри которой выполняется перемещение об'екта). Лучше не станет?
Офлайн
В tkinter циклический вызов функции делается через метод after, т. е в собственном потоке приложения, читайте про него.
Офлайн
Я просто запустил, а ты смотри потом, как запомнить нажатие кнопки, чтобы не запускать тред повторно.
#!/usr/bin/env python3 from tkinter import * from time import sleep from threading import Thread root = Tk() root.title ('Многопоточность') c = Canvas(width=2250, height=2250, bg='green') c.pack() treug = c.create_polygon(110, 110, 110, 160, 150, 135) krug = c.create_oval(40, 140, 100, 200) def dvig1(): c.move(treug, -1, 0) c.update() def dvig2(): c.move(krug, 1, 0) c.update() def runner(): root.after(1000, lambda: (dvig1(), dvig2())) def thread(): while True: runner() sleep(0.02) def run_thread(event): th = Thread(target=thread) th.daemon = True th.start() c.bind("<ButtonPress-1>", run_thread) root.mainloop()
#!/usr/bin/env python3 from tkinter import * from time import sleep from threading import Thread root = Tk() root.title ('Многопоточность') c = Canvas(width=2250, height=2250, bg='green') c.pack() treug = c.create_polygon(110, 110, 110, 160, 150, 135) krug = c.create_oval(40, 140, 100, 200) def dvig1(n): step = -1 if n < 50 else 1 c.move(treug, step, 0) c.update() def dvig2(n): step = 1 if n < 50 else -1 c.move(krug, step, 0) c.update() def runner(n): root.after(1000, lambda: (dvig1(n), dvig2(n))) def thread(): n = 0 while True: runner(n % 100) sleep(0.02) n += 1 def run_thread(event): th = Thread(target=thread) th.daemon = True th.start() c.bind("<ButtonPress-1>", run_thread) root.mainloop()
Отредактировано py.user.next (Янв. 2, 2025 00:21:33)
Офлайн
Всем спасибо, есть различные варианты решения задачи.
Офлайн