Lyuboslav Angelov Lyuboslav Angelov - 4 months ago 18
Python Question

Python Gtk 3 window is not defined, class instancing confusion

I am just starting to get into python and I am utterly confused as to how object creation works. I am trying to create user interface with GTK. Here is an example of the problem I am having:

from gi.repository import Gtk


def button_clicked(self, button):
self.button_label = button.get_label()
if self.button_label == "Login":
window.quit()
window2.start()

class LoginWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="AMOK Cloud")
self.connect("delete-event", Gtk.main_quit)
self.set_position(position = Gtk.WindowPosition.CENTER)

# Button
self.loginbutton = Gtk.Button(label="Login")
self.loginbutton.connect("clicked", button_clicked(self, self.loginbutton))
self.add(self.loginbutton)

self.show_all()
Gtk.main()

def quit(self):
self.close()
Gtk.main_quit()

class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="AMOK Cloud")
self.connect("delete-event", Gtk.main_quit)
self.set_position(position=Gtk.WindowPosition.CENTER)

def start(self):
self.show_all()
Gtk.main()

window = LoginWindow()
window2 = MainWindow()


Error comes up as NameError: name 'window' is not defined
even though I did define window. I don't understand. If someone can explain it would mean the world to me. Thanks in advance.

EDIT:
Thanks guys this works fine now, took Gtk.main() out of both classes and added button_clicked method inside LoginWindow() class and now it works like a charm. I assumed I needed Gtk.main() for every window I open.

Answer

It is because you are starting the main loop (Gtk.main()) inside of LoginWindow.__init__(). That means that the window = LoginWindow() line doesn't finish executing until after the login window is closed. You should take Gtk.main() outside of the __init__ method, and move it to the last line in the file. As mentioned by PM 2Ring in the comments, you don't need to call Gtk.main() twice. Take it out completely in MainWindow.start() because the one now added to the last line in the file takes care of that. Also mentioned by PM, connect() calls a function when an event happens. When you give it button_clicked(...), that function is called and you are actually telling connect() to call whatever is returned, None. If you want special arguments, use a lambda, but you aren't even changing anything (those are the default arguments anyway), so you can simply do this:

self.connect("clicked", button_clicked)

I would also suggest that instead of making button_clicked a separate function, make it a static method of the class. You do that by placing it inside the class, but with @staticmethod just above the def line. That way, it makes sense for it to take the self argument, but you don't need two parameters to account for the same window.

Comments