blog.furas.pl
# prywatne notatki - Python, Linux, Machine Learning, etc.

Tworzenie podokna w Tkinter za pomocą Toplevel()

To jest "przedruk" jednej z moich wypowiedzi na polskim forum Pythona. http://pl.python.org/forum/index.php?topic=4366.msg18662#msg18662


Złóżone GUI posiada tylko jedno okno główne a wszystko inne to jego potomstwo. Jest to naturalny sposób działania - (prawie) każdy program tak działa (niezależnie od języka czy biblioteki do GUI).

Tak więc dla głównego okna używa się Tk() a do całej reszty Toplevel().

Można tworzyć te okna poprzez bezpośrednie wywołanie Tk() , Toplevel() wewnątrz klas i przypisanie do zmiennej np. self.master aby potem mieć dostęp do właściwości danego okna przez self.master (wewnątrz klasy) i nazwa_okna.master poza klasą.

import Tkinter as tk

#----------------------------------------------------------------------

class Main():

    def __init__(self):
        self.master = tk.Tk() # bezposrednie tworzenie okna
        self.master.title("Main") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Main", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(self.master) # przekazanie okna jako rodzica

    def run(self):
        self.master.mainloop()

#----------------------------------------------------------------------

class Child():

    def __init__(self, parent):
        self.master = tk.Toplevel(parent) # bezposrednie tworzenie okna
        self.master.title("Child") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Child", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(self.master) # przekazanie okna jako rodzica

#----------------------------------------------------------------------

glowne = Main()
glowne.master.title("Glowne") # zewnetrzny dostep do wlasnosci okna
glowne.run()

Można też robić to poprzez "dziedziczenie klas" i wtedy cała klasa jest jakby oknem i do własności okna ma się dostęp przez self (wewnątrz klasy) i nazwa_okna poza klasą.

import Tkinter as tk

#----------------------------------------------------------------------

class Main(tk.Tk): # dziedziczenie po klasie tk.Tk

    def __init__(self):
        tk.Tk.__init__(self) # wywolanie konstruktora klasy tk.Tk
        self.title("Main") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self, text="Otworz okno Child z okna Main", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(self) # przekazanie okna jako rodzica

    def run(self):
        self.mainloop()

#----------------------------------------------------------------------

class Child(tk.Toplevel): # dziedziczenie po klasie tk.Toplevel

    def __init__(self, parent):
        tk.Toplevel.__init__(self, parent) # wywolanie konstruktora klasy tk.Toplevel
        self.title("Child") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self, text="Otworz okno Child z okna Child", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(self) # przekazanie okna jako rodzica

#----------------------------------------------------------------------

glowne = Main()
glowne.title("Glowne") # zewnetrzny dostep do wlasnosci okna
glowne.run()

Można ewentualnie jeszcze przekazywać z zewnątrz okno do klasy. I wtedy można decydować, które okno jest nam potrzebne jako główne - trzeba tylko pamiętać o mainloop() i albo dodać go też do Child albo użyć poza klasami.

import Tkinter as tk

#----------------------------------------------------------------------

class Main():

    def __init__(self, master):
        self.master = master # otrzymanie okna z zewnatrz
        self.master.title("Main") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Main", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(tk.Toplevel(self.master)) # przekazanie okna

    # def run(self):
        # self.master.mainloop()

#----------------------------------------------------------------------

class Child():

    def __init__(self, master):
        self.master = master # otrzymanie okna z zewnatrz
        self.master.title("Child") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Child", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(tk.Toplevel(self.master)) # przekazanie okna

    # def run(self):
        # self.master.mainloop()

#----------------------------------------------------------------------

master = tk.Tk()
glowne = Main(master)
master.title("Glowne") # dostep do wlasnosci okna
master.mainloop()

# wykorzystanie dziecka jako okno glowne z pominieciem okna Main()

master = tk.Tk()
glowne = Child(master)
master.title("Glowne Dziecko") # dostep do wlasnosci okna
master.mainloop()

Podział kodu na kilka plików (każda klasa w osobnym pliku) jest jak najbardziej możliwy. A za pomoca __name__ będzie można wykorzystywać Child jako podokno a także jako samodzielne okno główne

main_only.py

import Tkinter as tk
from child_only import *

#----------------------------------------------------------------------

class Main():

    def __init__(self, master):
        self.master = master # otrzymanie okna z zewnatrz
        self.master.title("Main") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Main", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(tk.Toplevel(self.master)) # przekazanie okna

    # def run(self):
        # self.master.mainloop()

#----------------------------------------------------------------------

if __name__ == '__main__':
    master = tk.Tk()
    glowne = Main(master)
    master.title("Glowne") # dostep do wlasnosci okna
    master.mainloop()

child_only.py

import Tkinter as tk

#----------------------------------------------------------------------

class Child():

    def __init__(self, master):
        self.master = master # otrzymanie okna z zewnatrz
        self.master.title("Child") # wewnetrzny dostep do wlasnosci okna

        tk.Button(self.master, text="Otworz okno Child z okna Child", command=self.onButton).grid()

    def onButton(self):
        self.child = Child(tk.Toplevel(self.master)) # przekazanie okna

    # def run(self):
        # self.master.mainloop()

#----------------------------------------------------------------------

if __name__ == '__main__':
    master = tk.Tk()
    glowne = Child(master)
    master.title("Glowne Dziecko") # dostep do wlasnosci okna
    master.mainloop()
Książki: python-dla-kazdego-podstawy-programowania python-wprowadzenie python-leksykon-kieszonkowy python-receptury python-programuj-szybko-i-wydajnie python-projekty-do-wykorzystania black-hat-python-jezyk-python-dla-hackerow-i-pentesterow efektywny-python-59-sposobow-na-lepszy-kod tdd-w-praktyce-niezawodny-kod-w-jezyku-python aplikacje-internetowe-z-django-najlepsze-receptury