24. Application¶
Gtk.Application
täcker flera upprepande uppgifter som ett modernt program behöver så som att hantera flera instanser, D-Bus-aktivering, öppna filer, kommandoradstolkning, uppstart/nedstängning, menyhantering, fönsterhantering med mera.
24.1. Åtgärder¶
Gio.Action
är ett sätt att exponera varje enskild uppgift ditt program eller din komponent gör med ett namn. Dessa åtgärder kan inaktiveras/aktiveras vid körtid och de kan antingen aktiveras eller få ett tillstånd ändrat (om de innehåller tillstånd).
Orsaken för att använda åtgärder är att separera logiken från användargränssnittet. Till exempel så tillåter detta användning av en menyrad i OSX och en kugghjulsmeny i GNOME genom att helt enkelt referera namnet på en åtgärd. Den huvudsakliga implementationen av detta som du kommer att använda är Gio.SimpleAction
som kommer demonstreras senare.
Många klasser så som Gio.MenuItem
och Gtk.ModelButton
stöder egenskaper för att ställa in ett åtgärdsnamn.
Dessa åtgärder kan grupperas tillsammans i en Gio.ActionGroup
och då dessa grupper läggs till i en komponent med Gtk.Widget.insert_action_group()
kommer de få ett prefix. Exempelvis ”win” då de läggs till ett Gtk.ApplicationWindow
. Du kommer använda det fullständiga åtgärdsnamnet då du refererar till det, som ”app.about”, men då du skapar åtgärden kommer den bara vara ”about” tills den läggs till i programmet.
Du kan också väldigt lätt göra tangentbindningar för åtgärder genom att ställa in egenskapen accel i Gio.Menu
-filen eller genom att använda Gtk.Application.set_accels_for_action()
.
24.3. Kommandorad¶
Då du skapar ditt program tar det en flaggegenskap från Gio.ApplicationFlags
. Med denna kan du låta det hantera allting själv eller ha mer anpassat beteende.
Du kan använda HANDLES_COMMAND_LINE för att tillåta anpassat beteende i Gio.Application.do_command_line()
. Kombinera med Gio.Application.add_main_option()
för att lägga till anpassade alternativ.
Att använda HANDLES_OPEN kommer göra jobbet med att helt enkelt ta filargument åt dig och låta dig hantera det i Gio.Application.do_open()
.
Om ditt program redan är öppet kommer alla dessa sändas till den befintliga instansen om du inte använder NON_UNIQUE för att tillåta flera instanser.
24.4. Exempel¶
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | import sys import gi gi.require_version("Gtk", "3.0") from gi.repository import GLib, Gio, Gtk # This would typically be its own file MENU_XML = """ <?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="app-menu"> <section> <attribute name="label" translatable="yes">Change label</attribute> <item> <attribute name="action">win.change_label</attribute> <attribute name="target">String 1</attribute> <attribute name="label" translatable="yes">String 1</attribute> </item> <item> <attribute name="action">win.change_label</attribute> <attribute name="target">String 2</attribute> <attribute name="label" translatable="yes">String 2</attribute> </item> <item> <attribute name="action">win.change_label</attribute> <attribute name="target">String 3</attribute> <attribute name="label" translatable="yes">String 3</attribute> </item> </section> <section> <item> <attribute name="action">win.maximize</attribute> <attribute name="label" translatable="yes">Maximize</attribute> </item> </section> <section> <item> <attribute name="action">app.about</attribute> <attribute name="label" translatable="yes">_About</attribute> </item> <item> <attribute name="action">app.quit</attribute> <attribute name="label" translatable="yes">_Quit</attribute> <attribute name="accel"><Primary>q</attribute> </item> </section> </menu> </interface> """ class AppWindow(Gtk.ApplicationWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # This will be in the windows group and have the "win" prefix max_action = Gio.SimpleAction.new_stateful( "maximize", None, GLib.Variant.new_boolean(False) ) max_action.connect("change-state", self.on_maximize_toggle) self.add_action(max_action) # Keep it in sync with the actual state self.connect( "notify::is-maximized", lambda obj, pspec: max_action.set_state( GLib.Variant.new_boolean(obj.props.is_maximized) ), ) lbl_variant = GLib.Variant.new_string("String 1") lbl_action = Gio.SimpleAction.new_stateful( "change_label", lbl_variant.get_type(), lbl_variant ) lbl_action.connect("change-state", self.on_change_label_state) self.add_action(lbl_action) self.label = Gtk.Label(label=lbl_variant.get_string(), margin=30) self.add(self.label) self.label.show() def on_change_label_state(self, action, value): action.set_state(value) self.label.set_text(value.get_string()) def on_maximize_toggle(self, action, value): action.set_state(value) if value.get_boolean(): self.maximize() else: self.unmaximize() class Application(Gtk.Application): def __init__(self, *args, **kwargs): super().__init__( *args, application_id="org.example.myapp", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs ) self.window = None self.add_main_option( "test", ord("t"), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, "Command line test", None, ) def do_startup(self): Gtk.Application.do_startup(self) action = Gio.SimpleAction.new("about", None) action.connect("activate", self.on_about) self.add_action(action) action = Gio.SimpleAction.new("quit", None) action.connect("activate", self.on_quit) self.add_action(action) builder = Gtk.Builder.new_from_string(MENU_XML, -1) self.set_app_menu(builder.get_object("app-menu")) def do_activate(self): # We only allow a single window and raise any existing ones if not self.window: # Windows are associated with the application # when the last one is closed the application shuts down self.window = AppWindow(application=self, title="Main Window") self.window.present() def do_command_line(self, command_line): options = command_line.get_options_dict() # convert GVariantDict -> GVariant -> dict options = options.end().unpack() if "test" in options: # This is printed on the main instance print("Test argument recieved: %s" % options["test"]) self.activate() return 0 def on_about(self, action, param): about_dialog = Gtk.AboutDialog(transient_for=self.window, modal=True) about_dialog.present() def on_quit(self, action, param): self.quit() if __name__ == "__main__": app = Application() app.run(sys.argv) |