コンテンツにスキップ

GTKプログラミング

出典: フリー教科書『ウィキブックス(Wikibooks)』

GTKとは

[編集]

GTK (GIMP Toolkit) は、クロスプラットフォームのGUIツールキットです。主にLinuxデスクトップ環境で使用されていますが、WindowsやmacOSでも動作します。GNOMEデスクトップ環境の基盤として使用されており、多くのオープンソースアプリケーションで採用されています。

開発環境のセットアップ

[編集]

Linuxでのインストール

[編集]
# Ubuntu/Debian
sudo apt-get install libgtk-3-dev python3-gi python3-gi-cairo gir1.2-gtk-3.0

# Fedora
sudo dnf install gtk3-devel python3-gobject python3-cairo-devel

Pythonでの基本的なウィンドウ作成

[編集]
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class MainWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="My GTK App")
        self.connect("destroy", Gtk.main_quit)
        
        # ボックスレイアウトの作成
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(box)
        
        # ラベルの追加
        label = Gtk.Label(label="Welcome to GTK!")
        box.pack_start(label, True, True, 0)
        
        # ボタンの追加
        button = Gtk.Button(label="Click Me")
        button.connect("clicked", self.on_button_clicked)
        box.pack_start(button, True, True, 0)

    def on_button_clicked(self, widget):
        print("Button clicked!")

win = MainWindow()
win.show_all()
Gtk.main()

高度なウィジェットの実装

[編集]

フォーム with グリッドレイアウト

[編集]
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class FormWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Registration Form")
        self.set_border_width(10)
        
        # グリッドの作成
        grid = Gtk.Grid()
        grid.set_column_spacing(10)
        grid.set_row_spacing(10)
        self.add(grid)
        
        # 名前フィールド
        name_label = Gtk.Label(label="Name:")
        self.name_entry = Gtk.Entry()
        grid.attach(name_label, 0, 0, 1, 1)
        grid.attach(self.name_entry, 1, 0, 2, 1)
        
        # メールフィールド
        email_label = Gtk.Label(label="Email:")
        self.email_entry = Gtk.Entry()
        grid.attach(email_label, 0, 1, 1, 1)
        grid.attach(self.email_entry, 1, 1, 2, 1)
        
        # 送信ボタン
        submit_button = Gtk.Button(label="Submit")
        submit_button.connect("clicked", self.on_submit)
        grid.attach(submit_button, 1, 2, 1, 1)

    def on_submit(self, widget):
        name = self.name_entry.get_text()
        email = self.email_entry.get_text()
        dialog = Gtk.MessageDialog(
            parent=self,
            flags=0,
            message_type=Gtk.MessageType.INFO,
            buttons=Gtk.ButtonsType.OK,
            text=f"Submitted: {name} ({email})"
        )
        dialog.run()
        dialog.destroy()

win = FormWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

リストビューの実装

[編集]
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class ListViewWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="ListView Example")
        self.set_default_size(400, 300)
        
        # リストストアの作成
        self.store = Gtk.ListStore(str, str, int)
        self.store.append(["John", "Developer", 30])
        self.store.append(["Alice", "Designer", 28])
        self.store.append(["Bob", "Manager", 35])
        
        # ツリービューの作成
        tree = Gtk.TreeView(model=self.store)
        
        # カラムの追加
        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn("Name", renderer, text=0)
        tree.append_column(column)
        
        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn("Role", renderer, text=1)
        tree.append_column(column)
        
        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn("Age", renderer, text=2)
        tree.append_column(column)
        
        # スクロールウィンドウに追加
        scrolled = Gtk.ScrolledWindow()
        scrolled.add(tree)
        self.add(scrolled)

window = ListViewWindow()
window.connect("destroy", Gtk.main_quit)
window.show_all()
Gtk.main()

CSS Styling

[編集]
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

css = b"""
.custom-button {
    background-color: #4CAF50;
    color: white;
    border-radius: 5px;
    padding: 10px;
}
.custom-button:hover {
    background-color: #45a049;
}
.custom-label {
    color: #333;
    font-size: 18px;
    font-weight: bold;
}
"""

class StyledWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Styled GTK Window")
        self.set_border_width(20)
        
        # CSSプロバイダーの設定
        screen = Gdk.Screen.get_default()
        provider = Gtk.CssProvider()
        provider.load_from_data(css)
        Gtk.StyleContext.add_provider_for_screen(
            screen,
            provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )
        
        # ボックスレイアウト
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        self.add(box)
        
        # スタイル付きラベル
        label = Gtk.Label(label="Styled Components")
        context = label.get_style_context()
        context.add_class("custom-label")
        box.pack_start(label, True, True, 0)
        
        # スタイル付きボタン
        button = Gtk.Button(label="Styled Button")
        context = button.get_style_context()
        context.add_class("custom-button")
        box.pack_start(button, True, True, 0)

win = StyledWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

シグナルとイベント処理

[編集]
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib

class SignalsWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Signals Example")
        self.set_border_width(10)
        
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(box)
        
        self.progress = Gtk.ProgressBar()
        box.pack_start(self.progress, True, True, 0)
        
        button = Gtk.Button(label="Start Process")
        button.connect("clicked", self.on_start_clicked)
        box.pack_start(button, True, True, 0)
        
        self.timeout_id = None
        self.activity_mode = False

    def on_start_clicked(self, widget):
        if self.timeout_id is None:
            widget.set_label("Stop")
            self.activity_mode = False
            self.progress.set_fraction(0.0)
            self.timeout_id = GLib.timeout_add(100, self.on_timeout, None)
        else:
            widget.set_label("Start Process")
            GLib.source_remove(self.timeout_id)
            self.timeout_id = None
            self.progress.set_fraction(0.0)

    def on_timeout(self, user_data):
        new_value = min(1.0, self.progress.get_fraction() + 0.01)
        self.progress.set_fraction(new_value)
        
        if new_value >= 1.0:
            self.timeout_id = None
            return False
        
        return True

win = SignalsWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

応用とベストプラクティス

[編集]

アプリケーション構造化

[編集]
  • Gtk.Applicationの使用
  • UI定義ファイル(Glade)の活用
  • モジュール分割とMVCパターンの適用

パフォーマンス最適化

[編集]
  • ウィジェットの遅延作成
  • メモリ管理への注意
  • バックグラウンド処理の適切な実装

デバッグとテスト

[編集]
  • GTK Inspectorの活用
  • ユニットテストの実装
  • エラーハンドリング

GTKは豊富な機能セットと強力なウィジェットライブラリを提供しており、特にLinux環境での開発に適しています。また、CSSによるスタイリングやGladeを使用したUIデザインなど、モダンな開発手法もサポートしています。