miércoles, 23 de octubre de 2013

Tutorial python Gtk3 botones y layouts

Si vieron el script que programe hace unos días se habrán dado cuenta que use un programa muy útil que se llama zenity,este programa nos crea ventanas fácilmente para usarlas en script's de shell,eso lo menciono porque existen niveles de programación y lo que seria zenity seria muy alto,no muy alto de que es muy buen coder el que lo usa si no de que esta muy preparado para usarse lo cual nos quita la capacidad de personalización por asi decirlo ya que trae hechas las GUI que podemos usar,las cuales nos devuelven un valor,si nos damos cuenta cuando ya lleven por lo menos otro tutorial ademas de este sera muy facil programar un zenity propio para usarlo en scripts en bash,ya que la programación de Gtk desde python es mas bajo nivel que la de zenity,ya que nos permite armar todo un front end,con botones,menus,notebooks,texviews,etc.

En este caso veremos lo que es botones y layouts,para poder armar una pequeña GUI,lo mas importante serian los layouts o contenedores ya que es lo que le da forma al programa,primero vamos a ver lo mas básico para ir fusionandolo entre si:

VBOX

Una vbox(Caja vertical) es un widget que almacena otros widgets adentro de ella de manera vertical,por defecto los widgets que se añaden a la ventana son solo uno,si añadimos mas colapsamos el programa.

Una pequeña pausa:

El esqueleto de los programas de python+Gtk3 debe ser siempre este(por lo menos en estos tutoriales):


#!/usr/bin/env python3

# -*- coding: utf-8 -*- # Codificacion
from gi.repository import Gtk # Importacion de Gtk

class CLase(Gtk.Window): # Una Clase principal que herede Window
    def __init__(self): # Constructor de la clase
        Gtk.Window.__init__(self,title="Titulo de la ventana") # Constructor de la clase padre

obje = EjemploRadioB() # Objeto creado de clase principal

obje.connect("delete-event",Gtk.main_quit) # Metodo de cerrar ventana

obje.show_all() # Mostramos todo

Gtk.main() # Bucle que mantiene abierta la ventana


Bien veamos un ejemplo de como añadiríamos un botón:


#!/usr/bin/env python3

# -*- coding: utf-8 -*-
from gi.repository import Gtk

class Ejemplo(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self,title="Ejemplo de un boton")
        button = Gtk.Button("Un boton")
        self.add(button)
     
ejem = Ejemplo()

ejem.connect("delete-event",Gtk.main_quit)

ejem.show_all()

Gtk.main()


Ahora veamos como usarlos VBOX para añadir mas botones de forma vertical:

Para empezar un objeto tipo caja se define de esta manera (objeto = Gtk.Box()) no importa si es en forma vertical o horizontal,a ese objeto le podemos pasar unos parametros,definiendolos por nombre para no cometer errores de posicion de parametros,por ejemplo podemos poner el espacio entre cada widget que almacenaremos,(pixeles) y entre ello tambien tenemos el parametro orientacion que es el que nos interesa,como python es orientado a objetos la orientacion de la caja no es una excepción debemos definir primero una lista para que no se vea tan largo el codigo(esto es opcional ya que asi lo hago yo):

pos = [Gtk.Orientation.HORIZONTAL,Gtk.Orientation.VERTICAL]
Ahi tenemos una lista con los valores de horizontal y vertical,esto es un poco raro pero asi me gusta hacerlo por si debemos intercambiar el valor solo cambiamos la forma de las constantes,por ejemplo:

pos = [Gtk.Orientation.VERTICAL,Gtk.Orientation.VERTICAL]

Para no andar cambiando una por una.

Ahora vamos a pasarle el parametro a la caja para que sea vertical(por defecto es horizontal):

vbox = Gtk.Box(spacing=5,orientation=pos[0])
Con eso tenemos un objeto vbox y podemos usar todos sus atributos,otra cosa es que esto ya se supone que se debe saber para el nivel de estos tutoriales,pero no lo he comentado es que en python usamos funciones de objetos similares a beans ,lo cual hace que algunos atributos que le podamos pasar como parámetros también tengan funciones que simplemente sirven para cambiarlos,por ejemplo es lo mismo esto:

vbox = Gtk.Box(spacing=5,orientation=pos[0])
Que esto:


vbox = Gtk.Box()
vbox.set_spacing(5)
vbox.set_orientation(pos[0])

Bien,eso se debe estudiar mas a fondo pero por el momento creo que se entiende,ahora vamos a ver las funciones que añaden los widgets,el cual son dos:

pack_start(widget,expand,fill,padding)

Esta funcion sirve para añadir widgets de principio a fin,osea desde el primero o el que sigue del ultimo que añadimos,le tenemos que pasar algunos parametros los cuales son:

widget # Un widget

expand # Un booleano para decir si se va a expandir basado en el widget que lo acompaña

fill # Un booleano para decir si se va a rellenar basado en la ventana

padding # Un numero entero,es contrario a spacing,añade espacio del otro lado.

También contamos con pack_end():

pack_start(widget,expand,fill,padding)

Tiene los mimos parametros,solo que se añade del final,osea al final de derecha a izquierda.

Bien como nos queda el codigo?

Primero vamos a ver como crear un botón normal para que podamos meterlo en :

Un objeto boton se define de la siguiente manera:

boton = Gtk.Button()
Le podemos pasar varios parámetros desde la creación o con funciones,por ejemplo el texto que mostrara(label) un stock(icono) y otros mas complejos como toltips(texto que se muestra cuando pasamos el cursor por arriba de un widget).

Un boton normal seria asi:

boton = Gtk.Button("Un boton")
De esa manera le estamos pasando un parámetro el cual es la label Un botón,no hay problema de hacerlo así ya que es el primer parámetro,pero también lo podríamos hacer así:

boton = Gtk.Button(label="Un boton")
O así:

boton = Gtk.Button()

boton.set_label("Un boton")

Un simple boton tiene muchas funciones,yo del metodo autodidacta que uso les recomiendo que vean las funciones que tiene usando dir:

Por ejemplo:


class Ejemplo(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self,title="Funciones de boton")
        self.button = Gtk.Button(label="Un boton",use_underline=False)
        for i in dir(self.button):
            print i
        self.add(self.button)

ejem =  Ejemplo()

ejem.connect("delete-event",Gtk.main_quit)

ejem.show_all()

Gtk.main()

Lo ejecutan y en la terminal les salen todas las funciones asociadas a esa clase,luego ya solo vemos que parametros usan o googleamos por informacion.

Antes de ver el codigo final queda repasar lo que vimos en la entrada pasada,un widget envia señales las cuales manipulamos con funciones,asi que una buena forma de programacion seria definir el objeto,luego definir sus funciones(si las usamos),luego definir las funciones de sus señales y luego añadirlas a una caja,por ejemplo:


boton = Gtk.Button() # Definicion 
boton.set_label("Boton 1") # Una que otra funcion del objeto
boton.connect("clicked", self.clic, "1") # Señales
vbox.pack_start(boton, False, False, 0) # Añadimos

Bien vamos a ver nuestro ejemplo de una ventana con dos botones:
Enlace


Como vemos se crea una ventana con dos botones en forma vertical,sobre su contrario,que seria hbox(caja horizontal),no hay mucho que explicar solo se tiene que definir que es horizontal o no pasarle el parámetro de orientation,también podemos anidar cajas dentro de cajas,por ejemplo dos cajas verticales dentro de una horizontal:

Enlace

Ahora vamos a ver otros tipos de botones:

RadioButton,el botón radio o botones redondos son muy vistos en algunos programas para elegir una opción,yo mismo los he usado en algunas ocasiones,pero si no los conocen son aquellos que tienen varias opciones pero cuando elegimos opción, cambia a esta y las otras quedan libres,para crear uno de estos botones primero necesitamos saber usar cajas como las de arriba lo cual ya vimos asi que vamos a comenzar creado una caja horizontal para añadir nuestros botones:

hbox = Gtk.Box(spacing=10)

Para definir el primer boton lo hacemos así:

rb = Gtk.RadioButton() # rb es radio button

Le tenemos que pasar algunos parámetros como la label y el grupo al que va a pertenecer,la label sera la opción que veremos,así que ponemos la que queramos y en grupo ponemos None ya que no hay grupo aun:

rb = Gtk.RadioButton(label="Ubuntu",group=None)

El segundo botón podemos añadirlo con la función new_from_widget,el cual le pasamos un parámetro que es el primer botón y así reconoce el grupo al que pertenece:

rb2 = Gtk.RadioButton.new_from_widget(rb1)

Luego podemos ponerle una label con la función set_label(muchos widgets tienen esta función):

rb2.set_label("Windows")

También podemos poner su señal que en este caso no es clicked si no que es toggled:

rb1.connect("toggled", self.clic, "Ubuntu")

Vamos a ver un ejemplo:

Enlace


Vamos a ver ahora el CheckButton,este botón también es muy conocido,ya que para configurar opciones,el cual es un botón con una paloma,si esta palomeado esta activa esa opción,si no no esta activa,es para definir solo dos opciones,ya que el radio button es para definir infinidad de opciones,para crearlo lo hacemos así:

Gtk.CheckButton(label="Hola mundo")

Luego también tenemos su señal que es toggled,y tenemos algunos beans para ver si esta activo:

set_active(boleano)

get_active() # Retorna boleano

Veamos un ejemplo:

Enlace


Hay otro botón que se parece mucho a este, el cual lo he visto en rhythmbox,el boton es el boton Toggled,el cual tiene las mismas funciones que el CheckButton pero con otro aspecto,para definirlo los hacemos así:

tb = Gtk.ToggleButton(label="Hola mundo",stock=Gtk.STOCK_ADD)

Veamos el mismo ejemplo:

Enlace


Otro botón con el que contamos y sirve para darle un poco de fama a nuestros programas es el link button el cual abre una uri,con el navegador que tengamos configurado por defecto en el sistema,(lo que seria xdg-open en linux),para definirlo solo le pasamos la label y la uri que mostrara,podemos hacerlo sin etiquetar los argumentos ya que el primero es la uri y el segundo es la label:

lb = Gtk.LinkButton("http://www.itimetux.com", "Ejemplo por Tiempo de Tux")

Por ejemplo:

Enlace



Por ultimo tenemos el boton spin,que es un tanto raro,ya que no lo he visto mucho,por ejemplo se podría usar para ajustar el tamaño de una fuente,el volumen de una aplicación,etc,pero no lo he visto mucho ya que para eso que mencione hay otros widgets dedicados,pero bueno,para definir un boton spin lo hacemos de la siguiente manera:

sb = Gtk.SpinButton()

Antes de usarlo tenemos que añadir un ajuste con otro widget,el cual se llama Adjustment,a este widget le pasamos algunos parámetros,el primero es el valor inicial(al abrir la ventana),el segundo es el valor mínimo(cuando le demos hacia atrás),el tercero es el valor máximo(hasta donde puede contar),el cuarto es de cuanto en cuanto va a contar,el quinto y sexto son argumentos mas avanzados los cuales no son muy necesarios,ya que con los primeros parámetros podemos hacer una cuenta normal,este widget lo usan otros ademas del spinbutton así que lo veremos de nuevo despumes,de momento vamos a definirlo así:

adjustment = Gtk.Adjustment(0, 0, 10, 2, 0, 0) # Comienza en 0,el mínimo es 0 y el máximo es 10,cuenta de 2 en 2

Las señales que otros widgets envía señales solo que son varias,la que podemos usar de ejemplo es value-changed,en la documentación oficial hay la información necesaria sobre señales,así que al final pondré el enlace,de momento podemos ver este ejemplo:


spinbutton = Gtk.SpinButton() # Definimos
spinbutton.set_adjustment(adjustment) # Añadimos el ajuste
spinbutton.connect("value-changed", self.clic,None) # Desviamos la señal a una funcion

Un ejemplo completo podría ser así:

Enlace


Ahora que ya conocemos los botones podemos pasar a ver las otras dos maneras de crear layouts,una de ellas es Grid,con la cual nos da una forma mas potente de añadir widgets que un box,primero definimos nuestro grid asi:

grid = Gtk.Grid()

Luego tenemos que añadir un widget(con la función add) para empezar,supongamos que tenemos un botón:

grid.add(boton)

Luego añadimos los otros con la función attach_next_to,a la cual le pasamos algunos parámetros:

attach_next_to(widget,despues,posicion,alto,ancho)

En widget ponemos el widget que vamos a añadir.

En después ponemos el widget del que queremos poner despues el widget del parametro 1.

En posición vamos a definir si va a estar arriba,abajo,izquierda o derecha,solo que vamos a usuar objetos especiales:

Gtk.PositionType.LEFT # Izquierda
Gtk.PositionType.RIGHT # Derecha
Gtk.PositionType.TOP # Arriba
Gtk.PositionType.BOTTOM # Abajo

En alto va a ser un dato int,el cual es el numero de widgets que estén disponibles,lo que seria las celdas a ocupar.

En ancho es igual que alto,solo que horizontal.

Veamos un ejemplo:

Enlace


Por ultimo tenemos el modo tabla,este es el mas avanzado de los tres,ya que manejamos celdas basadas en números,es como un tipo exel,o como un array de dos dimensiones,digamos que tenemos cuatro botones y queremos uno en cada esquina de la ventana,usando el método tabla tenemos que definir sus espacios basados en las celdas que ocupara cada widget:

Usamos la función attach y le pasamos algunos parámetros,el primero es el widget,pero los segundos son la celda que ocupara,basado en números:

izquierda, derecha, arriba, abajo

Primero creamos un objeto tabla con los parametros que serán el numero de filas y columnas para crear las celdas,supongamos 2x2:

table = Gtk.Table(2, 2, True) # El tercer parámetro es un bool 

Luego nos quedaría una ventana así:


Rojo es vertical y negro es horizontal.

Este es un ejemplo para que vean el modo de adición que vamos a usar.

Como vemos tenemos asignaciones numéricas,si quiero poner cuatro botones para que dibujen esa forma lo haría así:

Que el primer botón a la izquierda tenga cero para que este pegado a la izquierda,a la derecha tenga uno para que ocupe solo un espacio,que arriba comience en 0 para que este pegado a arriba,y abajo tenga 1 para que ocupe solo un espacio:

table.attach(boton1, 0, 1, 0, 1)

Ahora el segundo,que empiece en 1 a la izquierda,para que continue el espacio donde termina el primero,que a la derecha termine en 2,pegado a la otra orilla de la ventana,arriba y abajo es igual ya que usan la misma linea 0 y 1:

table.attach(boton2, 1, 2, 0, 1)

El tercer botón que empiece en 0 ya que estará pegado a la izquierda,a la derecha termine en 1,ya que es igual que el de arriba,arriba que comience en 1 para que este abajo del primero,y abajo termine en 2,pegado a la parte de abajo:

table.attach(boton3, 0, 1, 1, 2)

Por ultimo el cuarto que comience en 1,pegado al tercero,que termine en 2 a la derecha,pegado a la derecha,arriba y abajo es igual que el tercero 1 y 2:

table.attach(boton3, 1, 2, 1, 2)

Veamos el código entero:

Enlace



Es un poco raro,pero solo es cuestión de que se entienda como elegir las celdas de hecho Grid tambien cuenta con este modo de adición de widgets,con su función attach,pero quería mostrar el modo sencillo,también tenemos unas funciones para Table:

Estas son las que me gustan mas:

espacio = 10

table.set_row_spacings(espacio) # El espacio de serparacion de cada fila(pixeles)

table.set_col_spacings(espacio) # Eñ espacio de separacion de cada columna(pixeles)

Mas información el pagina oficial:

Enlace

developer.gnome.org/gtk3/stable/ch03.html 

6 comentarios:

  1. Hola Excelente tutorial
    Me pregunta si es posible crear un launcher atravez de python, Ya que quiero acceder mas facil a mis programas y/o documentos atravez del escritorio.

    ResponderBorrar
  2. Un launcher?

    No entiendo bien,si te refieres a un lanzador como el de windows o LXDE,etc o a otra cosa y para que entorno de escritorio seria?

    ResponderBorrar
  3. Buen tutorial ;) vi que usas java no tienes uno de java con gtk :)

    ResponderBorrar
  4. Java con Gtk es raro verlo,pero si,se puede.

    Yo no lo uso,tuve unos problemas los temas de decoración Gtk en el primer programa que hice y me decepciono,pero bueno te puedo poner de ejemplo el widget Table,primero necesitas instalar las librerias de Java + Gtk y agregar el .jar al IDE,luego solo usas este código,es sencillo y lo puedes complementar con el de python aqui visto:

    Enlace

    Saludos :D

    ResponderBorrar
  5. tutorial muy bien explicado!! podrias continuar por favor!!! estoy aprendiendo Gtk3 pero ay muy poca documentacion y para alguien nuevo es un poco complicado seguirle el paso al The Python GTK+ 3 Tutorial que esta en ingles!! espero puedas subir el siguiente pronto saludos...

    ResponderBorrar
  6. :D Gracias por comentar.

    De hecho estaba preparando uno que acabo de terminar,en el futuro abra mas:

    Enlace

    Saludos

    ResponderBorrar

Los comentarios serán revisados antes de ser publicados.