2014-11-12 4 views
1

Цель сценария:Tkinter Toplevel в сценарии OOP: как?

  • (3) различные окна, каждый в своем классе, со своими виджетами и макета, создаются с помощью TopLevel и обратных вызовов.
  • Когда создается новое окно (Toplevel), предыдущий уничтожается. Таким образом, только одно окно видимо и активно за раз.

Проблема? В принципе, я пробовал много вещей и не удалось, так что я должен понять слишком мало ["parent", "master", "root", "app", "..."] :(

Обратите внимание на воспитывающих окна: я реализовал успешный пример загрузки все кадры друг на друга и контролировать их видимость с помощью метода .raise.

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

Сценарий(не работает; жучки):

#!/usr/bin/env python 

from Tkinter import * 
import tkMessageBox, tkFont, random, ttk 

class First_Window(Frame): 
    """The option menu which is shown at startup""" 
    def __init__(self, master): 
     Frame.__init__(self, master) 

     self.gotosecond = Button(text = "Start", command = self.goto_Second) 
     self.gotosecond.grid(row = 2, column = 3, sticky = W+E) 

    def goto_Second(self): 
     self.master.withdraw() 
     self.master.update_idletasks() 
     Second_Window = Toplevel(self) 

class Second_Window(Toplevel): 
    """The gamewindow with questions, timer and entrywidget""" 
    def __init__(self, *args): 
     Toplevel.__init__(self) 
     self.focus_set() 

     self.gotothird = Button(text = "gameover", command = self.goto_Third) 
     self.gotothird.grid(row = 2, column = 3, sticky = W+E) 

    def goto_Third(self): 
     Third_Window = Toplevel(self) 
     self.destroy() 

class Third_Window(Toplevel): 
    """Highscores are shown with buttons to Startmenu""" 
    def __init__(self, *args): 
     Toplevel.__init__(self) 
     self.focus_set() 
     self.master = First_Window 

     self.gotofirst = Button(text = "startover", command = self.goto_First) 
     self.gotofirst.grid(row = 2, column = 3, sticky = W+E) 

    def goto_First(self): 
     self.master.update() 
     self.master.deiconify() 
     self.destroy() 

def main(): 
    root = Tk() 
    root.title("Algebra game by PJK") 
    app = First_Window(root) 
    root.resizable(FALSE,FALSE) 
    app.mainloop() 

main() 
+0

Какую ошибку вы получаете? – twasbrillig

+0

С помощью этого сценария первый экран загружается просто отлично. Нажатие на кнопку (goto_Second) откроет новое окно, которое ничего не отобразит. Закрытие этого окна также не закрывает программу (так как я должен закрыть окно терминала тоже). – Pjay

+0

Вы можете использовать 'self.top = Toplevel (self)' внутри вашего класса 'First_Window', а затем просто' self.top.destroy() 'при создании нового окна. Для виджетов, которые будут присутствовать в окне Toplevel, вы можете сделать 'self.some_button = Button (self.top, text = 'Start', command = self.goto_Second)', чтобы виджет использовал 'self.top' как родитель. – DuckPuncher

ответ

0

Проблема на самом деле не является проблемой Tkinter, но основная проблема с классами против экземпляров. Собственно, две подобные, но отдельные проблемы. Вам, вероятно, нужно прочитать учебное пособие по классам, например the one in the official Python tutorial.


Первое:

self.master = First_Window 

First_Window класс. У вас есть экземпляр этого класса (в глобальной переменной с именем app), которая представляет собой первое окно на экране. Вы можете позвонить update и deiconify и т. Д. На этот экземпляр, потому что он представляет это окно. Но First_Window сам не представляет какого-либо конкретного окна, это просто класс, фабрика для , создающая экземпляры, представляющие определенные окна. Поэтому вы не можете позвонить update или deiconify по классу.

Что вы, вероятно, хотите сделать, это передать первое окно через цепочку окон. (Вы могли бы, альтернативно, получить доступ к глобальному или сделать другие вещи, но это кажется самым чистым). Вы уже пытаетесь передать его Second_Window, вам просто нужно его спрятать и передать его снова в Second_Window (вместо того, чтобы проходить self экземпляр, который бесполезен - это просто разрушенный объект окна), а затем спрятать его и использовать в Third_Window.


Второе:

Second_Window = Toplevel(self) 

Вместо создания экземпляра класса Second_Window, вы просто создать экземпляр универсального Toplevel класса, и дает ему имя локального Second_Window (который временно скрывает имя класса ... но так как вы никогда не используете этот класс, это не имеет большого значения).

И у вас такая же проблема, когда вы пытаетесь создать третье окно.


Итак:

class First_Window(Frame): 
    # ... 
    def goto_Second(self): 
     # ... 
     second = Second_Window(self) 

class Second_Window(Toplevel): 
    def __init__(self, first, *args): 
     Toplevel.__init__(self) 
     self.first = first 
     # ... 

    def goto_Third(self): 
     third = Third_Window(self.first) 
     self.destroy() 

class Third_Window(Toplevel): 
    """Highscores are shown with buttons to Startmenu""" 
    def __init__(self, first, *args): 
     Toplevel.__init__(self) 
     self.first = first 
     # ... 

    def goto_First(self): 
     self.first.update() 
     self.first.deiconify() 
     self.destroy() 
+0

Спасибо. Я обновил свой вопрос, где я до сих пор. Переход от одного окна к другому, кажется, работает очень хорошо. Уничтожить их, однако, нет !? Также обратите внимание, что я переключился на использование Frame. Толевел работал так же и показал те же результаты. – Pjay

+0

Уничтожение «рамки» не уничтожает окно, в котором находится кадр; он уничтожает только сам кадр и все его содержимое, обычно оставляя пустое серое окно. – abarnert