Search code examples
linuxpython-3.xgtk3

How to make a one-window program with GTK, python and glade?


I'd like to write a program that has one main window and if I click on a button it changes the content of the window (or something similar) and the user can go back after that to the "home page". I'm using python3, gtk3 and glade on Ubuntu 19.04.

Here's the example.glade XML file

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkApplicationWindow" id="main">
    <property name="can_focus">False</property>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkButton" id="button">
        <property name="label" translatable="yes">button</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
      </object>
    </child>
  </object>
</interface>

And here's the Python3 file

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gi
import os
os.chdir('/home/sources')
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class app:

  def __init__(self):
    self.gladefile = 'example.glade'
    self.builder = Gtk.Builder()
    self.builder.add_from_file(self.gladefile)
    self.builder.connect_signals(self)
    self.window = self.builder.get_object('main')
    elf.window = self.builder.get_object('button')
    self.window.show()

if __name__ == '__main__':
  main = app()
  Gtk.main()

I'd like to change the window (but in the same window) to this when the button is pressed

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkApplicationWindow" id="main">
    <property name="can_focus">False</property>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkNotebook" id="notebook">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <child>
          <object class="GtkButton" id="but1">
            <property name="label" translatable="yes">button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
        </child>
        <child type="tab">
          <object class="GtkLabel">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">page 1</property>
          </object>
          <packing>
            <property name="tab_fill">False</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="but2">
            <property name="label" translatable="yes">button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="position">1</property>
          </packing>
        </child>
        <child type="tab">
          <object class="GtkLabel">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">page 2</property>
          </object>
          <packing>
            <property name="position">1</property>
            <property name="tab_fill">False</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="but3">
            <property name="label" translatable="yes">button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="position">2</property>
          </packing>
        </child>
        <child type="tab">
          <object class="GtkLabel">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">page 3</property>
          </object>
          <packing>
            <property name="position">2</property>
            <property name="tab_fill">False</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Solution

  • Here is a possible solution using Gtk.Stack

    The glade file:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated with glade 3.22.1 -->
    <interface>
      <requires lib="gtk+" version="3.20"/>
      <object class="GtkImage" id="image1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="stock">gtk-go-back</property>
      </object>
      <object class="GtkWindow" id="window">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="title" translatable="yes">window</property>
        <property name="window_position">center</property>
        <property name="default_width">500</property>
        <property name="default_height">400</property>
        <signal name="destroy" handler="on_window_destroy" swapped="no"/>
        <child>
          <placeholder/>
        </child>
        <child>
          <object class="GtkStack" id="stack">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkButton" id="home_button">
                <property name="label" translatable="yes">Notebook page</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="button_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="name">page0</property>
                <property name="title" translatable="yes">page0</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="notebook_box">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkButton">
                    <property name="label" translatable="yes">Home</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="image">image1</property>
                    <property name="always_show_image">True</property>
                    <signal name="clicked" handler="home_clicked" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkNotebook" id="notebook">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <child>
                      <object class="GtkButton" id="but1">
                        <property name="label" translatable="yes">button</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                      </object>
                    </child>
                    <child type="tab">
                      <object class="GtkLabel">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">page 1</property>
                      </object>
                      <packing>
                        <property name="tab_fill">False</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkButton" id="but2">
                        <property name="label" translatable="yes">button</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                      </object>
                      <packing>
                        <property name="position">1</property>
                      </packing>
                    </child>
                    <child type="tab">
                      <object class="GtkLabel">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">page 2</property>
                      </object>
                      <packing>
                        <property name="position">1</property>
                        <property name="tab_fill">False</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkButton" id="but3">
                        <property name="label" translatable="yes">button</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                      </object>
                      <packing>
                        <property name="position">2</property>
                      </packing>
                    </child>
                    <child type="tab">
                      <object class="GtkLabel">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">page 3</property>
                      </object>
                      <packing>
                        <property name="position">2</property>
                        <property name="tab_fill">False</property>
                      </packing>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="name">page1</property>
                <property name="title" translatable="yes">page1</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </interface>
    

    The python file:

    #!/usr/bin/env python
    
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    
    
    UI_FILE = "file.glade"
    
    class GUI:
        def __init__(self):
    
            self.builder = Gtk.Builder()
            self.builder.add_from_file(UI_FILE)
            self.builder.connect_signals(self)
    
            window = self.builder.get_object('window')
            window.show_all()
    
        def on_window_destroy(self, window):
            Gtk.main_quit()
    
        def home_clicked (self, button):
            stack = self.builder.get_object('stack')
            home_button = self.builder.get_object('home_button')
            stack.set_visible_child(home_button)
    
        def button_clicked (self, button):
            stack = self.builder.get_object('stack')
            notebook_box = self.builder.get_object('notebook_box')
            stack.set_visible_child(notebook_box)
    
    app = GUI()
    Gtk.main()