Stacks und Notebooks
| Anke (encarsia) | Auch verfügbar in: English
Inhalte organisiert anzeigen
Gtk.Stack und Gtk.Notebook sind Layout-Container, die ihrerseits beliebige Widgets enthalten können.
Ein Notebook stellt ein mehrseitiges Layout mit klassischer Tab-Funktionalität zur Verfügung. Stacks bieten die gleiche Grundfunktionalität, nämlich mehrere Container innerhalb eines Widgets zu enthalten, zwischen denen man hin- und herschalten kann.
Der Hauptunterschied besteht darin, dass das Bedienelement des Stacks als separates Widget verwendet werden muss (Gtk.StackSwitcher). Verschiedene Stackswitcher können dabei auf den selben Stack zugreifen. Weiterhin lassen sich Stackswitcher in Headerbars platzieren, außerdem werden animierte Überblenden zwischen den Stack-Seiten unterstützt.
Stacks passen sich subjektiv besser in die GNOME-Umgebung ein, bieten aber nicht ganz so große Funktionalität wie Notebooks.
Das Beispiel enhält ein Fenster mit Stack, in dessen dritter Seite ein Notebook enthalten ist, das verschiedene Webseiten anzeigt.
Glade
Stack
Ein Stack, zu finden in der Sidebar unter "Container", und dessen Unterseiten lassen sich einfach in Glade erstellen und bearbeiten. Als Unterwidgets kommen im Beispiel Gtk.Image, Vte.Terminal und Gtk.Notebook zum Einsatz.
Das Stackswitcher-Widget befindet sich unter "Steuerung und Anzeige" und wird der Headerbar hinzugefügt. Es kann aber auch in reguläre Container-Widgets wie einer Box platziert und die Unterseiten horizontal oder vertikal angezeigt werden. Unter "Allgemein > Stapel" wird der Stack ausgewählt, auf den sich das Widget beziehen soll. Die anzuzeigende Seitenbezeichnung wird im jeweiligen Stack-Unterwidget unter "Packen > Titel" festgelegt. Dies funktioniert aber erst, nachdem einer Unterseite ein Widget hinzugefügt wurde. Standardmäßig ist dies zunächst leer.
Notebook
Das Notebook findet sich ebenfalls unter "Container". Die Steuerungseinheit des Tabs ist ein bei Erstellung einer Seite generiertes Label-Child-Widget. Als Container-Widgets der Unterseiten werden hier Gtk.ScrolledWindows verwendet. Diese benötigt man auch z.B. für die Anzeige von (längeren) Tabellen (siehe auch Artikel zu List-/TreeStores Nr. 1 und Nr. 2).
Die Tab-Leiste des Notebooks bietet die Möglichkeit, sowohl am Anfang als auch am Ende ein Container-Widget bereitzustellen (unter "Allgemein > Start-Aktion/End-Aktion"), in dem zum Beispiel feste Buttons untergebracht werden können. Im Beispiel wird am Anfang ein "Home"-Button eingerichtet.
Python
Für das Umherschalten zwischen Stack-Unterseiten und Notebook-Tabs werden keine Signale benötigt. Im Beispiel werden nur zwei Signale benötigt, einmal für das Abfangen des "exit"-Kommandos innerhalb des Terminals und für den Button in der Notebook-Tableiste.
WebKit2
Die Darstellung von Webseiten wird im Beispiel von WebKit2 erledigt. Das zentrale Modul dabei ist WebKit2.WebView
. Ein neues WebView-Objekt selbst ist bereits ein scrollbares Gtk+-Widget in einem Gtk.Viewport, muss also laut API-Referenz nicht mehr in ein Gtk.ScrolledWindow platziert werden. Dies funktionierte im Test zwar für Gtk.Stack, nicht aber für Gtk.Notebook, weshalb dort trotzdem als "Unterlage" ein ScrolledWindow-Widget verwendet wird.
Das WebView-Widget wird nach folgendem Muster erstellt:
# create new WebView widget webview = WebKit2.WebView() # send URL to widget webview.load_uri("http://google.com") # add webview to notebook notebook.add(webview) # add webview to stack stack.add_titled(webview, name, "StackSwitcher title") webview.show()
Listings
Python
#!/usr/bin/python # -*- coding: utf-8 -*- import sys import urllib.request import gi gi.require_version("Gtk", "3.0") gi.require_version("Vte", "2.91") gi.require_version("WebKit2", "4.0") from gi.repository import Gtk, Gio, Vte, GObject, GLib, WebKit2 class Handler: def on_term_child_exited(self, widget, event): # reset and setup terminal on exit command widget.reset(True, True) app.stack_console() def on_home_button_clicked(self, widget): # reload given URL in current tab page = app.obj("notebook").get_current_page() app.nbtabs[page][2].load_uri(app.nbtabs[page][1]) class ExampleApp: def __init__(self): self.app = Gtk.Application.new("org.application.test", Gio.ApplicationFlags(0)) self.app.connect("activate", self.on_app_activate) def on_app_activate(self, app): GObject.type_register(Vte.Terminal) builder = Gtk.Builder() builder.add_from_file("21_stacknotebook.glade") builder.connect_signals(Handler()) self.obj = builder.get_object self.obj("window").set_application(app) self.obj("window").show_all() # get window content self.stack_image() self.stack_console() self.stack_notebook() def run(self, argv): self.app.run(argv) def stack_image(self): # download and show NASA Astonomy Picture of the Day URL = "https://apod.nasa.gov" source = urllib.request.urlopen(URL).read().decode("utf-8") img_start = source.find("<IMG SRC=") img_end = source.find("alt=") img = source[img_start+10:img_end-2] IMGURL = "https://apod.nasa.gov/apod/" + img urllib.request.urlretrieve(IMGURL, "apod.jpg") self.obj("image").set_from_file("apod.jpg") def stack_console(self): # setup terminal self.obj("term").spawn_sync( Vte.PtyFlags.DEFAULT, None, ["/bin/bash"], None, GLib.SpawnFlags.DEFAULT, ) def stack_notebook(self): self.nbtabs = [ ["gi_doc", "https://lazka.github.io/pgi-docs/"], ["gtk_tut", "http://python-gtk-3-tutorial.readthedocs.io/en/latest/index.html"], ["glade_tut", "https://encarsia.github.io/posts/tutorial-reihe-glade/"] ] for tab in self.nbtabs: webview = WebKit2.WebView() tab.append(webview) webview.load_uri(tab[1]) self.obj(tab[0]).add(webview) webview.show() app = ExampleApp() app.run(sys.argv)
Glade
21_stacknotebook.glade (Source)
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.20.1 --> <interface> <requires lib="gtk+" version="3.20"/> <requires lib="vte-2.91" version="0.50"/> <object class="GtkImage" id="image1"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="icon_name">go-home</property> </object> <object class="GtkApplicationWindow" id="window"> <property name="width_request">800</property> <property name="height_request">600</property> <property name="can_focus">False</property> <child> <object class="GtkStack" id="stack"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="transition_type">crossfade</property> <child> <object class="GtkImage" id="image"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="stock">gtk-missing-image</property> </object> <packing> <property name="name">page0</property> <property name="title" translatable="yes">Astronomy Picture of the Day</property> </packing> </child> <child> <object class="VteTerminal" id="term"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="hscroll_policy">natural</property> <property name="vscroll_policy">natural</property> <property name="encoding">UTF-8</property> <property name="scroll_on_keystroke">True</property> <property name="scroll_on_output">False</property> <signal name="child-exited" handler="on_term_child_exited" swapped="no"/> </object> <packing> <property name="name">page3</property> <property name="title" translatable="yes">Terminal</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkNotebook" id="notebook"> <property name="visible">True</property> <property name="can_focus">True</property> <child> <object class="GtkScrolledWindow" id="gi_doc"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <placeholder/> </child> </object> </child> <child type="tab"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="label" translatable="yes">PyGObject API Reference </property> </object> <packing> <property name="tab_fill">False</property> </packing> </child> <child> <object class="GtkScrolledWindow" id="gtk_tut"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <placeholder/> </child> </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">Python GTK+ 3 Tutorial</property> </object> <packing> <property name="position">1</property> <property name="tab_fill">False</property> </packing> </child> <child> <object class="GtkScrolledWindow" id="glade_tut"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <placeholder/> </child> </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">Glade-Tutorial</property> </object> <packing> <property name="position">2</property> <property name="tab_fill">False</property> </packing> </child> <child type="action-start"> <object class="GtkButton" id="home_button"> <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="on_home_button_clicked" swapped="no"/> </object> <packing> <property name="tab_fill">False</property> </packing> </child> </object> <packing> <property name="name">page1</property> <property name="title" translatable="yes">Notebook</property> <property name="position">2</property> </packing> </child> </object> </child> <child type="titlebar"> <object class="GtkHeaderBar"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="show_close_button">True</property> <child> <object class="GtkStackSwitcher"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="stack">stack</property> </object> </child> </object> </child> </object> </interface>
Kommentare bei
Kommentare
Comments powered by Disqus