mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 22:20:24 +00:00
436 lines
15 KiB
HTML
436 lines
15 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.6">
|
|
<TITLE>GTK+ FAQ: Desarrollo con GTK+</TITLE>
|
|
<LINK HREF="gtkfaq-es-5.html" REL=next>
|
|
<LINK HREF="gtkfaq-es-3.html" REL=previous>
|
|
<LINK HREF="gtkfaq-es.html#toc4" REL=contents>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF">
|
|
<A HREF="gtkfaq-es-5.html">Next</A>
|
|
<A HREF="gtkfaq-es-3.html">Previous</A>
|
|
<A HREF="gtkfaq-es.html#toc4">Contents</A>
|
|
<HR NOSHADE>
|
|
<H2><A NAME="s4">4. Desarrollo con GTK+</A></H2>
|
|
|
|
<H2><A NAME="ss4.1">4.1 ¿Cómo empiezo?</A>
|
|
</H2>
|
|
|
|
<P>Después de que ha instalado GTK+, hay un par de cosas que pueden
|
|
facilitarle el desarrollo de aplicaciones con él. Está el Tutor de
|
|
GTK+
|
|
<A HREF="http://www.gtk.org/tutorial/"><http://www.gtk.org/tutorial/></A>, el cual está en desarrollo
|
|
activo. Este tutorial le introducirá en la escritura de aplicaciones
|
|
utilizando C.
|
|
<P>El Tutor no contiene (todavía) información sobre todos los
|
|
<EM>widgets</EM> que existen en GTK+. Para código de ejemplo sobre la
|
|
utilización básica de todos los <EM>widgets</EM> de GTK+, debe ver
|
|
el archivo gtk/testgtk.c (y archivos fuentes asociados) en la distribución
|
|
GTK+. Ver estos ejemplos le dará una buena base sobre lo que pueden hacer
|
|
los <EM>widgets</EM>.
|
|
<P>
|
|
<H2><A NAME="ss4.2">4.2 ¿Qué <EM>widgets</EM> existen en GTK?</A>
|
|
</H2>
|
|
|
|
<P>El Tutor de GTK+ lista los siguientes <EM>widgets</EM>:
|
|
<PRE>
|
|
GtkObject
|
|
+GtkData
|
|
| +GtkAdjustment
|
|
| `GtkTooltips
|
|
`GtkWidget
|
|
+GtkContainer
|
|
| +GtkBin
|
|
| | +GtkAlignment
|
|
| | +GtkEventBox
|
|
| | +GtkFrame
|
|
| | | `GtkAspectFrame
|
|
| | +GtkHandleBox
|
|
| | +GtkItem
|
|
| | | +GtkListItem
|
|
| | | +GtkMenuItem
|
|
| | | | `GtkCheckMenuItem
|
|
| | | | `GtkRadioMenuItem
|
|
| | | `GtkTreeItem
|
|
| | +GtkViewport
|
|
| | `GtkWindow
|
|
| | +GtkColorSelectionDialog
|
|
| | +GtkDialog
|
|
| | | `GtkInputDialog
|
|
| | `GtkFileSelection
|
|
| +GtkBox
|
|
| | +GtkButtonBox
|
|
| | | +GtkHButtonBox
|
|
| | | `GtkVButtonBox
|
|
| | +GtkHBox
|
|
| | | +GtkCombo
|
|
| | | `GtkStatusbar
|
|
| | `GtkVBox
|
|
| | +GtkColorSelection
|
|
| | `GtkGammaCurve
|
|
| +GtkButton
|
|
| | +GtkOptionMenu
|
|
| | `GtkToggleButton
|
|
| | `GtkCheckButton
|
|
| | `GtkRadioButton
|
|
| +GtkCList
|
|
| `GtkCTree
|
|
| +GtkFixed
|
|
| +GtkList
|
|
| +GtkMenuShell
|
|
| | +GtkMenuBar
|
|
| | `GtkMenu
|
|
| +GtkNotebook
|
|
| +GtkPaned
|
|
| | +GtkHPaned
|
|
| | `GtkVPaned
|
|
| +GtkScrolledWindow
|
|
| +GtkTable
|
|
| +GtkToolbar
|
|
| `GtkTree
|
|
+GtkDrawingArea
|
|
| `GtkCurve
|
|
+GtkEditable
|
|
| +GtkEntry
|
|
| | `GtkSpinButton
|
|
| `GtkText
|
|
+GtkMisc
|
|
| +GtkArrow
|
|
| +GtkImage
|
|
| +GtkLabel
|
|
| | `GtkTipsQuery
|
|
| `GtkPixmap
|
|
+GtkPreview
|
|
+GtkProgressBar
|
|
+GtkRange
|
|
| +GtkScale
|
|
| | +GtkHScale
|
|
| | `GtkVScale
|
|
| `GtkScrollbar
|
|
| +GtkHScrollbar
|
|
| `GtkVScrollbar
|
|
+GtkRuler
|
|
| +GtkHRuler
|
|
| `GtkVRuler
|
|
`GtkSeparator
|
|
+GtkHSeparator
|
|
`GtkVSeparator
|
|
</PRE>
|
|
<P>
|
|
<H2><A NAME="ss4.3">4.3 ¿GTK+ es seguro ante múltiples hilos?</A>
|
|
</H2>
|
|
|
|
<P>Aunque GTK+, como la mayoría de los juegos de herramientas para X,
|
|
no es seguro ante múltiples hilos, esto no prohibe el desarrollo de
|
|
aplicaciones con múltiples hilos con GTK+.
|
|
<P>Rob Browning (rlb@cs.utexas.edu) describe técnicas de hilamiento
|
|
que pueden utilizarse con GTK+ (levemente modificado):
|
|
<P>Básicamente existen dos enfoques principales, el primero es sencillo,
|
|
y el segundo complicado. En el primero, simplemente hay que asegurarse
|
|
de que todas las interacciones de GTK+ (o X) se manejan por un, y solo un,
|
|
hilo. Cualquier otro hilo que desee dibujar algo tiene que notificarlo de
|
|
alguna manera al hilo "GTK+", y dejarlo que maneje el trabajo real.
|
|
<P>El segundo enfoque le permite llamar funciones de GTK+ (o X) desde cualquier
|
|
hilo, pero requiere sincronización cuidadosa. La idea básica es crear
|
|
una exclusión mutua de protección para X, de manera que nadie haga
|
|
llamadas X sin primero adquirir esta exclusión mutua.
|
|
<P>Observe que se trata de un pequeño esfuerzo, pero que le permitirá ser
|
|
potencialmente más eficiente que un GTK+ completamente seguro ante
|
|
múltiples hilos. Usted decide la granularidad del bloqueo de hilos.
|
|
También debe asegurarse que el hilo que llama a gtk_main mantiene la
|
|
cerradura cuando llama a gtk_main.
|
|
<P>Lo siguiente por lo que hay que preocuparse ya que se tenía agarrada
|
|
la exclusión mutua global cuando se entró a gtk_main, es que todos
|
|
los <EM>callbacks</EM> también la tendrán. Esto significa que el
|
|
<EM>callback</EM> debe soltarla si va a llamar a cualquier otro código
|
|
que pueda readquirirla. De otra manera obtendrá un bloqueo mortal.
|
|
También hay que tener agarrada la exclusión mutua cuando finalmente
|
|
regresa del <EM>callback</EM>.
|
|
<P>Para permitir a otros hilos, además del que llama a gtk_main, tener
|
|
acceso a la exclusión mutua, necesitamos registrar una función de
|
|
trabajo con GTK que nos permita liberar la exclusión mutua
|
|
periódicamente.
|
|
<P>¿Por qué GTK+ no puede ser seguro ante múltiples hilos de
|
|
manera nativa?
|
|
<P>Complejidad, sobrecarga, y mano de obra. La proporción de programas
|
|
con hilos es todavía razonablemente pequeña, y conseguir seguridad
|
|
ante hilos es muy difícil y le quita tiempo valioso al trabajo
|
|
principal de obtener una buena librería gráfica terminada. Sería
|
|
muy agradable que GTK+ fuera seguro ante hilos "al sacarlo de la caja",
|
|
pero no es práctico ahora mismo, y haría a GTK+ sustancialmente menos
|
|
eficiente si no se maneja cuidadosamente.
|
|
<P>De cualquier manera, no es una prioridad esencial ya que existen remedios
|
|
relativamente buenos.
|
|
<P>
|
|
<H2><A NAME="ss4.4">4.4 ¿Cómo puedo prevenir el redibujar y reacomodar tamaños mientras cambio múltiples <EM>widgets</EM>?</A>
|
|
</H2>
|
|
|
|
<P>
|
|
Utilize gtk_container_disable_resize y gtk_container_enable_resize alrededor
|
|
del código donde quiere cambiar varias cosas. Esto resultará en mayor
|
|
velocidad ya que prevendrá tener que darle el tamaño otra vez a la
|
|
jerarquía de <EM>widget</EM> por completo.
|
|
<P>
|
|
<H2><A NAME="ss4.5">4.5 ¿Cómo atrapo un evento de doble tecleo (en un <EM>widget</EM> de lista, por ejemplo)?</A>
|
|
</H2>
|
|
|
|
<P>Tim Janik escribió a la lista gtk-list (ligeramente modificado):
|
|
<P>Defina un manejador de señal:
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
gint
|
|
signal_handler_event(GtkWiget *widget, GdkEvenButton *event, gpointer func_data)
|
|
{
|
|
if (GTK_IS_LIST_ITEM(widget) &&
|
|
(event->type==GDK_2BUTTON_PRESS ||
|
|
event->type==GDK_3BUTTON_PRESS) ) {
|
|
printf("I feel %s clicked on button %d\",
|
|
event->type==GDK_2BUTTON_PRESS ? "double" : "triple",
|
|
event->button);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>Y conecte el manejador a su objeto:
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
{
|
|
/* lista, asuntos de inicializacion de articulos de lista */
|
|
|
|
gtk_signal_connect(GTK_OBJECT(list_item),
|
|
"button_press_event",
|
|
GTK_SIGNAL_FUNC(signal_handler_event),
|
|
NULL);
|
|
|
|
/* y/o */
|
|
|
|
gtk_signal_connect(GTK_OBJECT(list_item),
|
|
"button_release_event",
|
|
GTK_SIGNAL_FUNC(signal_handler_event),
|
|
NULL);
|
|
|
|
/* algo mas */
|
|
}
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>y, Owen Taylor escribió:
|
|
<P>Observe que se recibirá la pulsación del botón de antemano, y
|
|
si está haciendo esto para un botón, también obtendrá una señal
|
|
de "tecleado" para el botón. (Esto es cierto para cualquier juego de
|
|
herramientas, ya que las computadoras no son buenas para leer la mente de
|
|
cada quien.)
|
|
<P>
|
|
<H2><A NAME="ss4.6">4.6 ¿Cómo puedo averiguar cuál es la selección de un GtkList?</A>
|
|
</H2>
|
|
|
|
<P>
|
|
<P>Consiga la selección con algo como esto:
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
GList *sel;
|
|
sel = GTK_LIST(list)->selection;
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>Así es como GList está definido (sacado de glist.h):
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
typedef struct _GList GList;
|
|
|
|
struct _GList
|
|
{
|
|
gpointer data;
|
|
GList *next;
|
|
GList *prev;
|
|
};
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>Una estructura GList es simplemente una estructura para listas doblemente
|
|
enlazadas. Existen varias funciones g_list_*() para modificar una lista
|
|
enlazada en glib.h. Sin embargo, la selección GTK_LIST(MyGtkList)->selection
|
|
es mantenida por las funciones gtk_list_*() y no deben ser modificadas.
|
|
<P>El selection_mode del GtkList determina las facilidades de selección de un
|
|
GtkList y por lo tanto los contenidos de GTK_LIST(AnyGtkList)->selection:
|
|
<P>
|
|
<PRE>
|
|
selection_mode GTK_LIST()->selection contents
|
|
------------------------------------------------------
|
|
|
|
GTK_SELECTION_SINGLE) la selección es NULL
|
|
o contiene un puntero GList*
|
|
para un artículo seleccionado individualmente
|
|
|
|
GTK_SELECTION_BROWSE) la selección es NULL si la lista
|
|
no contiene widgets, de otra manera
|
|
contiene un puntero GList*
|
|
para una estructura GList.
|
|
GTK_SELECTION_MULTIPLE) la selección es NULL si no se seleccionan
|
|
listitems para un apuntador GList*
|
|
para el primer artículo seleccionado. Eso en
|
|
su lugar apunta a una estructura GList para el
|
|
segundo artículo seleccionado y continúa
|
|
|
|
GTK_SELECTION_EXTENDED) la selección es NULL.
|
|
</PRE>
|
|
<P>El campo data de la estructura GList GTK_LIST(MyGtkList)->selection apunta
|
|
al primer GtkListItem que es seleccionado. De manera que si quiere determinar
|
|
cuales listitems están seleccionados debe hacer esto:
|
|
<P>Durante la in>
|
|
<HR><H3>Transfer interrupted!</H3>
|
|
>
|
|
{
|
|
gchar *list_items[]={
|
|
"Item0",
|
|
"Item1",
|
|
"foo",
|
|
"last Item",
|
|
};
|
|
guint nlist_items=sizeof(list_items)/sizeof(list_items[0]);
|
|
GtkWidget *list_item;
|
|
guint i;
|
|
|
|
list=gtk_list_new();
|
|
gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE);
|
|
gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list);
|
|
gtk_widget_show (list);
|
|
|
|
for (i = 0; i < nlist_items; i++)
|
|
{
|
|
list_item=gtk_list_item_new_with_label(list_items[i]);
|
|
gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i);
|
|
gtk_container_add(GTK_CONTAINER(list), list_item);
|
|
gtk_widget_show(list_item);
|
|
}
|
|
}
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>Para tener conocimiento de la inicialización:
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
{
|
|
GList *items;
|
|
|
|
items=GTK_LIST(list)->selection;
|
|
|
|
printf("Selected Items: ");
|
|
while (items) {
|
|
if (GTK_IS_LIST_ITEM(items->data))
|
|
printf("%d ", (guint)
|
|
gtk_object_get_user_data(items->data));
|
|
items=items->next;
|
|
}
|
|
printf("\n");
|
|
}
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<H2><A NAME="ss4.7">4.7 ¿Acaso es posible desplegar un texto que se recorte para que quepa dentro del lugar que tenga asignado?</A>
|
|
</H2>
|
|
|
|
<P>El comportamiento de GTK+ (sin recorte) es una consecuencia de sus intentos
|
|
para conservar recursos de X. Los <EM>widgets</EM> etiqueta (entre otros) no
|
|
tienen su propia ventana X - simplemente dibujan su contenido en la ventana
|
|
de su padre. Aunque sería posible hacer que ocurran recortes al establecer
|
|
la máscara de recorte antes de dibujar el texto, esto podría causar una
|
|
penalización substancial en el rendimiento.
|
|
<P>Es posible que, a largo plazo, la mejor solución a tales problemas sea
|
|
simplemente cambiar gtk para que le de ventanas X a las etiquetas. Un remedio
|
|
a corto plazo es poner el <EM>widget</EM> de etiqueta dentro de otro
|
|
<EM>widget</EM> que sí obtiene su propia ventana - un candidato posible puede ser el <EM>widget</EM> <EM>viewport</EM>.
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
viewport = gtk_viewport (NULL, NULL);
|
|
gtk_widget_set_usize (viewport, 50, 25);
|
|
gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
|
|
gtk_widget_show(viewport);
|
|
|
|
label = gtk_label ("a really long label that won't fit");
|
|
gtk_container_add (GTK_CONTAINER(viewport), label);
|
|
gtk_widget_show (label);
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>Si estuviera haciendo esto para un montón de <EM>widgets</EM>, querrá
|
|
copiar gtkviewport.c y arrancar la funcionalidad de sombra y ajuste (tal vez
|
|
quiera llamarlo GtkClipper).
|
|
<P>
|
|
<H2><A NAME="ss4.8">4.8 ¿Por qué el contenido de un botón no se mueve al presionar el botón? Aquí les envío un parche para que funcione de esa forma...</A>
|
|
</H2>
|
|
|
|
<P>De: Peter Mattis
|
|
<P>La razón por la cuál los botones no mueven a su hijo abajo y a la derecha
|
|
cuando son presionados es porque no me parece que eso es lo que ocurre
|
|
visualmente. Mi visión de los botonos es que los miras de manera recta.
|
|
O sea, la interface de usuario tiende sobre un plano y tú estás sobre
|
|
él observándolo de manera recta. Cuando un botón es presionado se
|
|
mueve directamente lejos de tí. Para ser absolutamente correcto supongo
|
|
que el hijo debería encojerse un poquito. Pero no veo por qué el hijo
|
|
debería moverse abajo y a la izquierda. Recurda, el hijo se supone que
|
|
está pegado a la superficie del botón. No es bueno que luzca como si
|
|
el hijo se resbala sobre la superficie del botón.
|
|
<P>En una nota más práctica, ya implanté esto una vez y determiné
|
|
que no se veía bien y lo quité.
|
|
<P>
|
|
<H2><A NAME="ss4.9">4.9 ¿Cómo puedo definir una línea de separación como en un menú?</A>
|
|
</H2>
|
|
|
|
<P>Revise el
|
|
<A HREF="http://www.gtk.org/tutorial/">Tutor</A> para información sobre como crear menús.
|
|
<P>Sin embargo, para crear una línea de separación en un menú,
|
|
simplemente inserte un artículo de menú vacío:
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
menuitem = gtk_menu_item_new();
|
|
gtk_menu_append(GTK_MENU(menu), menuitem);
|
|
gtk_widget_show(menuitem);
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>
|
|
<H2><A NAME="ss4.10">4.10 ¿Cómo puedo darle justificación a la derecha a un menú, como Help, cuando utilizo MenuFactory?</A>
|
|
</H2>
|
|
|
|
<P>Utilice algo como lo que sigue:
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
menu_path = gtk_menu_factory_find (factory, "<MyApp>/Help");
|
|
gtk_menu_item_right_justify(menu_path->widget);
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<H2><A NAME="ss4.11">4.11 ¿Cómo hago mi ventana modal? / ¿Cómo hago una sóla ventana activa?</A>
|
|
</H2>
|
|
|
|
<P>Después de haber creado su ventana, haga gtk_grab_add(my_window). Y
|
|
después de cerrar la ventana haga gtk_grab_remove(my_window).
|
|
<P>
|
|
<H2><A NAME="ss4.12">4.12 ¿Por qué mi <EM>widget</EM> (ej. progressbar) no se actualiza?</A>
|
|
</H2>
|
|
|
|
<P>
|
|
<P>Probablemente usted está haciendo todos los cambios dentro de una función
|
|
sin devolver el control a gtk_main. La mayoría de las actualizaciones de
|
|
dibujo se colocan simplemente en una cola, la cual es procesada dentro de
|
|
gtk_main. Puede forzar que se procese la cola de dibujado utilizando algo como:
|
|
<P>
|
|
<BLOCKQUOTE><CODE>
|
|
<PRE>
|
|
while (gtk_events_pending())
|
|
gtk_main_iteration();
|
|
</PRE>
|
|
</CODE></BLOCKQUOTE>
|
|
<P>dentro de la función que cambia el <EM>widget</EM>.
|
|
<P>Lo que el fragmento anterior hace es correr todos los eventos pendientes y
|
|
funciones ociosas de alta prioridad, luego regresa de inmediato (el dibujado
|
|
se realiza en una función ociosa de alta prioridad).
|
|
<P>
|
|
<HR NOSHADE>
|
|
<A HREF="gtkfaq-es-5.html">Next</A>
|
|
<A HREF="gtkfaq-es-3.html">Previous</A>
|
|
<A HREF="gtkfaq-es.html#toc4">Contents</A>
|
|
</BODY>
|
|
</HTML>
|