Найти - Пользователи
Полная версия: Многопоточность
Начало » Python для новичков » Многопоточность
1 2
Konstantin1984+
Предполагается, что по щелчку мышкой оба предмета начнут двигаться, но двигается только один.
Прошу пояснить мою ошибку.

 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()
xam1816
Konstantin1984+
что по щелчку мышкой оба предмета начнут двигаться, но двигается только один.
Прошу пояснить мою ошибку.
потому что в c.bind функция дополнительно не привязывается, а перепривязывается другая
Konstantin1984+
А какие тогда следует внести изменения, чтобы программа корректно заработала?
Alex.Pro.
Konstantin1984+
какие следует внести изменения?
stackoverflow
Если посмотреть в документацию на функцию bind, то мы увидим, что у неё есть параметр add. Вот что написано про него в документации:

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

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

button.bind(“<Button>”, handler1)
button.bind(“<Button>”, handler2, ‘+’)
Konstantin1984+
Без указанных правок двигался только круг, с правками двигается только треугольник, одновременного движения нет.
Alex.Pro.
Konstantin1984+
двигался только круг, с правками двигается только треугольник
Видно, что привязки изменились.
К сожалению, не с моими знаниями и опытом решать подобные задачи. Я и в первый раз не смог понять ваш код. Хорошо, что xam1816 обратил внимание на непорядок с биндами. И сейчас не знаю что сказать, могу только строить гипотезы…
Мне не нравятся вложенные def'ы. Как-то это не по фэншую. Разве что threading позволяет делать такие матрёшки?
Мне не нравятся бесконечные циклы. Обычно, это считается недопустимым. threading прервёт выполнение цикла?
А ещё меня смущает функция sleep. Она останавливает выполнение потока или всей программы?

Надеюсь, кто-нибудь более опытный и знающий сможет сказать что-нибудь более умное и полезное.
Alex.Pro.
Ещё одна глупая идея: а что, если к событию привязать не какую-то функцию (движения об'екта), а функцию потока (внутри которой выполняется перемещение об'екта). Лучше не станет?
xam1816
В tkinter циклический вызов функции делается через метод after, т. е в собственном потоке приложения, читайте про него.
py.user.next
Я просто запустил, а ты смотри потом, как запомнить нажатие кнопки, чтобы не запускать тред повторно.
  
#!/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()
Konstantin1984+
Всем спасибо, есть различные варианты решения задачи.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB