5.Contenedos de diseño

Si bien muchos kits de herramientas GUI requieren que coloque los widgets en una ventana con precisión, utilizando el posicionamiento absoluto,GTK+ utilizada un enfoque diferente. En lugar de especificar la posicion y el tamaño de cada widget en filas, columnas y/o tablas. El tamaño de la ventana se puede determinar automaticamente, en funcion de los tamaños de los widgets estan determinados por la cantidad de texto que contiene. A su vez, los tamaños de los widgets estan determinados por la cantidad de texto que contiene o por los tamñaños minimos y maximos que especifica y/o por como ha solicitado que el espacio disponible se comparta entre conjuntos de widgets. puede perfeccionar su diseño especificado la distancia de relleno y los valores de centrado para cada uno de sus Widgets. GTK+ luego utiliza toda esta informacion para cambiar el tamaño y reposicionar todo de forma sensata y suave cuando el usuario manipula la ventana.

GTK+ organiza los widgets de forma jerarquica, utilizando contenedores. Son invisibles para el usuario final y se insertan en una ventana o se colocan entre si a los componentes de diseño. Hay dos opciones de contenedores : contenedores de un solo hijo, que son todos decendientes de Gtk.Bin, y contenedores de varios hijos, que son decendientes de Gtk.Container. Las más utilizadas son las cajas verticales o horizontales(Gtk.Box) y las cuadriculas (Gtk.Grid).

5.1. Boxes(cajas)

Los boxes(cajas) son contenedores invisibles en los que podemos empaquetar nuestros widgets. Al embalar Widgets en una caja horizontal, los objetos se insertan horizontalmente a izquierda dependiendo de si se utiliza Gtk.Box.pack_start() o Gtk.Box.pack_end(). En una caja vertical, los widgets se empaquetan de arriba a abajo o viceversa. Puede utilzar cualquier combinacion de cajas dentro o al lado de otras caja para crear el efecto deseado.

5.1.1. Ejemplo

Echemos un vistazo a una version ligeramentes modificada del ejemplo extendido con dos botones.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Hello World")

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="Goodbye")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

    def on_button1_clicked(self, widget):
        print("Hello")

    def on_button2_clicked(self, widget):
        print("Goodbye")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

En primer lugar, creamos un contenedor de caja horizontalmente orientado donde 6 pixeles se colocan entre los children. Esta casilla se convierte en el hijo de la ventana de nivel superior.

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

Posteriormente, agregamos dos botones diferentes al contenedor de la caja.

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="Goodbye")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

Mientras que con los widgets Gtk.Box.pack_start()se posicionan de izquierda a derecha, Gtk.Box.pack_end()los posiciona de derecha a izquierda.

5.2.Grid(Cuadricula)

Gtk.Grid es un cotenedor que organiza sus widgets secundarios en filas y columnas, pero no es necesario espescificar las dimensiones en el constructor. Los children se agregan usandoGtk.Grid.attach() . Puede abarcar varias filas o columnas. Tambien es posible agragar un children junto a otro children existente, usando Gtk.Grid.attach_next_to().

Gtk.Grid se puede usar como un Gtk.Box con solo usar Gtk.Grid.add() , que colocara los children uno junto al otro en la direccion determinada por la propiedad "orientation" (por defecto a Gtk.Orientation.HORIZONTAL).

5.2.1 Ejemplo

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class GridWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Grid Example")

        grid = Gtk.Grid()
        self.add(grid)

        button1 = Gtk.Button(label="Button 1")
        button2 = Gtk.Button(label="Button 2")
        button3 = Gtk.Button(label="Button 3")
        button4 = Gtk.Button(label="Button 4")
        button5 = Gtk.Button(label="Button 5")
        button6 = Gtk.Button(label="Button 6")

        grid.add(button1)
        grid.attach(button2, 1, 0, 2, 1)
        grid.attach_next_to(button3, button1, Gtk.PositionType.BOTTOM, 1, 2)
        grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1)
        grid.attach(button5, 1, 2, 1, 1)
        grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1)

win = GridWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

5.3 ListBox (Cuadro de lista)

Un Gtk.ListBox es un contenedor vertical que contiene Gtk.ListBoxRowchildren. Estas filas pueden clasificarse y filtrarse de forma dinamica y los encabezados se pueden agregar dinamicamente dependiendo del contenido de la fila. Tambien permite el teclado y la navegacion del raton y la seleccion comouna lista tipica.

El uso de Gtk.ListBox es amenudo una alternativa a Gtk.TreeViewespecialmente cuando el contenido de la lista tiene un diseño mas complicado que lo que permiten un Gtk.CellRenderer o cuando el contenido es interactivo(es decir, tiene un boton en el).

Aunque un Gtk.ListBoxdebe tener solo Gtk.ListBoxRow children, puede agregar cualquier tipo de widget a el a traves de Gtk.Container.add() y un widget Gtk.ListBoxRow se insertara automaticamente entre la lista y el widget.

5.3.1 Ejemplo

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class ListBoxRowWithData(Gtk.ListBoxRow):
    def __init__(self, data):
        super(Gtk.ListBoxRow, self).__init__()
        self.data = data
        self.add(Gtk.Label(data))

class ListBoxWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="ListBox Demo")
        self.set_border_width(10)

        box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(box_outer)

        listbox = Gtk.ListBox()
        listbox.set_selection_mode(Gtk.SelectionMode.NONE)
        box_outer.pack_start(listbox, True, True, 0)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        label1 = Gtk.Label("Automatic Date & Time", xalign=0)
        label2 = Gtk.Label("Requires internet access", xalign=0)
        vbox.pack_start(label1, True, True, 0)
        vbox.pack_start(label2, True, True, 0)

        switch = Gtk.Switch()
        switch.props.valign = Gtk.Align.CENTER
        hbox.pack_start(switch, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        label = Gtk.Label("Enable Automatic Update", xalign=0)
        check = Gtk.CheckButton()
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(check, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        label = Gtk.Label("Date Format", xalign=0)
        combo = Gtk.ComboBoxText()
        combo.insert(0, "0", "24-hour")
        combo.insert(1, "1", "AM/PM")
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(combo, False, True, 0)

        listbox.add(row)

        listbox_2 = Gtk.ListBox()
        items = 'This is a sorted ListBox Fail'.split()

        for item in items:
            listbox_2.add(ListBoxRowWithData(item))

        def sort_func(row_1, row_2, data, notify_destroy):
            return row_1.data.lower() > row_2.data.lower()

        def filter_func(row, data, notify_destroy):
            return False if row.data == 'Fail' else True

        listbox_2.set_sort_func(sort_func, None, False)
        listbox_2.set_filter_func(filter_func, None, False)

        listbox_2.connect('row-activated', lambda widget, row: print(row.data))

        box_outer.pack_start(listbox_2, True, True, 0)
        listbox_2.show_all()

win = ListBoxWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

5.4. Stack and StackSwicher

Un Gtk.Stack es un cotenedor que solo muestra a uno de sus children a la vez. En contraste con Gtk.Notebook, Gtk.Stack no proporciona un medio para que los usuarios cambien el children visible. En su lugar, el widget Gtk.StackSwitcherse puede utilizar con Gtk.Stack para propocionar esta funcionalidad.

Las transiciones entre paginas se pueden animar como diapositivas o se desvanece. Esto se puede controlar con Gtk.Stack.set_transition_type() . Estas animaciones respetan el ajuste "gtk-enable-animations".

Velocidad de transicion se puede ajustar con Gtk.Stack.set_transition_duration()

Los widget Gtk.StackSwitcher actuá como un controlador para un Gtk.Stack ; que muestra una fila de botones para cambiar entre las diferentes páginas del widget pila asociada.

Todo el contenido de los botones proviene de las propiedades secundarias del Gtk.Stack.

Es posible asociar varios widgets Gtk.StackSwitcher con el mismo artilugio Gtk.Stack .

5.4.1. Ejemplo.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class StackWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Stack Demo")
        self.set_border_width(10)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(vbox)

        stack = Gtk.Stack()
        stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        stack.set_transition_duration(1000)

        checkbutton = Gtk.CheckButton("Click me!")
        stack.add_titled(checkbutton, "check", "Check Button")

        label = Gtk.Label()
        label.set_markup("<big>A fancy label</big>")
        stack.add_titled(label, "label", "A label")

        stack_switcher = Gtk.StackSwitcher()
        stack_switcher.set_stack(stack)
        vbox.pack_start(stack_switcher, True, True, 0)
        vbox.pack_start(stack, True, True, 0)

win = StackWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

5.5. HeaderBar (Barra de encabezado).

Un Gtk.HeaderBar es similar a un Gtk.Box horizontal, permite colocar a los children al principio o al final. Además, permite mostrar un titulo. El titulo se centrará con respecto al ancho de la caja, incluso si los Children en ambos lados ocupan diferentes cantidades de espacio.

Dado que GTK+ ahora soporta Client Side Decoration, se puede usar un Gtk.HeaderBar en lugar de la barra de título ( que es renderizada por Window Manager).

Un Gtk.HeaderBar normalmente se encuentra en la parte superior de una ventana y debe contener controles de uso común que afectan al contenido de abajo. Tambien proporcionan acceso a los controles de la ventana, incluyendo el botón de cierre de la ventana y el menú de la ventana.

5.5.1. Ejemplo

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio

class HeaderBarWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="HeaderBar Demo")
        self.set_border_width(10)
        self.set_default_size(400, 200)

        hb = Gtk.HeaderBar()
        hb.set_show_close_button(True)
        hb.props.title = "HeaderBar example"
        self.set_titlebar(hb)

        button = Gtk.Button()
        icon = Gio.ThemedIcon(name="mail-send-receive-symbolic")
        image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
        button.add(image)
        hb.pack_end(button)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        Gtk.StyleContext.add_class(box.get_style_context(), "linked")

        button = Gtk.Button()
        button.add(Gtk.Arrow(Gtk.ArrowType.LEFT, Gtk.ShadowType.NONE))
        box.add(button)

        button = Gtk.Button()
        button.add(Gtk.Arrow(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE))
        box.add(button)

        hb.pack_start(box)

        self.add(Gtk.TextView())

win = HeaderBarWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

5.6.FlowBox

Un Gtk.FlowBox es un contenedor que posiciona los widgets children en secuencia según su orientación.

Por ejemplo, con la orientación horizontal, los widgets se organizaran de izquierda a derecha, comenzando una nueva fila debajo de la fila anterior cuando sea necesario. Reducir el ancho en este caso requerirá más filas, por lo que se solicitará una altura mayor.

Del mismo nodo, con la orientación vertical los widgets se organizarán de arriba a abajo, comenzando una nueva columna ala derecha cuando sea necesario. Reducir la altura requerirá más columnas, por lo que se solicitará una anchura mayor.

Los children de un Gtk.FlowBox se pueden ordenar dinámicamente y filtrar.

Aunque un Gtk.FlowBox debe tener sólo los children Gtk.FlowBoxChild puede agregar cualquier tipo de widget a él a través de Gtk.Container.add() y un widget Gtk.FlowBoxChild se insertará automáticamente entre el cuadro y el widget.

5.6.1. Ejemplo.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

class FlowBoxWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="FlowBox Demo")
        self.set_border_width(10)
        self.set_default_size(300, 250)

        header = Gtk.HeaderBar(title="Flow Box")
        header.set_subtitle("Sample FlowBox app")
        header.props.show_close_button = True

        self.set_titlebar(header)

        scrolled = Gtk.ScrolledWindow()
        scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)

        flowbox = Gtk.FlowBox()
        flowbox.set_valign(Gtk.Align.START)
        flowbox.set_max_children_per_line(30)
        flowbox.set_selection_mode(Gtk.SelectionMode.NONE)

        self.create_flowbox(flowbox)

        scrolled.add(flowbox)

        self.add(scrolled)
        self.show_all()

    def color_swatch_new(self, str_color):
        color = Gdk.color_parse(str_color)

        rgba = Gdk.RGBA.from_color(color)
        button = Gtk.Button()

        area = Gtk.DrawingArea()
        area.set_size_request(24, 24)
        area.override_background_color(0, rgba)

        button.add(area)

        return button

    def create_flowbox(self, flowbox):
        colors = [
        'AliceBlue',
        'AntiqueWhite',
        'AntiqueWhite1',
        'AntiqueWhite2',
        'AntiqueWhite3',
        'AntiqueWhite4',
        'aqua',
        'aquamarine',
        'aquamarine1',
        'aquamarine2',
        'aquamarine3',
        'aquamarine4',
        'azure',
        'azure1',
        'azure2',
        'azure3',
        'azure4',
        'beige',
        'bisque',
        'bisque1',
        'bisque2',
        'bisque3',
        'bisque4',
        'black',
        'BlanchedAlmond',
        'blue',
        'blue1',
        'blue2',
        'blue3',
        'blue4',
        'BlueViolet',
        'brown',
        'brown1',
        'brown2',
        'brown3',
        'brown4',
        'burlywood',
        'burlywood1',
        'burlywood2',
        'burlywood3',
        'burlywood4',
        'CadetBlue',
        'CadetBlue1',
        'CadetBlue2',
        'CadetBlue3',
        'CadetBlue4',
        'chartreuse',
        'chartreuse1',
        'chartreuse2',
        'chartreuse3',
        'chartreuse4',
        'chocolate',
        'chocolate1',
        'chocolate2',
        'chocolate3',
        'chocolate4',
        'coral',
        'coral1',
        'coral2',
        'coral3',
        'coral4'
        ]

        for color in colors:
            button = self.color_swatch_new(color)
            flowbox.add(button)


win = FlowBoxWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

5.7. Notebook

El widget Gtk.Notebookes un Gtk.Container cuyo children hijos son páginas que se pueden cambiar entre usar etiquetas de pestañas a lo largo de un borde.

Hay muchas opciones de configuración para GtkNotebook. Entre otras cosas, puede elegir en que borde aparecen las pestañas(vea Gtk.Notebook.set_tab_pos()) , si si hay demasiadas pestañas para encajar en el cuaderno, debe hacerse más grande o se pueden agregar flechas de desplazamiento (consulte Gtk.Notebook.set_scrollable() ) y si habrá un menú emergente que permita a los usuarios cambiar páginas (ver Gtk.Notebook.popup_enable(), Gtk.Notebook.popup_disable()).

5.7.1.Ejemplo

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Simple Notebook Example")
        self.set_border_width(3)

        self.notebook = Gtk.Notebook()
        self.add(self.notebook)

        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)
        self.page1.add(Gtk.Label('Default Page!'))
        self.notebook.append_page(self.page1, Gtk.Label('Plain Title'))

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        self.page2.add(Gtk.Label('A page with an image for a Title.'))
        self.notebook.append_page(
            self.page2,
            Gtk.Image.new_from_icon_name(
                "help-about",
                Gtk.IconSize.MENU
            )
        )

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

results matching ""

    No results matching ""