# MenuBar (Python)

Tiffany Antopolski
tiffany.antopolski@gmail.com 2012
Marta Maria Casetti
mmcasetti@gmail.com 2012
Widget, který sdružuje widgety GtkMenuItem.

# MenuBar vytvořený pomocí XML a GtkBuilder

MenuBar vytvořený pomocí XML a GtkBuilder.

# Vytvoření MenuBar pomocí XML

Abyste vytvořili nabídkovou lištu pomocí XML:

Pomocí svého oblíbeného textového editoru vytvořte menubar.ui.

Na začátek souboru vložte následující řádek:

<?xml version="1.0"? encoding="UTF-8"?>

Chceme vytvořit rozhraní, které bude obsahovat naši nabídkovou lištu a její podnabídky. Naše nabídková lišta bude obsahovat podnabídky Soubor, Upravit, Volby a Nápověda. Do souboru přidáme následující kód XML:

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> </submenu> <submenu> <attribute name="label">Edit</attribute> </submenu> <submenu> <attribute name="label">Choices</attribute> </submenu> <submenu> <attribute name="label">Help</attribute> </submenu> </menu> </interface>

Nyní vytvoříme soubor .py a použijeme GtkBuilder k naimportování souboru menubar.ui, který jsme před chvílí vytvořili.

# Přidání MenuBar do okna pomocí GtkBuilder

from gi.repository import Gtk import sys

class MyWindow(Gtk.ApplicationWindow):

def __init__(self, app): Gtk.Window.__init__(self, title="MenuBar Example", application=app) self.set_default_size(200, 200)

class MyApplication(Gtk.Application):

def __init__(self): Gtk.Application.__init__(self)

def do_activate(self): win = MyWindow(self) win.show_all()

def do_startup(self): Gtk.Application.do_startup(self)

# Builder pro přidání uživatelského rozhraní navrženého v Glade do mřížky builder = Gtk.Builder() # Získá soubor (pokud existuje) try: builder.add_from_file("menubar_basis.ui") except: print("file not found") sys.exit()

# Použije metodu Gtk.Application.set_menubar(nabídková_lišta) pro přídání # nabídkové lišty do aplikace (Upozornění: NE do okna!) self.set_menubar(builder.get_object("menubar"))

app = MyApplication() exit_status = app.run(sys.argv) sys.exit(exit_status)

Nyní aplikaci napsanou v jazyce Python spusťte. Měla by vypadat podobně, jako na obrázku na začátku této stránky.

# Přidání položek do nabídky

Začneme přidáním dvou položek nabídky do nabídky File: New a Quit. Provedeme to přidáním `oddílu` s těmito položkami do podnabídky `File`. Soubor menubar.ui by měl vypadat jako tento (řádky 6 až 13 včetně obsahují nově přidaný oddíl):

## menubar.ui

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> <section> <item> <attribute name="label">New</attribute> </item> <item> <attribute name ="label">Quit</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Edit</attribute> </submenu> <submenu> <attribute name="label">Choices</attribute> </submenu> <submenu> <attribute name="label">Help</attribute> </submenu> </menu> </interface>

Podle tohoto vzoru nyní můžete přidat položky Copy a Paste do podnabídky Edit a položku About do podnabídky Help.

# Nastavení akcí

Nyní vytvoříme akce pro „New“ a „Quit“ napojené na funkce zpětného volání v souboru .py. Například „new“ vytvoříme jako:

new_action = Gio.SimpleAction.new("new", None) new_action.connect("activate", self.new_callback)

A vytvoříme funkci zpětného volání pro „new“ jako

def new_callback(self, action, parameter): print "You clicked \"New\""

Nyní v souboru XML napojíme položky nabídky na akce v souboru XML přidáním atributu „action“:

<item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item>

Všimněte si, že pro akce, které se vztahují k aplikaci, používáme předponu `app.` a pro akce, které se vztahují k oknu, používáme předponu `win.`.

Nakonec v souboru .py přidáme akci do aplikace nebo do okna – například `app.new` bude přidáno do aplikace v metodě `do_startup(self)` jako

self.add_action(new_action)

Podrobnější vysvětlení signálů a zpětných volání viz .

# Akce: Aplikace nebo okno?

Výše jsme vytvořili akce `"new"` a `"open"` jako součást třídy `MyApplication`. Akce, které ovládají přímo aplikaci, jako je `"quit"` by se vytvořily podobně.

Některé akce, jako je `"copy"` (kopírovat) nebo `"paste"` (vložit) se vztahují k oknu a ne k aplikaci. Akce okna by měly být vytvářeny jako součást třídy okna.

Soubor s celým příkladem obsahuje jak akce aplikace, tak akce okna. Akce okna jsou obvykle zároveň i součástí aplikační nabídky. Není dobrým zvykem vkládat akce okna do aplikační nabídky. Pro předváděcí účely zahrnuje soubor s celým příkladem, který následuje, kód XML v souboru .ui, který vytvoří aplikační nabídku včetně položek `"New"` a `"Open"` a ty jsou zavěšeny na stejnou akci, jako položky nabídkové lišty se stejným názvem.

# Podnabídka „Choices“ a položky se stavem

Řádky 30 až 80 včetně v ukazují kód XML použitý k vytvoření uživatelského rozhraní pro nabídku Choices.

Dosud vytvořené akce jsou bezstavové, tj. takové, které si nepamatují stave nebo nezávisí na stavu akce samotné. Akce, které potřebujeme vytvořit pro podnabídku Choices jsou na druhou stranu stavové. Příkladem vytvoření stavové akce je:

shape_action = Gio.SimpleAction.new_stateful("shape", GLib.VariantType.new('s'), GLib.Variant.new_string('line'))

kde proměnné v metodě jsou: název, typ parametru (v tomto případě řetězec, úplný seznam s významem znaků viz zde), počáteční stav (v tomto případě `'line'`, v případě pravdivostní hodnoty `True` by to mělo být `Glib.Variant.new_boolean(True)` apod.; úplný seznam viz zde).

Po vytvoření stavové jednoduché akce ji napojíme na funkci zpětného volání a přidáme ji do okna (nebo do aplikace v některých případech), stejně jako dřív:

shape_action.connect("activate", self.shape_callback) self.add_action(shape_action)

# Celý soubor s uživatelským rozhraním ve formátu XML pro tento příklad

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> <section> <item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Edit</attribute> <section> <item> <attribute name="label">Copy</attribute> <attribute name="action">win.copy</attribute> </item> <item> <attribute name="label">Paste</attribute> <attribute name="action">win.paste</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Choices</attribute> <submenu> <attribute name="label">Shapes</attribute> <section> <item> <attribute name="label">Line</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">line</attribute> </item> <item> <attribute name="label">Triangle</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">triangle</attribute> </item> <item> <attribute name="label">Square</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">square</attribute> </item> <item> <attribute name="label">Polygon</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">polygon</attribute> </item> <item> <attribute name="label">Circle</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">circle</attribute> </item> </section> </submenu> <section> <item> <attribute name="label">On</attribute> <attribute name="action">app.state</attribute> <attribute name="target">on</attribute> </item> <item> <attribute name="label">Off</attribute> <attribute name="action">app.state</attribute> <attribute name="target">off</attribute> </item> </section> <section> <item> <attribute name="label">Awesome</attribute> <attribute name="action">app.awesome</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Help</attribute> <section> <item> <attribute name="label">About</attribute> <attribute name="action">win.about</attribute> </item> </section> </submenu> </menu> <menu id="appmenu"> <section> <item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item> </section> </menu> </interface>

# Kompletní soubor v jazyce Python pro tento příklad

from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gio import sys

class MyWindow(Gtk.ApplicationWindow):

def __init__(self, app): Gtk.Window.__init__(self, title="MenuBar Example", application=app) self.set_default_size(200, 200)

# Vytvoří bezstavovou akci (název, typ parametru) copy_action = Gio.SimpleAction.new("copy", None) # Napojí ji na funkci zpětného volání copy_action.connect("activate", self.copy_callback) # Přidá ji do okna self.add_action(copy_action)

# Vytvoří bezstavovou akci (název, typ parametru) paste_action = Gio.SimpleAction.new("paste", None) # Napojí ji na funkci zpětného volání paste_action.connect("activate", self.paste_callback) # Přidá ji do okna self.add_action(paste_action)

# Vytvoří stavovou akci (název, typ_parametru, počáteční_stav) shape_action = Gio.SimpleAction.new_stateful( "shape", GLib.VariantType.new('s'), GLib.Variant.new_string('line')) # Napojí ji na funkci zpětného volání shape_action.connect("activate", self.shape_callback) # Přidá ji do okna self.add_action(shape_action)

# Vytvoří stavovou akci about_action = Gio.SimpleAction.new("about", None) # Napojí ji na funkci zpětného volání about_action.connect("activate", self.about_callback) # Přidá ji do aplikace self.add_action(about_action)

# Funkce zpětného volání pro copy_action def copy_callback(self, action, parameter): print("\"Copy\" activated")

# Funkce zpětného volání pro paste_action def paste_callback(self, action, parameter): print("\"Paste\" activated")

# Funkce zpětného volání pro shape_action def shape_callback(self, action, parameter): print("Shape is set to", parameter.get_string()) # Note that we set the state of the action! action.set_state(parameter)

# Funkce zpětného volání pro about (viz příklad AboutDialog) def about_callback(self, action, parameter): # Gtk.AboutDialog aboutdialog = Gtk.AboutDialog()

# Seznam autorů kódu a dokumentace (bude použit později) authors = ["GNOME Documentation Team"] documenters = ["GNOME Documentation Team"]

# Vyplní AboutDialog aboutdialog.set_program_name("MenuBar Example") aboutdialog.set_copyright( "Copyright \xc2\xa9 2012 GNOME Documentation Team") aboutdialog.set_authors(authors) aboutdialog.set_documenters(documenters) aboutdialog.set_website("http://developer.gnome.org") aboutdialog.set_website_label("GNOME Developer Website")

# Napojí signál "response" na on_close, aby se zavřel # AboutDialog, když je kliknuto na "close" aboutdialog.connect("response", self.on_close) # Zobrazí AboutDialog aboutdialog.show()

# Funkce zpětného volání pro likvidaci AboutDialog def on_close(self, action, parameter): action.destroy()

class MyApplication(Gtk.Application):

def __init__(self): Gtk.Application.__init__(self)

def do_activate(self): win = MyWindow(self) win.show_all()

def do_startup(self): # PRVNÍ, CO SE MUSÍ UDĚLAT: do_startup() Gtk.Application.do_startup(self)

# Vytvoří bezstavovou akci new_action = Gio.SimpleAction.new("new", None) # Napojí ji na funkci zpětného volání new_action.connect("activate", self.new_callback) # Přidá ji do aplikace self.add_action(new_action)

# Vytvoří bezstavovou akci quit_action = Gio.SimpleAction.new("quit", None) # Napojí ji na funkci zpětného volání quit_action.connect("activate", self.quit_callback) # Přidá ji do aplikace self.add_action(quit_action)

# Vytvoří stavovou akci state_action = Gio.SimpleAction.new_stateful( "state", GLib.VariantType.new('s'), GLib.Variant.new_string('off')) # Napojí ji na funkci zpětného volání state_action.connect("activate", self.state_callback) # Přidá ji do aplikace self.add_action(state_action)

# Vytvoří stavovou akci awesome_action = Gio.SimpleAction.new_stateful( "awesome", None, GLib.Variant.new_boolean(False)) # Napojí ji na funkci zpětného volání awesome_action.connect("activate", self.awesome_callback) # Přidá ji do aplikace self.add_action(awesome_action)

# Builder, který přidá navrh uživatelského rozhraní z Glade do mřížky builder = Gtk.Builder() # Získá soubor (pokud existuje) try: builder.add_from_file("menubar.ui") except: print("file not found") sys.exit()

# Použije metodu Gtk.Application.set_menubar(menubar) pro přidání # nabídkové lišty a aplikační nabídky (Poznámka: NE do okna!) self.set_menubar(builder.get_object("menubar")) self.set_app_menu(builder.get_object("appmenu"))

# Funkce zpětného volání pro new def new_callback(self, action, parameter): print("You clicked \"New\"")

# Funkce zpětného volání pro quit def quit_callback(self, action, parameter): print("You clicked \"Quit\"") sys.exit()

# Funkce zpětného volání pro state def state_callback(self, action, parameter): print("State is set to", parameter.get_string()) action.set_state(parameter)

# Funkce zpětného volání pro awesome def awesome_callback(self, action, parameter): action.set_state(GLib.Variant.new_boolean(not action.get_state())) if action.get_state().get_boolean() is True: print("You checked \"Awesome\"") else: print("You unchecked \"Awesome\"")

app = MyApplication() exit_status = app.run(sys.argv) sys.exit(exit_status)

# Horké klávesy a klávesové zkratky

Popisky mohou obsahovat horké (mnemotechnické) klávesy. Mají podobu podtržených písmen v popiscích a používají se pro ovládání z klávesnice. Horké klávesy se vytváří umístěním podtržítka před příslušný znak. Například `"_File"` namísto `"File"` v atributu `label` v menubar.ui.

Horké klávesy jsou vidět, když zmáčknete klávesu Alt. Zmáčknutím Alt F otevřete nabídku File.

Klávesové zkratky mohou být přidány přímo do definicí uživatelského rozhraní. Například je běžné, že aplikaci lze ukončit zmáčknutím CtrlQ, nebo že lze uložit soubor zmáčknutím CtrlS. Pro přidání klávesové zkratky do definice uživatelského rozhraní stačí akorát přidat do položky atribut `"accel"`.

`<attribute name="accel">&lt;Primary&gt;q</attribute>` vytvoří sekvenci CtrlQ při přidávání položky `Quit`. „Primary“ má zde význam klávesy Ctrl na počítačích PC nebo klávesy ⌘ na počítačích Mac.

<item> <attribute name="label">_Quit</attribute> <attribute name="action">app.quit</attribute> <attribute name="accel">&lt;Primary&gt;q</attribute> </item>

# Přeložitelné řetězce

Protože aplikace GNOME jsou překládány do mnoha jazyků, je důležité, aby řetězce ve vaší aplikaci byly přeložitelné. U popisku to zajistíte jednoduše nastavením `translatable="yes"`:

<attribute name="label" translatable="yes">Quit</attribute>

# Odkazy k API

V této ukázce se používá následující:

GSimpleAction

GtkBuilder