14.17 X-Toolkits meets Xlib
Zum Schluss möchte ich Ihnen noch zeigen, wie Sie zur Ausgabe von Grafiken mit dem X-Toolkit auf Funktionen der »niedrigeren Ebene« der Xlib zurückgreifen können. Das Widget, das Sie als Grafikfenster verwenden, also mit den Routinen der Xlib darauf zeichnen, initialisieren Sie am besten zwischen den Toolkit-Funktionen und XtRealizeWidget() und XtAppMainLoop().
Zuerst belegen Sie mit der Funktion XtDisplay() einen Parameter vom Typ Display. Als Parameter muss das Fenster angegeben werden, das anschließend unter der Verwendung der Xlib als Root-Fenster agiert. Als Rückgabewert erhalten Sie einen Zeiger auf ein Display, den Sie für die Grafikfunktionen der Xlib verwenden können.
Des Weiteren benötigen Sie eine Struktur vom Typ Window für die Xlib-Grafikfunktionen, die Sie mit der Funktion XtWindow() als Rückgabewert zurückbekommen, unter Angabe des Widgets als Parameter, worauf sich die anschließenden Zeichenaktionen beziehen sollen.
Ein kurzer Blick auf eine Grafikfunktion der Xlib (zum Zeichnen einer Linie)
XDrawLine (display, win, gc, x0, y0, x1, y1);
zeigt, dass Sie auch noch den Grafikkontext benötigen. Diesen erhalten Sie mit der Funktion XtGetGC() und der Angabe des entsprechenden Widgets, das Sie als ersten Parameter angeben. Die anderen beiden Parameter der Funktion XtGetGC() sind hier nicht von Interesse und können mit 0 bzw. NULL belegt werden.
Die Steuerung der Events nimmt Ihnen weiterhin die Toolkit-Funktion XtAppMainLoop() ab, was vor allem auch das (Neu-)Zeichnen des Fensters bedeutet. Ein Refresh (XFlush()), z. B. nach einer Ikonisierung, müssen Sie allerdings selbst übernehmen.
Mithilfe einer eingerichteten Callback-Funktion auf ein entsprechendes Widget, worauf gezeichnet werden soll, können Sie die Steuerung nach Xlib-Konvention im Grafikfenster vornehmen. Am Ende muss diese klassische Event-Bearbeitungsschleife aber wieder verlassen werden, da sonst die anderen Widgets nicht mehr auf Events reagieren können.
Das folgende Beispiel ist ein einfaches Malprogramm, mit dem Sie mit der Maus und dem Cursor etwas in ein Form-Widget zeichnen können.
/* toolkit4.c */
#include <stdio.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command. h.>
static Display *dsp;
static Window win;
static GC gc;
static void
paint_proc (Widget canvas, caddr_t client_data, XEvent * event) {
static int x0, y0, x1, y1;
switch (event->type) {
case ButtonPress:
switch (event->xbutton.button) {
case 1:
x0 = event->xbutton.x;
y0 = event->xbutton.y;
break;
default:
XClearWindow (dsp, win);
XFlush (dsp);
break;
}
break;
case MotionNotify:
x1 = event->xbutton.x;
y1 = event->xbutton.y;
XDrawLine (dsp, win, gc, x0, y0, x1, y1);
x0 = x1;
y0 = y1;
XFlush (dsp);
break;
default:
break;
}
}
static void
quitCB (Widget button, XtPointer client_data, XtPointer call_data) {
exit (EXIT_SUCCESS);
}
int main (int argc, char **argv) {
XtAppContext ac;
Widget toplevel, form, panel, canvas;
Widget quit;
toplevel = XtVaAppInitialize (
&ac, "Paint", NULL, 0,
&argc, argv, NULL, NULL);
form = XtVaCreateManagedWidget (
"form",
formWidgetClass,
toplevel,
XtNvertDistance, (XtArgVal) 5,
XtNwidth, (XtArgVal) 80,
XtNheight, (XtArgVal) 40,
NULL);
panel = XtVaCreateManagedWidget (
"panel",
formWidgetClass,
form,
XtNvertDistance, (XtArgVal) 420,
NULL);
canvas = XtVaCreateManagedWidget (
"canvas",
formWidgetClass,
form,
XtNbackground, (XtArgVal) 0xffffff,
XtNwidth, (XtArgVal) 600,
XtNheight, (XtArgVal) 400,
NULL);
XtAddEventHandler(canvas, ButtonPressMask | Button1MotionMask,
False, (XtEventHandler) paint_proc, NULL);
quit = XtVaCreateManagedWidget (
"quit",
commandWidgetClass,
panel,
XtNbackground, (XtArgVal) "white",
XtNbackground, (XtArgVal) "black",
XtNlabel, (XtArgVal) "Ende",
XtNhorizDistance, (XtArgVal) 5,
NULL);
XtAddCallback (quit, XtNcallback, quitCB, NULL);
XtRealizeWidget (toplevel);
/* Wird von der Xlib zum Zeichnen benötigt */
dsp = XtDisplay (canvas);
win = XtWindow (canvas);
gc = XtGetGC (canvas, 0, NULL);
XSetForeground (dsp, gc, BlackPixel (dsp, 0));
XSetBackground (dsp, gc, WhitePixel (dsp, 255));
XtAppMainLoop (ac);
return EXIT_SUCCESS;
}
Das Programm bei der Ausführung:
$ gcc -o toolkit4 toolkit4.c -L/usr/X11R6/lib -lX11 -lXaw -lXt
$ ./toolkit4
|