2

I am trying to use an object-oriented approach to create a class that inherits from tkinter's Toplevel, triggered by pressing a button in the main window.

The current code raises an AttributeError ('MakeWindow' object has no attribute 'tk'). Can anyone point me in the right direction?

#! python3
import tkinter as tk


class Application:
    def __init__(self, master):
        self.frame = tk.Frame(master)
        self.frame.pack()    
        self.okButton = tk.Button(self.frame, text="OK",
                                  command=self.window_maker).pack()
        self.quitButton = tk.Button(self.frame, text="Close",
                                    command=self.frame.quit).pack()
    def window_maker(self):
        MakeWindow("A message to Toplevel")


class MakeWindow(tk.Toplevel):
    def __init__(self, message):
        super().__init__(self)
        self.message = message
        self.display = tk.Label(self, text=message)
        self.display.pack()


if __name__ == '__main__':
    root = tk.Tk()
    app = Application(root)
    root.mainloop()

Full traceback:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\r\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
  File "C:/Users/r/PycharmProjects/tkinter_gui/y.py", line 15, in window_maker
    MakeWindow("A message to Toplevel")
  File "C:/Users/r/PycharmProjects/tkinter_gui/y.py", line 20, in __init__
    super().__init__(self)
  File "C:\Users\r\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2182, in __init__
    BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
  File "C:\Users\r\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2132, in __init__
    BaseWidget._setup(self, master, cnf)
  File "C:\Users\r\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2110, in _setup
    self.tk = master.tk
AttributeError: 'MakeWindow' object has no attribute 'tk'
qwertysmack
  • 188
  • 1
  • 12

1 Answers1

3

The problem is the super().__init__(self) it should be super().__init__(). Moreover, it is not necesssary to use super in this case (see What does 'super' do in Python?). The following code works:

import tkinter as tk


class Application:
    def __init__(self, master):
        self.frame = tk.Frame(master)
        self.frame.pack()    
        self.okButton = tk.Button(self.frame, text="OK",
                                  command=self.window_maker).pack()
        self.quitButton = tk.Button(self.frame, text="Close",
                                    command=self.frame.quit).pack()
    def window_maker(self):
        MakeWindow("A message to Toplevel")


class MakeWindow(tk.Toplevel):
    def __init__(self, message):
        tk.Toplevel.__init__(self) #instead of super
        self.message = message
        self.display = tk.Label(self, text=message)
        self.display.pack()


if __name__ == '__main__':
    root = tk.Tk()
    app = Application(root)
    root.mainloop()
Community
  • 1
  • 1
j_4321
  • 15,431
  • 3
  • 34
  • 61
  • Why wouldn't you use `super`? You don't need to, but it's much neater. – jonrsharpe Jul 11 '16 at 15:01
  • Thanks - so if I use super() no 'self' is required, tk.Toplevel.__init__(self) does require 'self'. Pycharm complains about the latter ("Expected type 'Toplevel' but got 'Make Window' instead") but it works fine. Thanks, and thanks for the link! – qwertysmack Jul 11 '16 at 15:02