Using tkinter, I'm trying to open one window from another window and doing so by creating the windows in a class.
This question talks about tkinter and class, but not multiple windows: Python Tkinter with classes
This question addresses multiple windows but it's creating an instance of the class: Python tkinter multiple windows. I don't want to create an instance of the class because tkdoc.com has the root = Tk()
being passed into the class rather than creating an instance.
So, I have this example from https://www.pythontutorial.net/tkinter/tkinter-toplevel/ which does what I want but it creates a subclass of tk.TK
rather than passing in root
. I'm trying to adapt this example to pass in root
because that's what the official docs do.
Here's the example of one window opening up another window that works, but it creates a subclass of tk.Tk
:
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()
if __name__ == "__main__":
app = App()
app.mainloop()
Here's my adaptation:
from tkinter import *
from tkinter import ttk
class Window(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():
def __init__(self, root):
super().__init__()
root.geometry('300x200')
root.title('Main Window')
# place a button on the root window
ttk.Button(root,
text='Open a window',
command=self.open_window).pack(expand=True)
def open_window(self):
window = Window(self)
window.grab_set()
if __name__ == "__main__":
root = Tk()
App(root)
root.mainloop()
The first window opens fine (class App()
). I'm getting an AttributeError
that occurs when attempting to open the second window (class Window(Toplevel)
). Yet, the AttributeError
is on the first window.
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "c:\Users\User\Documents\Python\Python_Tutorial_net\Multiple_Windows_pass-in-Class.py", line 30, in open_window
window = Window(self)
^^^^^^^^^^^^
File "c:\Users\User\Documents\Python\Python_Tutorial_net\Multiple_Windows_pass-in-Class.py", line 7, in __init__
super().__init__(parent)
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2678, in __init__
BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2623, in __init__
self._setup(master, cnf)
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2592, in _setup
self.tk = master.tk
^^^^^^^^^
AttributeError: 'App' object has no attribute 'tk'
Note that instance of App()
is not a tkinter widget, so it cannot be used as the parent of the second window.
Use the root window as the parent of the second window instead:
class App():
def __init__(self, root):
super().__init__()
self.root = root # save root to an instance variable
...
def open_window(self):
window = Window(self.root) # used self.root instead of self
window.grab_set()