Поток не остановится, пока окно не будет уничтожено, окно не уничтожится, пока поток не будет остановлен

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

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

class Window1:
    def __init__(...):
        self.Master = tk.Tk()
        # some code
        self.BackgroundUpdates = threading.Thread(target=self.ActiveWindow)
        self.BackgroundUpdates.start()

    def ActiveWindow(self):
        # gets some instruction
        if instruction == 'next window':
            nextWindow(self)

    def StartWindow(self):
        self.Master.mainloop()

    def KillWindow(self):
        self.Master.destroy()


class Window2:
    def __init__(...):
        self.Master = tk.Tk()
        # some code...

    def StartWindow(self):
        self.Master.mainloop()


def nextWindow(objectWindow):
    objectWindow.KillWindow()
    # when this function is called it never gets past the line above
    nextWindow = Window2()
    nextWindow.StartWindow()

application = Window1()
application.StartWindow()

Есть ли способ изменить порядок обработки потока, чтобы не столкнуться с этой проблемой?

работающий пример:

import tkinter as tk
import threading

class MainWindow:
    def __init__(self):
        self.Master = tk.Tk()
        self.Frame = tk.Frame(self.Master, width=100, height=100)
        self.Frame.pack()
        self.Updates = threading.Thread(target=self.BackgroundUpdates)
        self.Updates.start()

    def BackgroundUpdates(self):
        # imagine instructions to be a really long list with each element being a 
        # different instruction
        instructions = ['instruction1', 'instruction2', 'next window']
        while True:
            if instructions[0] == 'next window':
                ChangeWindow(self)
            else:
                instructions.remove(instructions[0])

    def StartWindow(self):
        self.Master.mainloop()

    def KillWindow(self):
        self.Master.destroy()

class SecondaryWindow:
    def __init__(self):
        self.Master = tk.Tk()
        self.Frame = tk.Frame(self.Master, width=100, height=100)
        self.Frame.pack()

    def StartWindow(self):
        self.Master.mainloop()

    def KillWindow(self):
        self.Master.destroy()

def ChangeWindow(oldObject):
    oldObject.KillWindow()
    # the line above will halt the program, since it has to wait on the thread to 
    # finish before the window can be destroyed, but this function is being called 
    # from within the thread and so the thread will never stop executing
    del oldObject
    newObject = SecondaryWindow()
    newObject.StartWindow()

window = MainWindow()
window.StartWindow() 

ваш код даже не запускается

coderoftheday 20.12.2020 20:11

@coderoftheday я НАМНОГО упростил его по сравнению с тем, как он есть в моей программе, не знаю, работает ли этот настоящий здесь код, это просто для того, чтобы показать общую проблему.

0isab 20.12.2020 20:14

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

coderoftheday 20.12.2020 20:19
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял, что tkinter является однопоточным, это можно объяснить здесь:

https://stackoverflow.com/a/45803955/11702354

Проблема заключалась в том, что я пытался уничтожить свое окно из потока, отличного от того, в котором оно было создано. Чтобы решить эту проблему, мне пришлось использовать метод «после» из модуля Tkinter, а также использовать событие, это означало, что Я мог управлять фоновыми вещами (т.е. ждать определенной команды от моего подключенного сервера), и когда мне нужно было изменить окно, я устанавливал событие.

Часть моего адаптированного кода можно увидеть ниже:

    def CheckEvent(self):
        if LOBBY_EVENT.is_set():
            ChangeWindow(self, 'game')
        self.Master.after(5000, self.CheckEvent)

    def StartWindow(self):
        self.Master.after(5000, self.CheckEvent)
        self.Master.after(2000, self.HandleInstruction)
        self.Master.mainloop()

Поэтому всякий раз, когда я вызывал метод StartWindow для своего окна, он проверял, установлено ли событие каждые 5 секунд, а затем каждые 2 секунды переходил к отдельной функции «HandleInstruction», которая позволяла мне создавать ответ в моем графическом интерфейсе. (Я также использовал очереди для передачи информации этой функции)

Я надеюсь, что это прояснит путаницу, если кто-то наткнется на это!

Другие вопросы по теме