Paepoi

Paepoi » GTK4(Python) Tips » GTK4(Python) Tips | ダイアログ

GTK4(Python) Tips | ダイアログ

# 最終更新日 2023.05.14

AlertDialog
4.10 で GtkMessageDialog は GtkAlertDialog に変わりました。
GtkDialog ベースではないので上に Widget を載せたりはできません。
引きかえにもの凄く単純化されました。
アラートを表示するだけならたったコレだけ、show の引数に親ウインドウを指定。
#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw

class Win(Gtk.ApplicationWindow):
    def __init__(self, a):
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        Gtk.ApplicationWindow.__init__(self, application=a)
        btn = Gtk.Button(label='Show Alert', halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER)
        btn.connect('clicked', self.on_button_clicked)
        self.set_child(btn)
        self.set_default_size(200, 100)

    def on_button_clicked(self, button):
        alert = Gtk.AlertDialog(message='メッセージ', detail='補足')
        alert.show(self)

app = Gtk.Application()
app.connect('activate', lambda a: Win(a).present())
app.run()
alert1.webp

また複数ボタンを配置して戻り値を得ることもできます。
AdwMessageDialog との住み分けが難しいかもしれませんが。
アチラは GtkWindow ベースなので上に Widget を載せ GtkDialog 代わりにも使える。
#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw

class Win(Gtk.ApplicationWindow):
    def __init__(self, a):
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        Gtk.ApplicationWindow.__init__(self, application=a)
        btn = Gtk.Button(label='Show Alert', halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER)
        btn.connect('clicked', self.on_button_clicked)
        self.set_child(btn)
        self.set_default_size(200, 100)

    def on_button_clicked(self, button):
        alert = Gtk.AlertDialog(message='どのカメラが好き?', detail='Esc でキャンセル')
        alert.set_buttons(['オリンパス', 'スマホで十分', '靴カメ', 'Cancel'])
        alert.set_default_button(0)
        alert.set_cancel_button(3)
        alert.choose(self, None, self.on_alert_dlg_callback)

    def on_alert_dlg_callback(self, dlg, res):
        try:
            num = dlg.choose_finish(res)
            match num:
                case 0:
                    self.set_title('青がイイね')
                case 1:
                    self.set_title('十分だよね')
                case 2:
                    self.set_title('通報します')
                case _:
                    self.set_title('Esc か Cancel')
        except Exception as e:
            self.set_title('set_cancel_button しないと Esc はココにくる')

app = Gtk.Application()
app.connect('activate', lambda a: Win(a).present())
app.run()
alert2.webp

FileDialog
GtkFileDialog は GtkFileChooserDialog の後継 Widget です。
open と save の振り分け及び複数選択指定はプロパティではなく関数になりました。
シグナルではなくコールバック関数にて処理になりましたが違いはあまり感じません。
#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio

WRITE_TEXT = 'Python 文字列は UTF-8 に変換する'.encode('utf8')

class Win(Gtk.ApplicationWindow):
    def __init__(self, a):
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        Gtk.ApplicationWindow.__init__(self, application=a)
        # Button
        button_open = Gtk.Button(label='_Open', use_underline=True)
        button_open.connect('clicked', self.on_button_open_clicked)
        button_save = Gtk.Button(label='_Save', use_underline=True)
        button_save.connect('clicked', self.on_button_save_clicked)
        # box
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.append(button_open)
        vbox.append(button_save)
        self.set_child(vbox)

    def on_button_open_clicked(self, button):
        dlg = Gtk.FileDialog()
        dlg.open(self, None, self.on_open_dlg_callback)

    def on_open_dlg_callback(self, dlg, res):
        try:
            f = dlg.open_finish(res)
            self.set_title(f.get_basename())
        except Exception as e:
            self.set_title('Cancel')

    def on_button_save_clicked(self, button):
        dlg = Gtk.FileDialog()
        dlg.save(self, None, self.on_save_dlg_callback)

    def on_save_dlg_callback(self, dlg, res):
        try:
            f = dlg.save_finish(res)
            stream = f.replace(None, False, Gio.FileCreateFlags.NONE)
            stream.write(WRITE_TEXT)
            stream.close()
        except Exception as e:
            self.set_title('Cancel')

app = Gtk.Application()
app.connect('activate', lambda a: Win(a).present())
app.run()
fileopen.webp

FileLauncher
GtkFileLauncher は GtkAppChooserDialog の後継 Widget です。
名前が紛らわしいと思うのは筆者だけなんだろうか?
#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio

PICFILE = './test.jpg'

class Win(Gtk.ApplicationWindow):
    '''
        GtkFileLauncher: Sample Code
    '''
    def __init__(self, a):
        # Set Adwaita Style
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        # init
        Gtk.ApplicationWindow.__init__(self, application=a)
        # button
        button = Gtk.Button(label='Launch test.jpg')
        button.connect('clicked', self.on_button_clicked)
        self.set_child(button)

    def on_button_clicked(self, button):
        f = Gio.File.new_for_path(PICFILE)
        # GtkFileLauncher
        launcher = Gtk.FileLauncher(file=f)
        launcher.launch(self, None, self.on_launch_finish)

    def on_launch_finish(self, launcher, res):
        try:
            result = launcher.launch_finish(res)
            if result:
                print('Success')
            else:
                print('Failed')
        except Exception as e:
            print(f'Launch Error: {e}')

app = Gtk.Application()
app.connect('activate', lambda a: Win(a).present())
app.run()
launch.webp

GtkAboutDialog
GtkAboutDialog は GTK3 時は GtkDialog ベースでしたが GtkWindow ベースに変わっています。
なので 4.10 以降でも残りますが AdwAboutDialog との住み分けはどうするのでしょう?

全部プロパティだけで設定可能、transient_for と modal の指定を忘れずに。
後は表示するだけで使えます。
#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw

class Win(Gtk.ApplicationWindow):
    def __init__(self, a):
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        Gtk.ApplicationWindow.__init__(self, application=a)
        btn = Gtk.Button(label='このアプリについて', halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER)
        btn.connect('clicked', self.on_button_clicked)
        self.set_child(btn)
        self.set_default_size(200, 100)

    def on_button_clicked(self, button):
        about = Gtk.AboutDialog(
            transient_for=self,
            modal = True,
            #logo = ***, # アイコン
            program_name = 'OM SYSTEM E-M5',
            version = '3.0.0',
            comments = 'OLYMPUS のカメラ事業は OM SYSTEM に変わりました',
            website = 'http://localhost/',
            website_label = 'localhost', # 指定しなければ「ホームページ」と表示
            copyright = 'Copyright(C) 2022 sasakima-nao',
            # 以下ライセンスボタン、指定しなければボタンは出ない
            license = Gtk.License.GPL_3_0, #'GPL',
            # 以下クレジットボタン、指定しなければボタンは出ない、配列に注意
            authors = ['sasakima-nao'],     # 開発担当
            artists = ['sasakima-nao'],     # アートワーク担当
            documenters = ['sasakima-nao'], # ドキュメント担当
            translator_credits = 'sasakima-nao' # 翻訳担当、ここは str
        )
        about.set_visible(True)

app = Gtk.Application()
app.connect('activate', lambda a: Win(a).present())
app.run()
gtkabout.webp

Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.