[Python] tkinter - generate_event not working when called from a background thread

Discussão em 'Python' iniciado por Stack, Maio 23, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to update some UI elements from a background thread, since tkinter doesn't support that I tried to create a queue for generating events with event_generate.

    So every time I need some kind of update I have to insert a ticket into this queue:

    from enum import Enum, auto
    from queue import Queue
    from ttkbootstrap import Window



    class TicketPurpose(Enum):
    UPDATE_LOG_TEXT = auto()


    class Ticket:
    def __init__(self, ticket_type : TicketPurpose, ticket_value : str):
    self.ticket_type = ticket_type
    self.ticket_value = ticket_value




    class QueueMaster():

    __instance = None

    @staticmethod
    def get_instance():
    """singleton """

    if QueueMaster.__instance is None:
    raise Exception("No instance available yet!")
    return QueueMaster.__instance

    def __init__(self, root : Window):
    if QueueMaster.__instance is not None:
    raise Exception("Singleton cannot be instantiated more than once!")
    else:
    QueueMaster.__instance = self
    self.queue = Queue()
    self.root = root

    def put_ticket(self, ticket : Ticket):
    """puts a ticket into the queue"""

    print(f"inserting ticket: {ticket.ticket_value}")
    self.queue.put(ticket)
    #self.root.after(0, lambda : self.root.event_generate("<<CheckQueue>>"))
    self.root.event_generate("<<CheckQueue>>")


    def get_ticket(self):
    """gets a tickted from the queue"""

    ticket = self.queue.get()
    print(f"removed {ticket.ticket_value} from queue")
    return ticket

    def queue_empty(self):
    """check if queue is empty"""

    return self.queue.empty()


    my main file has a simple function called foo which is executed from a background thread and inserts a ticket into the queue:

    class MainWindow():

    def __init__(self, root):
    self.root = root
    self.ticket_queue = None
    self.ticket_queue = QueueMaster(self.root)
    self.__init_window()

    def main_loop(self):
    """starts the main loop"""

    self.root.mainloop()

    def foo(self):
    """test function"""

    self.ticket_queue.put_ticket(Ticket(ticket_type=TicketPurpose.UPDATE_LOG_TEXT, ticket_value="foo"))
    sleep(2)

    def check_queue(self, event=None):
    """update ui"""

    ticket = self.ticket_queue.get_ticket()
    if ticket.ticket_type == TicketPurpose.UPDATE_LOG_TEXT:
    print("updating...")
    else:
    raise Exception("Invalid ticket!")


    def __init_window(self):
    """init the window and widgets"""

    self.root.bind("<<CheckQueue>>", self.check_queue)
    thread = threading.Thread(target = self.foo, daemon = True)
    thread.start()





    def main():
    """main"""

    root = ttkb.Window(themename = "litera")
    root.title("test")
    root.minsize(800, 600)

    main_window = MainWindow(root)
    main_window.main_loop()


    if __name__ == "__main__":
    main()


    I'm also binding to a method called check_queue here so that every time an event is generated I'll have a chance to handle it, the problem is that this method isn't being called at all, what am I doing wrong?

    Continue reading...

Compartilhe esta Página