Search code examples
pythonuser-interfacegtkpython-2.xglade

Closing the GUI window does not end the program


I have been reading a lot about Glade and been playing with it for the last couple of days to get a basic Python GUI application working. I was able to get a window showing, but whenever I close it I get a ghost process in the terminal from which my program is launched - the application just hangs, but the window is hidden. The process can only be killed via kill - it does not respond to Ctrl-C or Ctrl-D.

The Adventures - what have I tried

I have a function in my code called onDeleteWindow All modifications to the code have been happening inside this function.

I have consulted a variety of sources including this Stack Overflow question and this GTK3 documentation example and here are the different methods that I have extracted from those sources and, of course, tried:

Method 1: window.connect("destroy", self.Destroy)
Method 2: self.quit or self.quit()
Method 3: gtk.main_quit()
All of them lead to the same outcome - ghost process. The example from the GTK3 documentation also leads to the same outcome, if it is copy and pasted as is.

My application and code

somegui.py:

from gi.repository import Gtk
import sys

class Handler:
    def onDeleteWindow(self, *args):
        self.quit()


    def onButtonPressed(self, button):
        print("Hello World!")

builder = Gtk.Builder()
builder.add_from_file("somegui.glade")
builder.connect_signals(Handler())

window = builder.get_object("MainWindow")
window.show_all()

builder.get_objects()

Gtk.main()

somegui.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface domain="">
  <requires lib="gtk+" version="3.10"/>
  <object class="GtkWindow" id="MainWindow">
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">Hi there</property>
    <property name="startup_id">MainWindow</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">Hi there!</property>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="button1">
            <property name="label" translatable="yes">Awesome button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="relief">none</property>
            <property name="yalign">0.56000000238418579</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Gtk version: (according to XML) 3.10
Python version: (checked by launching the interpreter) 2.7.6

What am I doing wrong? I have been trying to get it working for the last couple of days with no progress. Any hints would be appreciated.

EDIT: It appears there were issues with the .glade file, I have copied and pasted its source again, hopefully this will work.

EDIT2: Thank you everyone who have taken their time to answer. The issue was that the handlers were not paired with the GUI itself.


Solution

  • First of all: Are you editing the XML by hand? Your Glade file is corrupt, because you added 2 children to a Window. That is not allowed. You need to add a container (e.g. a GtkBox) to the window and then put all other widgets inside that box.

    In your Pyhthon code you also call self.quit() But self is in this case just a Python object. And it doesn't inherit any methods from GTK. Look another time at how the classes are defined in the Python-GTK3-Tutorial (https://python-gtk-3-tutorial.readthedocs.org/en/latest/).

    As Leonardo mentioned you need to also define your signals in Glade and then use the same name in Python so that your handlers are connected. Here is where you need to set your window-destroy signal:

    enter image description here

    Here is the basic setup that I would use:

    from gi.repository import Gtk
    import sys
    
    class Handler(object):
        def __init__(self, builder):
            self.builder = builder
            self.window = builder.get_object("window1")
            self.window.show_all()
    
        def on_window1_destroy(self, *args):
            Gtk.main_quit()
    
        def on_button1_clicked(self, button):
            print("Hello World!")
    
    builder = Gtk.Builder()
    builder.add_from_file("somegui.glade")
    hdlr = Handler(builder)
    builder.connect_signals(hdlr)
    Gtk.main()
    

    And the UI:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated with glade 3.18.3 -->
    <interface>
      <requires lib="gtk+" version="3.12"/>
      <object class="GtkWindow" id="window1">
        <property name="can_focus">False</property>
        <property name="title" translatable="yes">Hi there</property>
        <signal name="destroy" handler="on_window1_destroy" swapped="no"/>
        <child>
          <object class="GtkBox" id="box1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <property name="homogeneous">True</property>
            <child>
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Hi There!</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="button1">
                <property name="label" translatable="yes">Awesome Button!</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_button1_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </interface>