Remove widget from Gtk viewport / scrolled window in dynamic GUI

前端 未结 2 1360
猫巷女王i
猫巷女王i 2021-01-17 00:35

I am building a GUI (Python binding of GTK3) where one Gtk Scrolled Window (from Glade) can contain different treeviews. The program launches with an empty window and the fi

相关标签:
2条回答
  • 2021-01-17 01:14

    To clear out the scrolled window, do this:

    self.scrolled_window.remove(self.scrolled_window.get_child())
    
    0 讨论(0)
  • 2021-01-17 01:34

    After the answer by ptomato I realized that I was adding the TreeViews by using:

      self.scrolled_window.add_with_viewport(some_treeview)
    

    For some reason the scrolled_window.remove() function does not like viewports. Instead one should use:

      self.scrolled_window.add(some_treeview)
    

    It probably makes sense because the documentation states that:

    If a widget has native scrolling abilities, such as Gtk.TextView, Gtk.TreeView or Gtk.IconView, it can be added to a Gtk.ScrolledWindow with Gtk.Container.add (). If a widget does not, you must first add the widget to a Gtk.Viewport, then add the viewport to the scrolled window.

    (Source: https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Viewport.html)

    So because a Gtk.TreeView is already scrollable it should not go into a separate Gtk.Viewport widget.

    Working example

    I cleaned up the example from above and it is now fully functioning:

    Glade file

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated with glade 3.16.1 -->
    <interface>
      <requires lib="gtk+" version="3.10"/>
      <object class="GtkWindow" id="window1">
        <property name="can_focus">False</property>
        <property name="default_width">800</property>
        <property name="default_height">600</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>
            <child>
              <object class="GtkBox" id="box2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkScrolledWindow" id="scrolledwindow1">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="shadow_type">in</property>
                    <child>
                      <placeholder/>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkScrolledWindow" id="scrolledwindow2">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="shadow_type">in</property>
                    <child>
                      <placeholder/>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="box3">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkButton" id="add_layer">
                    <property name="label" translatable="yes">add layer</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="on_add_layer_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="GtkButton" id="add_data">
                    <property name="label" translatable="yes">add data</property>
                    <property name="name">add_data</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="on_add_data_clicked" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </interface>
    

    Python file

    #!/usr/bin/python3
    
    from gi.repository import Gtk
    import random
    
    class LayerTreeView(Gtk.TreeView):
        def __init__(self, store):
            Gtk.TreeView.__init__(self, store)
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn("Name", renderer, text=0)
            self.append_column(column)
    
    class DataTreeView(Gtk.TreeView):
        def __init__(self, store):
            Gtk.TreeView.__init__(self, store)
            self.store = store
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn("Dataset", renderer, text=0)
            self.append_column(column)
    
            for x in range(10):
                self.store.append(None, [str(random.random())])
    
    class MainWindow(object):
        def __init__(self, builder):
            self.main_window = builder.get_object("window1")
            self.sw1 = builder.get_object("scrolledwindow1")
            self.sw2 = builder.get_object("scrolledwindow2")
            self.layernumber = 1
    
            #Initializing top TreeStore and TreeView
            #First object is the store, second is the view of the bottom data-view
            self.topstore = Gtk.TreeStore(str, object, object)
            self.topview = LayerTreeView(self.topstore)
            self.sw1.add(self.topview)
    
            #Adding some testdata
            for x in range(3):
                datastore = Gtk.TreeStore(str)
                dataview = DataTreeView(datastore)
                layername = "Layer {0}".format(self.layernumber)
                self.layernumber += 1
                self.topstore.append(None, [layername, datastore, dataview])
    
            self.select = self.topview.get_selection()
            self.select.connect("changed", self.on_tree_selection_changed)
            self.main_window.show_all()
    
        def on_add_layer_clicked(self, widget):
            datastore = Gtk.TreeStore(str)
            dataview = DataTreeView(datastore)
            layername = "Layer {0}".format(self.layernumber)
            self.layernumber += 1
            self.topstore.append(None, [layername, datastore, dataview])
    
        def on_add_data_clicked(self, widget):
            self.selection = self.topview.get_selection()
            model, treeiter = self.selection.get_selected()
            if treeiter != None:
                data_object = model[treeiter][1]
                data_object.append(None, [str(random.random())])
    
        def on_window1_destroy(self, widget):
            Gtk.main_quit()
    
        def on_tree_selection_changed(self, selection):
            model, treeiter = selection.get_selected()
            if treeiter != None:
                treeview_object = model[treeiter][2]
                child = self.sw2.get_child()
                if child != None:
                    self.sw2.remove(self.sw2.get_child())
                self.sw2.add(treeview_object)
                self.main_window.show_all()
    
    def main():
        builder = Gtk.Builder()
        objects = builder.add_objects_from_file("treeview_switcher.glade",
             ("window1", ""))
    
        window_instance = MainWindow(builder)
        builder.connect_signals(window_instance)
        Gtk.main()
    
    if __name__ == "__main__":
         main()
    
    0 讨论(0)
提交回复
热议问题