decocode decocode deco    

Grafische Oberflächen für GTK+ 3 #

(Version 3.8.4 unter Linux Mint Debian Edition UP 8)

Python unterstützt eine Reihe von Toolkits für verschiedene Grafikbibliotheken, auf die hier nicht im einzelnen eingegangen wird. Diese Anleitung beschränkt sich auf GTK+, mit dem grafischen Oberflächen beispielsweise für die Gnome Shell bzw. den Cinnamon-Desktop hergestellt werden können. Es werden lediglich die wichtigsten Widgets vorgestellt. Für eine ausführliche Übersicht sei die GTK+-Dokumentation empfohlen.

Für die Unterstützung für GObject, das für die Entwicklung von grafischen Oberflächen für GTK+ 3 verwendet wird, müssen zunächst folgende Pakete nachinstalliert werden:

sudo apt-get install python3-gi python3-gi-cairo

Installation per apturl symbol: question

Anschließend kann aus dem Modul gi.repository die Komponente Gtk importiert werden.

GtkWindow #

► GTK+ 3 Dokumentation: GtkWindow

Das Prinzip der grafischen Oberfläche besteht darin, dass zunächst ein neues Gtk.Window-Objekt erzeugt wird (Zeile 3), das die gewünschten Widgets enthält. Interaktive Widgets werden üblicherweise mit bestimmten Funktionen verknüpft (Zeile 4), die aufgerufen werden, sobald durch eine Benutzeraktion das entsprechende Signal von dem Widget gesendet wird (hier wird das Fenster geschlossen, sobald der Benutzer in der Fensterleiste das ☒ zum Schließen des Fensters anklickt). Die Methode show_all() in Zeile 5 bewirkt die Anzeige sämtlicher definierter Widgets (hier lediglich das Fenster selbst). Schließlich wird in Zeile 6 die Hauptschleife der Anwendung gestartet, da das Programm ja nicht gleich wieder beendet werden soll, sobald alle Zeilen des Skripts durchlaufen wurden.

Quelltext auswählen
1
2
3
4
5
6
from gi.repository import Gtk

win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Unterklasse von GtkWindow #

Der übliche Weg, um mehr als nur ein relativ funktionsloses Fenster anzuzeigen, besteht darin, eine Unterklasse von GtkWindow zu bilden, in der dann die gesamte Funktionalität der angestrebten Anwendung implementiert wird.

Quelltext auswählen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from gi.repository import Gtk

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Hello World")
        self.set_icon_from_file("/usr/share/pixmaps/python.xpm")
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_default_size(200, 40)
        self.set_border_width(6)

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="World")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

    def on_button1_clicked(self, widget):
        print("Hello")

    def on_button2_clicked(self, widget):
        print("World")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Dieses Skript kann folgendermaßen erweitert werden, um die Fenstergröße und Position in der Datei myscript.conf zu speichern, wenn das Fenster geschlossen wird. So wird es mit den gespeicherten Werten beim erneuten Starten der Anwendung wieder geöffnet.

Quelltext auswählen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import os
from gi.repository import Gtk

class MyWindow(Gtk.Window):

    def __init__(self):
        
        self.thisdir = os.path.dirname(os.path.realpath(__file__)) + "/"
        self.config  = self.thisdir + "myscript.conf"
        
        Gtk.Window.__init__(self, title="Hello World")
        self.set_icon_from_file("/usr/share/pixmaps/python.xpm")
        self.set_position(Gtk.WindowPosition.CENTER)
        
        if os.path.exists(self.config) == True:
            d = open(self.config)
            content = d.read().split(",")
            d.close
            windowXsize = int(content[0])
            windowYsize = int(content[1])
            self.move(int(content[2]), int(content[3]))
        else:
            windowXsize = 200
            windowYsize = 40
            
        self.set_default_size(windowXsize, windowYsize)
        self.set_border_width(6)

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="World")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

    def on_button1_clicked(self, widget):
        print("Hello")

    def on_button2_clicked(self, widget):
        print("World")
        
def quit_window(self, widget):
    print("Goodbye!")
    wsize = self.get_size()
    wpos = self.get_position()
    out = str(wsize[0]) + "," + str(wsize[1]) + "," + str(wpos[0]) + "," + str(wpos[1])
    d = open(self.config, "w")
    d.write(out)
    d.close()
    Gtk.main_quit()

win = MyWindow()
win.connect("delete-event", quit_window)
win.show_all()
Gtk.main()