Glade y Tcl/Tk para la creación de interfaces gráficas
Desde hace ya un montón de tiempo, me viene rondando en la cabeza crear un aplicación para crear interfaces grácias en Tcl/Tk. Evidentemente, para que sea algo que pueda hacer en mi tiempo libre, tengo que apoyarme en herramientas ya existentes. Como tenía experiencia con GTK+ (cuando aún se llamaba así…) pensé en Glade, que aunque es una herramienta que no está mantenida, su versión 3.8 es una versión madura y la última que soporta integración con GTK-2, que tiene cierto parecido a Tk en sus tipos de widgets. Esto significa que se pueden utilizar sus XMLs para crear las interefaces, utilizando grid en la parte Tk.
La intención es evidente: ahorar tiempo en mis proyectos, y la GUI es parte de ello.
Widgets soportados
En principio los widgets soportados son:
- GtkWindow
- GtkBox
- GtkGrid
- GtkFrame
- GtkLabel
- GtkButton
- GtkEntry
- GtkCheckButton
- GtkRadioButton
- GtkComboBoxText
- GtkNotebook
- GtkTextView
- GtkScrolledWindow
- GtkSeparator
- GtkVBox
- GtkHBox
- GtkTable
- GtkHSeparator
- GtkVSeparator
que creo que son suficientes inicialmente.
De hecho, no los he probado todos y es más, la única prueba que he hecho es crear dos interfaces que se me han ocurrido (una de ellas la típica de TkDocs).
XML
Evidentemente hay que manejar ficheros XML y para ello tenemos varias opciones:
- tdom
- tcldom
pero no quería ligarme a ninguna, así que construí una capa por encima para ello (aunque al final siempre acabo usadon tdom… con lo que tiene pinta que esta decisión es sobreingeniería…).
La pinta de los XML es la siguiente (ejemplo simple).
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Nombre:</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">Enviar</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Por supuesto, la mayoría de las propiedades no las manejo (espero hacer eso más tarde), pero la estructura está ahí.
Glade
El aspecto en glade de las interfaces es esta:
y el resultado en Tcl/Tk
Una GUI algo más compleja (sacada de TkDocs):
y el resultado en Tcl/Tk
En este último caso, no recuerdo cómo hacer para que solo uno de los radio buttons esté activo… así que conforme está en Glade, sale en Tk.
Futuro
El futuro de esta aplicación resulta prometedor ya que los primeros tests han sido un éxito. Cierto es que la complejidad de las GUI creadas es muy bajo, pero todo parece apuntar a que el manejo de la jerarquía GUI es correcto.
Esta aplicación tiene solo un día de vida y tengo que revisar todo el código (lo que me llevará bastante tiempo), así que de momento queda solo para mi, pero, conforme vaya utilizándola y vea que puede servir a más gente, la haré pública para su uso (y extensión).