Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 14, 2024 18:43:43

Konstantin1984+
Зарегистрирован: 2020-02-04
Сообщения: 79
Репутация: +  0  -
Профиль   Отправить e-mail  

Многопоточность

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

 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()

Офлайн

#2 Дек. 15, 2024 14:05:20

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1358
Репутация: +  119  -
Профиль   Отправить e-mail  

Многопоточность

Konstantin1984+
что по щелчку мышкой оба предмета начнут двигаться, но двигается только один.
Прошу пояснить мою ошибку.
потому что в c.bind функция дополнительно не привязывается, а перепривязывается другая

Офлайн

#3 Дек. 29, 2024 18:45:18

Konstantin1984+
Зарегистрирован: 2020-02-04
Сообщения: 79
Репутация: +  0  -
Профиль   Отправить e-mail  

Многопоточность

А какие тогда следует внести изменения, чтобы программа корректно заработала?

Офлайн

#4 Дек. 29, 2024 20:36:53

Alex.Pro.
От: Марик
Зарегистрирован: 2024-11-13
Сообщения: 42
Репутация: +  1  -
Профиль   Отправить e-mail  

Многопоточность

Konstantin1984+
какие следует внести изменения?
stackoverflow
Если посмотреть в документацию на функцию bind, то мы увидим, что у неё есть параметр add. Вот что написано про него в документации:

Перевод:
Необязательный параметр. Может быть равным либо ‘', либо ’+'. Передача пустой строки означает, что новая связь заменит все связи с событием, установленные ранее. Передача ‘+’ означает, что функция будет добавлена к списку функций, связанных с указанным событием.

По умолчанию add='', Поэтому новая функция заменяет предыдущую.
Вот минимальный пример связывания нескольких функций с одним событием:

button.bind(“<Button>”, handler1)
button.bind(“<Button>”, handler2, ‘+’)

Отредактировано Alex.Pro. (Дек. 29, 2024 20:38:54)

Офлайн

#5 Дек. 30, 2024 10:21:39

Konstantin1984+
Зарегистрирован: 2020-02-04
Сообщения: 79
Репутация: +  0  -
Профиль   Отправить e-mail  

Многопоточность

Без указанных правок двигался только круг, с правками двигается только треугольник, одновременного движения нет.

Офлайн

#6 Дек. 30, 2024 14:49:41

Alex.Pro.
От: Марик
Зарегистрирован: 2024-11-13
Сообщения: 42
Репутация: +  1  -
Профиль   Отправить e-mail  

Многопоточность

Konstantin1984+
двигался только круг, с правками двигается только треугольник
Видно, что привязки изменились.
К сожалению, не с моими знаниями и опытом решать подобные задачи. Я и в первый раз не смог понять ваш код. Хорошо, что xam1816 обратил внимание на непорядок с биндами. И сейчас не знаю что сказать, могу только строить гипотезы…
Мне не нравятся вложенные def'ы. Как-то это не по фэншую. Разве что threading позволяет делать такие матрёшки?
Мне не нравятся бесконечные циклы. Обычно, это считается недопустимым. threading прервёт выполнение цикла?
А ещё меня смущает функция sleep. Она останавливает выполнение потока или всей программы?

Надеюсь, кто-нибудь более опытный и знающий сможет сказать что-нибудь более умное и полезное.

Офлайн

#7 Дек. 31, 2024 17:37:51

Alex.Pro.
От: Марик
Зарегистрирован: 2024-11-13
Сообщения: 42
Репутация: +  1  -
Профиль   Отправить e-mail  

Многопоточность

Ещё одна глупая идея: а что, если к событию привязать не какую-то функцию (движения об'екта), а функцию потока (внутри которой выполняется перемещение об'екта). Лучше не станет?

Офлайн

#8 Дек. 31, 2024 21:01:45

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1358
Репутация: +  119  -
Профиль   Отправить e-mail  

Многопоточность

В tkinter циклический вызов функции делается через метод after, т. е в собственном потоке приложения, читайте про него.

Офлайн

#9 Янв. 2, 2025 00:10:13

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9874
Репутация: +  854  -
Профиль   Отправить e-mail  

Многопоточность

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

  
#!/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)

Офлайн

#10 Янв. 2, 2025 10:25:49

Konstantin1984+
Зарегистрирован: 2020-02-04
Сообщения: 79
Репутация: +  0  -
Профиль   Отправить e-mail  

Многопоточность

Всем спасибо, есть различные варианты решения задачи.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version