Aplicaciones de escritorio con Ruby + Gtk

Hace poco en las reuniones mensuales de RubyLit, surgió el tema de la inexistencia de aplicaciones como Delphi o C++ Builder para hacer aplicaciones gráficas en GNU/Linux puntualmente con Ruby o Python. La realidad es que cuando uno se introduce al mundo del SL ve que las cosas están pensadas de una manera bastante distinta. Las suites integradas a veces resultan hasta antipáticas, y muchas de las aplicaciones estan pensadas no para ser utilizadas con un solo lenguaje, sino para varios. Sacrificando quizás las comodidades circunstanciales ( doble click en un widget para editar el código del evento ) por ventajas más interesantes como la utilización de una API similar y bindings para docenas de lenguajes ( como es el caso de GTK+).

A veces la ambición parece extrema, pero el caso es que eventualmente siempre resulta ventajosa.

Investigando un poco, me puse a ver si realmente era mucho más trabajoso hacer una aplicación GUI con Ruby en Linux y resulta que no solo no lo es, sino que el resultado es muy bueno y la capacidad de poder editar la interfaz como se nos venga la gana ( o aún más, permitir al usuario editarla como se le venga la gana sin modificar código) es genial.

A continuación un breve ejemplo de crear una aplicación con glade (es un cliente del api rest de redmine en que estoy trabajando):

necesitaremos la gema gtk3 y Glade

Primero creamos un nuevo archivo con glade y definimos los handlers que determinaran que hacer cada vez que el widget emite una señal, es importante guardar el archivo como .ui ya que así podremos utilizar directamente Gtk::Builder para leerlo, de otro modo necesitaríamos utilizar la librería glade

source: imgur.com

 Luego en nuestro programa:

#!/usr/bin/env ruby

require 'gtk3'

 

class MinerApp

  def initialize

    @ui = Gtk::Builder.new  

    @ui.add_from_file "ui/blueminer.ui"

    @ui.connect_signals {|handler| method(handler)}

 

````    @main_window = @ui.get_object "mainwindow"

    @main_window.signal_connect "destroy" do

     Gtk.main_quit

    end

 

    @main_window.show_all 

  end

 

  def about_menuitem_activate_cb  

    dialog = @ui.get_object "aboutdialog1" 

     dialog.run #ejecutamos el dialogo

    dialog.hide

  end

end

Aquí lo que hacen algunas lineas:

    @ui = Gtk::Builder.new  

    @ui.add_from_file “ui/blueminer.ui”

instanciamos el objeto UI, y cargamos el archivo .ui este nos permite obtener instancias de nuestro widget ya definido.

    @ui.connect_signals {|handler| method(handler)}

esta es una linea interesante, aquí le pasamos un bloque que asigna a cada handler el método o función correspondiente, en este caso le estamos diciendo que llame un método de la clase actual que se llame igual que el handler, nótese que esto puede no ser lo ideal, ya que hace todos los metodos de la clase activables a través del nombre del handler. Pero resulta conveniente para este caso.

   @main_window = @ui.get_object "mainwindow"

   @main_window.show_all

Acá obtenemos el objeto por el identificador (ID) que le pusimos en el archivo glade, por defecto este es “window1”. Luego llamamos el método show_all que muestra la ventana y redibuja todos sus contenidos.

 

 

  def about_menuitem_activate_cb  

    dialog = @ui.get_object "aboutdialog1" 

     dialog.run #ejecutamos el dialogo

     dialog.hide

  end

 

Si vemos la imagen, veremos que tengo definido un handler “about_menuitem_activate_cb” para el item de menu “Acerca de” y la señal “activate”, este es el método que responde a dicho evento. Los dialogos Gtk se suelen ejecutar con el método run, que devuelve una respuesta de tipo Gtk::ResponseType al cerrar el dialogo, en este caso no queremos evaluar la respuesta ya que es solo un dialogo de información.

 

Finalmente instanciamos nuestra aplicación e inicializamos el loop Gtk

 

Gtk.init

miner = MinerApp.new

Gtk.main

 

El resto es simplemente continuar definiendo handlers para las señales en glade 

 Les dejo además estos tutorialesmuy completos para Ruby y otros lenguajes

 

Pronto voy a subir esta app en mi repo github

 

Edit: Cuando usamos Gtk::Builder deberemos ocultar los dialogos luego de su ejecución en vez de destruirlos con destroy(), ya que a diferencia de al crearlos con Gtk::Dialog.new estamos destruyendo una referencia y al intentar abrir el diálogo nuevamente el programa lanzará una excepción.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket