Desarrollo de Interfaces Grá cas de Usuario con GTKmm

Anuncio
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Desarrollo de Interfaces Grácas de Usuario con
GTKmm
Software Freedom Day, Bogotá
Hugo Franco
Ubuntu-CO, Bioingenium (U.N.)
17 de septiembre de 2009
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Diseño de interfaces grácas de usuario bajo el enfoque orientado a objetos
1
Diseño de interfaces grácas de usuario bajo el enfoque
orientado a objetos
2
Usabilidad/Accessibilidad/Guías de diseño
3
Nociones de Autotools
4
Estructura de la API GTKmm
5
Taller
Generación de la aplicación básica en el EID Anjuta
Uso de controles de disposición y posicionamiento
Adición de funcionalidad a controles básicos
Implementación sencilla de aplicaciones con interfaz de
múltiples documentos.
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Diseño de interfaces grácas de usuario bajo el enfoque orientado a objetos
Diseño de Interfaces grácas de usuario mediante ADOO
Enfoque DocumentoVista
Abstracción de la ventana padre
para dar funcionalidad a la
aplicación
Uso intensivo de la herencia
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Usabilidad/Accessibilidad/Guías de diseño
Lineamientos a tener en cuenta en el diseño de una GUI
Líneas guía de GNOME en
http://library.gnome.org/devel/hig-book/stable/
Diseñar para la gente (usuario antes que desarrollador)
No limitar el público objetivo (accesibilidadidioma)
Relacionar la aplicación con el mundo real
Ser consistente en las estructuras de la GUI
Mantener informado al usuario (alertas, noticaciones)
Mantener las cosas simples (y agradables) KISS
Poner el usuario al mando
Perdonar al usuario (deshacer, guardar automáticamente)
Proveer manipulación directa
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Nociones de Autotools
Herramientas de desarrollo en *NIX Autotools
Tutorial completo en
http://www.seul.org/docs/autotut
Organizar archivos del código fuente
Crear archivos de conguración
congure.in
Makele.am
Ejecutar aclocal
Ejecutar autoheader
Ejecutar autoconf
Ejecutar automake (generalmente con la opción
−−add−missing)
Listo para usar la secuencia
./congure
make
sudo make install
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Estructura de la API GTKmm
Estructura de la API GTKmm
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Generación de la aplicación básica en el EID Anjuta
Creación del esqueleto de la aplicación
1
2
3
4
5
Abrir el Anjuta
Crear un proyecto C++→ escoger la opción gtkmm
Seleccionar carpeta del proyecto en
/home/ubuntu/Proyectos/nombre_proyecto
Editar el archivo src/main.cc para quitar el subdirectorio
de la macro GLADE_FILE
Construir el proyecto: generar con la conguración
"predeterminado"
src
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Generación de la aplicación básica en el EID Anjuta
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Generación de la aplicación básica en el EID Anjuta
Creación de la clase de la ventana principal
Ir al menú Archivo→Nuevo→Clase C++/GObject
Establecer nombre de la clase, miembros y atributos (derivada
de Gtk::Window)
Seleccionar objetivo (target) al que está asociada la clase
(nombre del proyecto) y aceptar (crea los archivos fuente)
Añadir gtkmm.h a archivo de cabecera de la clase
Añadir llamado del constructor de la clase base en el
constructor de la clase derivada (Parent)
Añadir archivo de cabecera a la función principal
Modicar el código de la función principal (main.cc) para usar
la clase derivada y no la obtenida mediante glade (borrar
bloque trycatch del glade).
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Generación de la aplicación básica en el EID Anjuta
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Uso de controles de disposición y posicionamiento
Las Clases Gtk::HPaned y GTK::VPaned
Añadir un Gtk::HPaned (a la aplicación en la declaración de la
clase Parent
Crear controles arbitrarios en el constructor del Parent
Gtk::Button *btn=new Gtk::Button("Botón de Prueba");
Gtk::Label *label=new Gtk::Label("Muestra de una etiqueta");
Añadir el Paned a la ventana para que se dibuje:
add(m_Paned);
Agregar los controles creados al Paned
m_Paned.add1(*btn);
m_Paned.add2(*label);
Repintar el Parent (control principal)
show_all_children();
Ejercicio: cambiar HPaned por VPaned y ver el resultado, cambiar
VPaned por HBox y VBox, añadiendo un control Gtk::Entry,
Gtk::CheckBox, Gtk::RadioButton
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Uso de controles de disposición y posicionamiento
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Uso de controles de disposición y posicionamiento
Contenedores anidados y Grupos I
Volver a HPaned. Añadir dos Gtk::VBox en la declaración de Parent
Gtk::VBox m_RadioBox;
Gtk::VBox m_ButtonBox;
Crear un grupo de radio y varios botones de radio en el constructor
de la clase Parent antes de añadir el Paned
Gtk::RadioButton::Group rbGrp;
Gtk::RadioButton *rb1=new Gtk::RadioButton(rbGrp,"1a. opción");
Gtk::RadioButton *rb2=new Gtk::RadioButton(rbGrp,"2a. opción");
Gtk::RadioButton *rb3=new Gtk::RadioButton(rbGrp,"3a. opción");
Añadir, tras el Paned, los RadioButtons a la primera VBox
m_RadioBox.add(*rb1);
m_RadioBox.add(*rb2);
m_RadioBox.add(*rb3);
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Uso de controles de disposición y posicionamiento
Contenedores anidados y Grupos II
Cambiar el botón y la etiqueta a la segunda caja vertical
m_ButtonBox.add(*btn);
m_ButtonBox.add(*label);
Por último, añadir de forma anidada cada box a una de las
mitades del Paned
m_Paned.add1(m_RadioBox);
m_Paned.add2(m_ButtonBox);
Ejercicio: añadir más cajas con otros controles, cambiar el orden,
anidar diferentes tipos de contenedores
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Uso de controles de disposición y posicionamiento
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Adición de funcionalidad a controles básicos
Controles básicos I
Uso de sigc::memfun con Gtk::Button
Declarar en el constructor de la clase Parent una función
handler de evento: void onButtonClicked()
Conectar la señal de click sobre el botón a la función handler
mediante
btn->signal_clicked().connect(
sigc::mem_(*this,&Parent::onButtonClicked));
La función signal_clicked, perteneciente al widget, devuelve la
señal asociada al evento click A su vez, la función connect
de dicha señal recibe el puntero a la función encargada de
manejar el evento click mediante sigc::memfun
(libsigc++ 2.0) , cuyos parámetros son:
referencia al objeto que manejará el evento
puntero a la función handler dentro de la clase a la que
pertenece ese objeto
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Adición de funcionalidad a controles básicos
Controles básicos: Gtk::Button II
Uso de Gtk::Label y Diálogos (Gtk::MessageDialog)
Convertir el label en el constructor en un atributo de la clase
parent (incluir Gtk::Label *m_label en el archivo parent.h)
Denición de la función handler del evento asociado al botón
void Parent::onButtonClicked(){
Gtk::MessageDialog md(*this,"¾Desea cerrar este ejemplo?",
false,Gtk::MESSAGE_QUESTION,Gtk::BUTTONS_OK_CANCEL);
int salida=md.run();
switch(salida){
case(Gtk::RESPONSE_OK):
hide();//oculta ventana principal→cierra la aplicación
break;
default: //Gtk::RESPONSE_CANCEL
m_label->set_text("Se presionó \"Cancelar\".");
break;
}//switch
}//onButtonClicked
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Adición de funcionalidad a controles básicos
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Creación de la ventana principal: Menú
Glib::RefPtr<Gtk::UIManager> y Glib::RefPtr<Gtk::ActionGroup>
La parte más truculenta
Tomar ejemplo inicial que incluye la clase Parent, en limpio
Denir título y tamaño: funciones set_title y set_default_size
Agregar en la declaración de la clase Parent un atributo de tipo
Gtk::VBox, además de un Gtk::Notebook y una Gtk::StatusBar
Agregar también un UI Manager
(Glib::RefPtr<Gtk::UIManager>) y un Action Group
(Glib::RefPtr<Gtk::ActionGroup>)
Adicionar en la parte pública de la declaración de la clase las
funciones handler de los eventos de menú: void onAbrir(), void
onCerrar(), void onSalir()
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Apariencia de la clase Parent
class Parent: public Gtk::Window
{
public:
Parent();
~Parent();
void onSalir();
void onAbrir();
void onCerrar();
void crearMenu();
protected:
Gtk::VBox m_vBox;
Gtk::Notebook *m_pClientArea;
Gtk::Statusbar *m_pSBar;
Glib::RefPtr<Gtk::UIManager> m_refUIManager;
Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
private:
};
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Funcionalidad del menú I
Denir la función crearMenu usando los atributos actionGroup y
UIManager
void Parent::crearMenu(){
m_refActionGroup = Gtk::ActionGroup::create();
m_refActionGroup->add(Gtk::Action::create("FileOpen",
Gtk::Stock::OPEN, "_Abrir", "Abre un archivo"),
sigc::mem_fun(*this, &Parent::onAbrir));
m_refActionGroup->add(Gtk::Action::create("FileClose",
Gtk::Stock::CLOSE, "_Cerrar", "Cierra un archivo"),
sigc::mem_fun(*this, &Parent::onCerrar));
m_refActionGroup->add(Gtk::Action::create("FileQuit",
Gtk::Stock::CLOSE, "_Salir", "Termina la aplicación"),
sigc::mem_fun(*this, &Parent::onSalir));
m_refActionGroup->add(Gtk::Action::create("FileMenu", "_Archivo"));
m_refUIManager = Gtk::UIManager::create();
m_refUIManager->insert_action_group(m_refActionGroup);
add_accel_group(m_refUIManager->get_accel_group());
m_refUIManager->add_ui_from_string(ui_info);
Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar");
if(pMenubar)
m_vBox.pack_start(*pMenubar, Gtk::PACK_SHRINK);
}
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Descripción física del menú
Creación de una cadena ui_info (XML)
Añadir la conguración de los elementos y las acciones en la barra
de menú con sintaxis XML (en este caso, el menú Archivo,
declarado en el archivo de cabecera:
const Glib::ustring ui_info =
"<ui>"
" <menubar name='MenuBar'>"
" <menu action='FileMenu'>"
" <menuitem action='FileOpen'/>"
" <menuitem action='FileClose'/>"
" <menuitem action='FileQuit'/>"
" </menu>"
" </menubar>"
"</ui>";
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
La clase Gtk::Notebook I
Referirse al paso 6 del taller en: /home/ubuntu/taller/taller-gtkmm6
Añadir el notebook a la ventana Padre y activar el desplazamiento; es
necesario crear los controles que hijos del notebook (tabs). Los childs
naturales de un notebook son ventanas o sus clases derivadas:
m_pClientArea=new Gtk::Notebook;
m_pClientArea->set_scrollable();
Gtk::ScrolledWindow *sw=new Gtk::ScrolledWindow;
Gtk::TextView *tv=new Gtk::TextView;
sw->add(*tv);
Tras hacer las operaciones de carga del documento en la clase de control
(en este caso, Gtk::TextView), se añade el child al notebook usando un
label (texto en la pestaña) y la ventana
Gtk::Label l(fName);
int
npos=m_pClientArea->append_page(*sw->get_ancestor(GTK_TYPE_SCROLLED_WINDOW),
l);
sw->show();
m_pClientArea->show_all_children();
m_pClientArea->set_current_page(npos);
show_all_children();
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
La clase Gtk::Notebook II
Cierre seguro de Tabs (childs)
Para evitar errores de punteros internos, es recomendable usar los
índices (únicos) de los hijos de un notebook:
void Parent::onCerrar()
{
int nPag=m_pClientArea->get_current_page();
if(nPag>=0)
{
Gtk::Widget *wgt=m_pClientArea->get_nth_page(nPag);
m_pClientArea->remove_page(*wgt);
m_pClientArea->queue_draw();
}
}
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Aplicación hasta el momento
Desarrollo de Interfaces Grácas de Usuario con GTKmm
Taller
Implementación sencilla de aplicaciones con interfaz de múltiples documentos.
Notas nales
Usar Gtk::manage(...) para crear widgets que no estarán
almacenados en atributos de las clases; esto permite usar el
recolector de basura de la librería al terminar la aplicación
Se debe preferir siempre la implementación GtkGlib pues
contiene pasos de inicialización y manejo de punteros no
explícitos.
Descargar