Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.com

Gráficos con X11

Vamos a hacer un pequeño programa que cree una ventana y dibuje en ella un gráfico consistente en una línea. Sobre la marcha iremos explicando de forma sencilla los conceptos que se van manejando. Cuando en alguno de los parámetros veas un enlace, pinchando en él verás el porqué se pone ese parámetro o cómo se puede elegir adecuadamente.

En Unix hay un programa que es el encargado de dibujar sobre la pantalla, es el servidor de X . Este programa lo suele arrancar Unix al encender el ordenador. A partir de ese momento estará siempre pendiente de cualquier otro programa que quiera dibujar en pantalla. Cualquier programa unix que quiera dibujar sobre la pantalla, debe hacerlo a través del servidor. También disponemos de una librerías para conectarnos y dibujar gráficos con dicho servidor (las librerías de X11).

Las librerías de X11 son las de más "bajo nivel" con las que podemos pintar gráficos sobre Unix. Únicamente nos van a permitir abrir  ventanas gráficas y dibujar en ellas con las primitivas de pintado habituales en cualquier lenguaje de programación (pintar puntos, lineas, arcos, etc). Si queremos dibujar algo "más complejo", como una ventanas con botones, listas y menús desplegables, debemos irnos a librerías de más "alto nivel" (Gtk, motif, etc), que normalmente están basadas a su vez en las librerías de X11.

Un pequeño detalle: las librerías de X11 y los ficheros .h asociados para poder programar con ellos puede que sean opcionales al instalar linux. Así que antes de ponerte manos a la obra, asegúrate que tienes los ficheros .h a los que se hace referencia en este ejemplo.

CONECTARSE AL SERVIDOR DE X

Si queremos hacer un programa (por ejemplo, en C) que dibuje gráficos, lo primero que debemos hacer es conectarnos con el servidor de X. Las librerías de X11 (X11R6 para los sistemas linux), nos ofrecen la funcion display XOpenDisplay (char *), que es la encargada de conectar con el servidor.

Lo habitual para este parámetro es pasarle NULL. Con este valor, podremos hacer que nuestro programa haga su dibujo en la pantalla de cualquier otro ordenador que esté en red, siempre y cuando tengamos los permisos adecuados.

La función nos devuelve un "display", que es la conexión con el servidor de X. Cualquier función posterior que utilicemos de dibujo o de ventanas nos pedirá dicha conexión, así que es importante guardársela en algún sitio accesible.

El código para abrir la conexión quedaría, por tanto

Display *disp = NULL;
disp = XOpenDisplay(NULL);

CREAR UNA VENTANA PARA DIBUJAR

El siguiente paso para dibujar es crear y visualizar una ventana en la que dibujaremos nuestros gráficos. Para ello tenemos varias funciones, pero la más sencilla es Window XCreateSimpleWindow (). Los parámetros de esta función son

La llamada a la función para crear la ventana quedará entonces

Window ventana;
ventana = XCreateSimpleWindow (
    /* Conexión con el servidor de X */
    disp,          
    /* Ventana raíz de la pantalla, que será padre de la nuestra */
    XDefaultRootWindow (disp),
    /* Posición x,y para la ventana dentro de la ventana padre */
    100, 100,       
    /* Ancho y alto de la ventana. */
    500, 500,
    /* Ancho en pixels para el borde y color del mismo. (1 por poner algo). */
    /* Pincha el enlace del 1 para ver por qué */
    1, 1,         
    /* Color de fondo. Pincha el 0 para ver cómo elegirlo */
    0);                                                               

El valor que nos devuelve la función XCreateSimpleWindow() es el identificador para esa ventana. Cuando queramos dibujar en ella, tendremos que dárselo a las funciones de pintado. Con esto ya tenemos la ventana creada, pero todavía no es visible. La función que hace que se pinte en pantalla es  XMapWindow (display, ventana). Los parámetros son, como no, la conexión con el servidor de X y el identifcador de la ventana que queremos que visualice.

Puesto que el servidor es un proceso separado del nuestro, cuando le mandamos dibujar la ventana, únicamente le estamos mandando un mensaje indicándole que lo haga. Al llamar a XMapWindow(), se envia el mensaje y se nos devuelve el control posiblemente antes de que la ventana esté realmente visible. Para asegurarnos de que es visible, se llama a la función XFlush (display). Esta función "espera" a que el servidor de X termine con todas nuestras peticiones y después nos devuelve el control. Es decir, tendremos la seguridad de que el código que va detrás de XFlush() se ejecutará cuando la ventana sea realmente visible.

Todo esto nos quedaría

XMapWindow (disp, ventana);
XFlush (disp);

VAMOS A DIBUJAR

Ya estamos en disposición de dibujar. Lo primero que hay que hacer es indicar en qué color vamos a dibujar. La función para ello es  XSetForeground (). Los parémetros para esta función son:

El código quedará entonces

XSetForeground (
  /* El de siempre */
  disp,
  /* El contexto gráfico por defecto para nuestra conexión de servidor, pantalla 0 */
  XDefaultGC (disp, 0),
  /* El color con el que queremos dibujar a partir de ahora. */
  255);

Ya podemos dibujar, por ejemplo, una línea. La función para ello es XDrawLine() y sus parámetros son:

Igual que antes, para asegurarnos que se dibuja, llamamos a la función XFlush() y el código resultante será

XDrawLine (
    /* ... */
    disp,
    /* La ventana en la que queremos dibujar */
    ventana,
    /* El contexto gráfico por defecto. */
    XDefaultGC (disp, 0),
    /* posición x,y del origen de la línea. */
    10, 10,
    /* Distancia en x y en y del final al origen de la línea. */
    100, 100);
XFlush (disp);

Ponemos un sleep(100) para que la ventana no se cierre inmediatamente y podamos contemplar nuestra obra de arte.

Un pequeño consejo para ganar eficiencia. Cada vez que llamamos a una función de pintado, estamos enviando un mensaje al servidor de X. Es más rápido pintar 100 líneas de un golpe que pintar las 100 líneas de una en una. Echa un ojo a las funciones plurales.

Si quieres puedes bajarte el código final y el Makefile. Acuérdate de cambiar las extensiones para que funcionen bien.

También tienes el mismo código, pero usando las funciones adecuadas, en vez de poner los parémtros a pelo. El Makefile vale el mismo de antes. Para compilar debes poner make ventana1 o make ventana2, según la que quieras hacer.

Aquí tienes unas cuantas funciones útiles , aunque ya hemos explicado casi todas.

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: