Una barra de menú usando XML y GtkBuilder.
Para crear la barra de menú usando XML:
Cree
Añada la siguiente línea en la parte superior del archivo:
<?xml version="1.0"? encoding="UTF-8"?>
Se quiere crear la interfaz que contendrá la barra de menú y sus submenús. Su barra de menú contendrá los submenús
<?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>
Ahora se crea el archivo .py y se usa «GtkBuilder» para importar el
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)
# a builder to add the UI designed with Glade to the grid:
builder = Gtk.Builder()
# get the file (if it is there)
try:
builder.add_from_file("menubar_basis.ui")
except:
print("file not found")
sys.exit()
# we use the method Gtk.Application.set_menubar(menubar) to add the menubar
# to the application (Note: NOT the window!)
self.set_menubar(builder.get_object("menubar"))
app = MyApplication()
exit_status = app.run(sys.argv)
sys.exit(exit_status)
Ahora ejecute la aplicación de Python. Se debería ver como la imagen en la parte superior de esta página.
Se empieza añadiendo 2 elementos al menú section
al submenú File
con estos elementos. El
<?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>
De esta misma manera puede añadirle un elemento Copy
y uno Paste
al submenú Edit
, y un elemento About
al submenú Help
.
Ahora se crean las acciones para «New» y «Quit», conectadas a una función de retorno de llamada en el archivo de Python; por ejemplo se crea «new» así:
new_action = Gio.SimpleAction.new("new", None)
new_action.connect("activate", self.new_callback)
Y se crea la función de retorno de llamada de «new» como
def new_callback(self, action, parameter):
print "You clicked \"New\""
Ahora, en el archivo XML, se conectan los elementos del menú a las acciones en el archivo XML añadiendo el atributo «action»:
<item>
<attribute name="label">New</attribute>
<attribute name="action">app.new</attribute>
</item>
Tenga en cuenta que para una acción relativa a la aplicación, se usa el prefijo app.
; para acciones relativas a la ventana, se usa el prefijo win.
.
Finalmente, en el archivo de Python, se añade la acción a la aplicación o a la ventana: por ejemplo app.new
se añadirá a la aplicación en el método do_startup(self)
así:
self.add_action(new_action)
Consulte la para obtener una explicación más detallada sobre señales y retornos de llamada.
Anteriormente, se crearon las acciones «new» y «open» como parte de la clase «MyApplication». Las acciones que controlan la aplicación en sí, como «quit» deben crearse de manera similar.
Algunas acciones, como «copy» y «paste» trabajan con la ventana, no con la aplicación. Las acciones de ventanas deben crearse como parte de la clase de la ventana.
Los archivos de ejemplo completos contienen tanto acciones de aplicación como de ventana. Estas últimas son generalmente también las incluidas en el menú de la aplicación. No es una buena práctica incluir acciones de ventana en el menú de la aplicación. Con motivo de demostración, los archivos de ejemplo completos incluyen XML en el archivo de IU que crea el menú de la aplicación incluyendo elementos «New» y «Open», y estos están vinculados a las mismas acciones que los elementos de la barra de menú del mismo nombre.
Las líneas 30 a 80 inclusive del demuestran el código XML usado para crear la IU del menú
Las acciones creadas hasta ahora no tienen estado, esto significa que no mantienen o dependen de un estado dado por la acción en sí. Las acciones que necesita crear para el submenú «Choices», por otro lado, tienen estado. Un ejemplo de creación de una acción con estado es:
shape_action = Gio.SimpleAction.new_stateful("shape", GLib.VariantType.new('s'), GLib.Variant.new_string('line'))
donde las variables del método son: nombre, tipo de parámetro (en este caso, una cadena: consulte aquí para una lista completa de significados de caracteres), estado inicial (en este caso, «line»; en el caso de un valor booleano True
debería ser Glib.Variant.new_boolean(True)
, y así sucesivamente, consulte aquí para ver una lista completa).
Después de haber creado la «SimpleAction» con estado se conecta a su función de retorno de llamada y se añade a la ventana (o la aplicación, si es el caso), como antes:
shape_action.connect("activate", self.shape_callback)
self.add_action(shape_action)
<?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>
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)
# action without a state created (name, parameter type)
copy_action = Gio.SimpleAction.new("copy", None)
# connected with the callback function
copy_action.connect("activate", self.copy_callback)
# added to the window
self.add_action(copy_action)
# action without a state created (name, parameter type)
paste_action = Gio.SimpleAction.new("paste", None)
# connected with the callback function
paste_action.connect("activate", self.paste_callback)
# added to the window
self.add_action(paste_action)
# action with a state created (name, parameter type, initial state)
shape_action = Gio.SimpleAction.new_stateful(
"shape", GLib.VariantType.new('s'), GLib.Variant.new_string('line'))
# connected to the callback function
shape_action.connect("activate", self.shape_callback)
# added to the window
self.add_action(shape_action)
# action with a state created
about_action = Gio.SimpleAction.new("about", None)
# action connected to the callback function
about_action.connect("activate", self.about_callback)
# action added to the application
self.add_action(about_action)
# callback function for copy_action
def copy_callback(self, action, parameter):
print("\"Copy\" activated")
# callback function for paste_action
def paste_callback(self, action, parameter):
print("\"Paste\" activated")
# callback function for 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)
# callback function for about (see the AboutDialog example)
def about_callback(self, action, parameter):
# a Gtk.AboutDialog
aboutdialog = Gtk.AboutDialog()
# lists of authors and documenters (will be used later)
authors = ["GNOME Documentation Team"]
documenters = ["GNOME Documentation Team"]
# we fill in the 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")
# to close the aboutdialog when "close" is clicked we connect the
# "response" signal to on_close
aboutdialog.connect("response", self.on_close)
# show the aboutdialog
aboutdialog.show()
# a callback function to destroy the 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):
# FIRST THING TO DO: do_startup()
Gtk.Application.do_startup(self)
# action without a state created
new_action = Gio.SimpleAction.new("new", None)
# action connected to the callback function
new_action.connect("activate", self.new_callback)
# action added to the application
self.add_action(new_action)
# action without a state created
quit_action = Gio.SimpleAction.new("quit", None)
# action connected to the callback function
quit_action.connect("activate", self.quit_callback)
# action added to the application
self.add_action(quit_action)
# action with a state created
state_action = Gio.SimpleAction.new_stateful(
"state", GLib.VariantType.new('s'), GLib.Variant.new_string('off'))
# action connected to the callback function
state_action.connect("activate", self.state_callback)
# action added to the application
self.add_action(state_action)
# action with a state created
awesome_action = Gio.SimpleAction.new_stateful(
"awesome", None, GLib.Variant.new_boolean(False))
# action connected to the callback function
awesome_action.connect("activate", self.awesome_callback)
# action added to the application
self.add_action(awesome_action)
# a builder to add the UI designed with Glade to the grid:
builder = Gtk.Builder()
# get the file (if it is there)
try:
builder.add_from_file("menubar.ui")
except:
print("file not found")
sys.exit()
# we use the method Gtk.Application.set_menubar(menubar) to add the menubar
# and the menu to the application (Note: NOT the window!)
self.set_menubar(builder.get_object("menubar"))
self.set_app_menu(builder.get_object("appmenu"))
# callback function for new
def new_callback(self, action, parameter):
print("You clicked \"New\"")
# callback function for quit
def quit_callback(self, action, parameter):
print("You clicked \"Quit\"")
sys.exit()
# callback function for state
def state_callback(self, action, parameter):
print("State is set to", parameter.get_string())
action.set_state(parameter)
# callback function for 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)
Las etiquetas pueden contener atajos. Los atajos son caracteres subrayados en la etiqueta, usados para navegar con el teclado. Se crean poniendo un guión bajo antes del carácter de atajo. Por ejemplo «_Archivo» en lugar de solo «Archivo» en el atributo «label» del «menubar.ui».
Los atajos son visibles cuando pulsa la tecla
Los aceleradores pueden añadirse explícitamente en las definiciones de la IU. Por ejemplo, es común poder cerrar una aplicación presionando
<attribute name="accel"><Primary>q</attribute>
creará la secuencia Quit
. Aquí, «Primary» se refiere a la tecla
<item>
<attribute name="label">_Quit</attribute>
<attribute name="action">app.quit</attribute>
<attribute name="accel"><Primary>q</attribute>
</item>
Dado que las aplicaciones de GNOME se traducen a muchos idiomas, es importante que las cadenas en su aplicación puedan traducirse. Para hacer una etiqueta traducible, simplemente añada translatable="yes"
:
<attribute name="label" translatable="yes">Quit</attribute>
En este ejemplo se usa lo siguiente:
GSimpleAction
GtkBuilder