Python Tkinter, как синхронизировать несколько мигающих виджетов? - PullRequest
0 голосов
/ 08 мая 2020

Это мой первый вопрос!

Я создал несколько настраиваемых виджетов (на основе холста), которые имеют один и тот же метод мигания. Когда я нажимаю на них (используя bind ()), они должны мигать (используя обратный вызов after ()), пока я не нажму на них второй раз.

Это работает, но их мигание асинхронно, потому что оно начинается, когда я щелкните по виджету.

Я хотел бы синхронизировать их мигание, но не могу понять, что использовать.

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

Ниже приведен упрощенный пример:

import tkinter as tk


def flash(button):
    current_color = button.cget("background")
    next_color = "green" if current_color == "red" else "red"
    button.config(background=next_color)
    root.after(1000, flash, button)


root = tk.Tk()

Button1 = tk.Button(root, text="Button1", background="green")
Button2 = tk.Button(root, text="Button2", background="green")

Button1.pack()
Button2.pack()

Button1.bind("<ButtonPress-1>", lambda event: flash(Button1))
Button2.bind("<ButtonPress-1>", lambda event: flash(Button2))

root.mainloop()

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

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

(я также использовал foreground i / o background цвета, чтобы заставить его работать в моей системе.)

import tkinter as tk


def flash(button, buttons=set(), _after=[]):
    if button not in buttons:
        buttons.add(button)
    current_color = button.cget("foreground")
    next_color = "blue" if current_color == "red" else "red"
    for button in buttons:
        button.config(foreground=next_color)
    for after_id in _after:
        root.after_cancel(after_id)
    if buttons:
        _after.append(root.after(1000, flash, button))


if __name__ == '__main__':

    root = tk.Tk()

    Button1 = tk.Button(root, text="Button1", foreground="blue")
    Button2 = tk.Button(root, text="Button2", foreground="blue")

    Button1.pack()
    Button2.pack()

    Button1.bind("<ButtonPress-1>", lambda event: flash(Button1))
    Button2.bind("<ButtonPress-1>", lambda event: flash(Button2))

    root.mainloop()

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

def flash(button, callback=False, buttons=set(), _after=[]):
    if callback:
        pass
    elif button not in buttons:
        buttons.add(button)
    else:
        buttons.remove(button)
    current_color = button.cget("foreground")
    next_color = "blue" if current_color == "red" else "red"
    for button in buttons:
        button.config(foreground=next_color)
    for after_id in _after:
        root.after_cancel(after_id)
    if buttons:
        _after.append(root.after(1000, flash, button, True))
0 голосов
/ 08 мая 2020

Ты можешь попробовать сделать что-нибудь. вот так:

import tkinter as tk
import time


class Blinker:
    def flash(self, button):
        current_color = button.cget("background")
        next_color = "green" if current_color == "red" else "red"
        button.config(background=next_color)
    def ch(self, i):
        self.b[i] = not self.b[i]
    def __init__(self):
        self.root = tk.Tk()

        self.b = [False, False]

        Button1 = tk.Button(self.root, text="Button1", background="green")
        Button2 = tk.Button(self.root, text="Button2", background="green")

        Button1.pack()
        Button2.pack()

        Button1.bind("<ButtonPress-1>", lambda event: self.ch(0))
        Button2.bind("<ButtonPress-1>", lambda event: self.ch(1))

        while 1:
            if self.b[0]:
                self.flash(Button1)
            if self.b[1]:
                self.flash(Button2)
            t = time.time()
            while time.time()-t<1:
                self.root.update()
Blinker()

Надеюсь, это поможет!

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