Python tkinter закрывает первое окно при открытии второго окна

Я пытаюсь закрыть первое окно, когда открывается второе окно. Оба окна закрываются, или первое окно закрывается, а второе окно никогда не открывается.

В этом вопросе есть аналогичная проблема, но она была решена путем обращения к импортированным библиотекам: Tkinter открывает второе окно, когда закрывается первое

Вот мой код, взятый отсюда https://www.pythontutorial.net/tkinter/tkinter-toplevel/

import tkinter as tk
from tkinter import ttk


class Window(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)

        self.geometry('300x100')
        self.title('Toplevel Window')

        ttk.Button(self,
                text='Close',
                command=self.destroy).pack(expand=True)


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.geometry('300x200')
        self.title('Main Window')

        # place a button on the root window
        ttk.Button(self,
                text='Open a window',
                command=self.open_window).pack(expand=True)

    def open_window(self):
        window = Window(self)
        window.grab_set()
        self.destroy()


if __name__ == "__main__":
    app = App()
    app.mainloop()

Я добавил self.destroy() в функцию def open_window(self). Но оно не закрывает окно, созданное этим классом: class App(tk.Tk).

Вам придется написать self.destroy(), чтобы эта строка действительно что-то сделала.

jasonharper 16.05.2024 22:28

Если вы не поняли, дело в том, что вы забыли () для вызова функции.

Barmar 16.05.2024 22:36

Спасибо @jasonharper и @Barmar. Добавление ( ) уничтожит первое окно, но теперь второе окно никогда не откроется. Плюс, почему ( ) не нужен при закрытии второго окна кнопкой в ​​class Window? Это окно прекрасно закрывается без ( ).

David Collins 16.05.2024 22:39

Добавление () в конец ссылки на функцию приведет к выполнению этой функции. command=self.destroy передаст ссылку на функцию опции command кнопки, поэтому при нажатии кнопки функция будет выполнена.

acw1668 17.05.2024 04:26
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

По вашему замыслу вам нужно будет каким-то образом начать основной цикл второго окна. Раньше я сталкивался с этой проблемой, и мне показалось, что наиболее полезным было сначала запустить оба окна, а затем закрыть их, когда они не были нужны до и после того, как они были показаны, а также запустить метод .update() в обоих окнах, чтобы они работали одновременно. Не расстраивайтесь, убранные окна не означают свернутые окна, и конечный пользователь не может легко получить к ним доступ, но они легко доступны вам с помощью метода .deiconify. Что касается уничтожения окон, я обнаружил, что в tkinter в Python это очень и очень привередливо.

Итак, в вашем случае:

import tkinter as tk
from tkinter import ttk


class Window(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent

        self.geometry('300x100')
        self.title('Toplevel Window')
        self.withdraw()

        ttk.Button(self,
                text='Close',
                command=self.parent.destroy).pack(expand=True)


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.geometry('300x200')
        self.title('Main Window')

    def bar(self, window_unwithdraw_fn):
        # place a button on the root window
        ttk.Button(self,
                text='Open a window',
                command=window_unwithdraw_fn).pack(expand=True)



if __name__ == "__main__":
    app = App()
    window = Window(app)

    def foobar():
        window.deiconify()
        window.grab_set()
        app.withdraw()
    
    app.bar(foobar)

    while True:
        app.update()
        window.update()

Обратите внимание на пару вещей:

  • После уничтожения всех окон интерпретатор tcl не завершает работу, а значит, и интерпретатор python. Вы можете использовать метод .quit(), но это зависит от того, что вы хотите.
  • Это быстрый набросок, показывающий, как будет работать базовая логика. Вам решать, как привести ее в соответствие со структурой вашего проекта, чтобы вы могли переместить пару вещей в методы __init__() или из них или создать новые классы. и т. д.
  • Это работает, и если вы хотите возиться с окном, на котором находится фокус, я бы рекомендовал проверить win32gui или библиотеку графического интерфейса вашей соответствующей ОС.
  • Я не полностью детализировал этот небольшой фрагмент кода, поэтому, хотя он работает в соответствии с тем, как вы описали в своем посте, будьте осторожны с реализацией self.parent.destroy в Window, поскольку это может иметь некоторые неожиданные последствия, такие как некорректное поведение виджетов.
  • Как описано выше, это не уничтожает ваши App или Window, а только отзывает их до тех пор, пока не будет нажата кнопка окончательного закрытия.
  • Наконец, я не был уверен, должно ли первое окно открываться снова после нажатия кнопки закрытия второго окна, но если да, то вместо уничтожения родителя в Window должно быть просто деиконизировать его и удалить текущее окно self в какая-то новая foo() функция
.iconify() работает аналогично .withdraw()
George S. 17.05.2024 01:58

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