Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 14 Xlib – X Window-Programmierung
  gp 14.1 Architektur von X
    gp 14.1.1 Pufferung
    gp 14.1.2 Ressourcen
  gp 14.2 X Toolkit
  gp 14.3 Der Window-Manager
  gp 14.4 Fenster mit X
    gp 14.4.1 Verbindung herstellen
    gp 14.4.2 Fenster definieren
    gp 14.4.3 Informationen für den Window-Manager
    gp 14.4.4 Fenster anzeigen
    gp 14.4.5 Fenster und X-Verbindung beenden
    gp 14.4.6 Das Grundgerüst als Quellcode
  gp 14.5 Events
    gp 14.5.1 Event-Maske setzen
    gp 14.5.2 Event-Bearbeitungsschleife
    gp 14.5.3 Abarbeitung der Events
    gp 14.5.4 Tastatur-Event
    gp 14.5.5 Mausbutton-Event
    gp 14.5.6 Expose-Event
    gp 14.5.7 EnterWindowMask – LeaveWindowMask
    gp 14.5.8 Listing zu den Events
  gp 14.6 Grafik mit X
    gp 14.6.1 Grafikprimitive – Zeichenfunktionen
  gp 14.7 Text mit X
    gp 14.7.1 Fonts benutzen
    gp 14.7.2 Übersicht zu den Fonts
    gp 14.7.3 Höhe und Breite ermitteln
    gp 14.7.4 Listing mit Textausgabe
  gp 14.8 Farben mit X
  gp 14.9 Beispiel – ein Button mit X
  gp 14.10 Wozu kann ich denn nun die Xlib in der Praxis verwenden?
  gp 14.11 X und X-Toolkits – Einführung
  gp 14.12 Toolkit-Programmierung
    gp 14.12.1 Widgets
  gp 14.13 Ein einfaches Fenster mit einem Button
    gp 14.13.1 Ressourcen
  gp 14.14 Zwei Buttons in Box- und Form-Widget mit Textausgabe (Label-Widget)
  gp 14.15 editres – Widget-Hierarchie
  gp 14.16 Texteingabe mit Dialog-Widget
  gp 14.17 X-Toolkits meets Xlib
  gp 14.18 Zusammenfassung


Rheinwerk Computing

14.6 Grafik mitdowntop

Um überhaupt etwas zeichnen zu können, muss zuvor ein Speicherobjekt zum Grafikkontext (eine weitere Datenstruktur) erzeugt werden. Diese Struktur, GC, enthält sämtliche Attribute, die für die grafischen Funktionen benötigt werden. Erzeugen können Sie ein Speicherobjekt des Grafikkontexts GC mit der Funktion XCreateGC():

GC mygc;
...
mygc = XCreateGC(display, win, 0, 0);

Die ersten beiden Parameter sollten mittlerweile keine Fragen mehr aufwerfen. Mit dem dritten Parameter könnten Sie eine Maske verwenden, womit Sie bestimmen, in welcher Komponente der übergebenen Struktur des vierten Parameters (vom Typ XGCValues) Informationen enthalten sind. Im Buch wird allerdings davon kein Gebrauch gemacht. Als Rückgabewert der Funktion erhalten Sie eine Kennungs-ID, die bei jeder Zeichenoperation an den Server übergeben wird. Natürlich können in einer Zeichnung mehrere bzw. (fast) beliebig viele GC verwendet werden.

Wird der Speicherplatz für den Grafikkontext nicht mehr benötigt, sollte man diesen mit der Funktion XFreeGC(display, win) wieder freigeben.


Rheinwerk Computing

14.6.1 Grafikprimitive – Zeichenfunktionen  toptop

Es folgt nun ein kurzer Überblick zu den Zeichenfunktionen der Xlib, womit im Prinzip alles wie z. B. Buttons, Menüs etc. (natürlich nur für Hardcore-Programmierer) oder auch eine Spielebibliothek erstellt werden kann. Alle Funktionen benötigen den Grafikkontext GC.


Tabelle 14.3    Zeichenfunktionen der Xlib

Funktion Bedeutung
XDrawPoint() einen Punkt zeichnen
XDrawPoints() mehrere Punkte zeichnen
XDrawLine() eine Linie zeichnen
XDrawLines() verbundene Folge von Linien zeichnen
XDrawSegments() mehrere getrennte Linien zeichnen
XDrawArc() einen Bogen/Kreis zeichnen
XDrawArcs() mehrere Bögen/Kreise zeichnen
XFillArc() einen Bogen/Kreis ausfüllen
XFillArcs() mehrere Bögen/Kreise ausfüllen
XDrawRectangle() ein Rechteck zeichnen
XDrawRectangles() mehrere Rechtecke zeichnen
XFillRectangle() ein Rechteck ausfüllen
XFillRectangles() mehrere Rechtecke ausfüllen
XFillPolygon() zeichnet ein ausgefülltes Vieleck

Die ersten drei Parameter aller Funktionen sind, der Reihe nach, das Display (Server), das Fenster (win) und der Grafikkontext (mygc). Anschließend folgen je nach Funktion die x,y-Koordinaten, von wo bis wo gezeichnet werden soll. Bei den Funktionen, die mit einem ...s enden wie XDrawPoints(), wird anstatt der x,y-Koordinate ein Vektor von Koordinaten übergeben. Für eine genauere Syntaxbeschreibung sei die Manual Page empfohlen – oder man betrachte das nachfolgende Listing genauer.


Hinweis   Nicht behandelt und besprochen werden hier die Pixmaps, Bitmaps und die Images, die ebenfalls eine intensive Beziehung zu dem Grafikkontext pflegen.


Es folgt wieder ein Listing, das die Verwendung einiger Grafikprimitiven mit dem Kontext demonstrieren soll. Die Grafik wird sofort gezeichnet, wenn das Fenster erzeugt wurde und das Expose-Event gesendet wird.

/* xgrafik.c */
#include <stdio.h>
#include <stdlib.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "my_delay.h"
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 320
/* Funktionsprototypen */
static int create_window (void);
static void process_event (XEvent report);
static void eventloop (void);
static void close_window (void);
extern int delay (int i);
extern int time_diff (void);
static void draw_graphics (void);
/* Globale Variablen */
static unsigned int width, height;
static Display *display;
static int screen;
static int depth;
static Window win; 
/* Funktion erzeugt ein Fenster */
static int create_window (void) {
  char *window_name = "Einfache Grafikprimitiven";
  char *icon_name   = "window";
  static XSizeHints size_hints;
  Window rootwin;
  width = WINDOW_WIDTH;
  height = WINDOW_HEIGHT;
  /* X-Sitzung öffnen */
  display = XOpenDisplay (NULL);
  /* Fehlerüberprüfung */
  if (display == NULL) {
    printf ("Verbindung zum X-Server fehlgeschlagen?!?\n");
    exit(EXIT_FAILURE);
  }
  /* Standardbildschirm eines Displays */
  screen = XDefaultScreen (display);
  /* Standardtiefe des Screens - Anzahl der Ebenen */
  depth = XDefaultDepth (display, screen);
  rootwin = RootWindow (display, screen);
  win = XCreateSimpleWindow ( display, rootwin, 10, 10,
                              width, height, 5,
                              BlackPixel (display, screen),
                              WhitePixel (display, screen));
  size_hints.flags = PSize | PMinSize | PMaxSize;
  size_hints.min_width =  width;
  size_hints.max_width =  width;
  size_hints.min_height = height;
  size_hints.max_height = height;
  XSetStandardProperties ( display, win, window_name, icon_name,
                           None, 0, 0, &size_hints );
  XSelectInput ( display, win,
                 ButtonPressMask | KeyPressMask | ExposureMask );
  XMapWindow (display, win);
  return 1;
}
static void close_window (void) {
  XCloseDisplay (display);
}
static void eventloop (void) {
  XEvent xev;
  int num_events;
  XFlush (display);
  num_events = XPending (display);
  while ((num_events != 0)) {
     num_events--;
     XNextEvent (display, &xev);
     process_event (xev);
  }
}
static void process_event (XEvent report) {
  switch (report.type) {
  case Expose:      /* Expose-Event => Bild zeichnen */
    if (report.xexpose.count == 0) {
      draw_graphics ();
    }
    break;
  case KeyPress:
    printf ("Tastaturaktion\n");
    break;
  case ButtonPressMask:
    printf ("Mausaktion\n");
    break;
  default:
    break;
  }
}
static void draw_graphics () {
  GC mygc;                      /* neu: Grafikkontext    */
  unsigned long black, white;   /* Nummern der Farben    */
  int i;                        /* gut fuer alles        */
  XPoint punkte[50];            /* Punkteschar           */
  XPoint poly[4];               /* 4 Punkte fuer Polygon */
  /* Ein paar Felder belegen                   */
  /* Eine Schräge mithilfe von Punkten zeichnen */
  for (i = 0; i < 50; i++) {
    punkte[i].x = 470 + i;
    punkte[i].y = 200 + i;
  }
  /* geschlossenes Dreieck */
  poly[0].x = 200;
  poly[0].y = 200;   
  poly[1].x = 300;
  poly[1].y = 300;
  poly[2].x = 400;
  poly[2].y = 200;
  poly[3].x = 200;
  poly[3].y = 200;
  /* Fenster oben drauf anzeigen */
  XMapRaised (display, win);   
  /* Farbnummern besorgen */
  black = BlackPixel (display, screen);
  white = WhitePixel (display, screen);
  /* Graphical Context erzeugen, Farben eintragen */
  mygc = XCreateGC (display, win, 0, 0);
  XSetForeground (display, mygc, black);
  XSetBackground (display, mygc, white);
  /* sicherheitshalber alles löschen */
  XClearWindow(display, win);  
  /* Ein Rechteck zeichnen */
  XDrawRectangle (display, win, mygc, 10, 50, 50, 50);
  /* Einen rechteckigen Bereich mit Farbe füllen */
  XFillRectangle (display, win, mygc, 110, 50, 50, 50);
  /* Einen Kreis zeichnen */
  XDrawArc (display, win, mygc, 210, 50, 50, 50, 0, 360 * 64);
  /* Einen Kreisbereich füllen */
  XFillArc (display, win, mygc, 310, 50, 50, 50, 0, 360 * 64);
  /* Eine Ellipse zeichnen */
  XDrawArc (display, win, mygc, 410, 50, 60, 40, 0, 360 * 64);
  /* Einen Ellipsenbereich füllen */
  XFillArc (display, win, mygc, 510, 50, 60, 40, 0, 360 * 64);
  /* Einen Halbkreis zeichnen */
  XDrawArc (display, win, mygc, 10, 200, 60, 40, 90*64, 180*64);
  /* Einen Halbkreis füllen */
  XFillArc (display, win,mygc, 110, 200, 60, 40, 90*64, 180*64);
  /* Einen bestimmten Bereich im Polygon (in diesem Fall ein */
  /* Dreieck füllen ausgefuelltes Polygon bzw. Dreieck       */
  XFillPolygon(display, win, mygc, poly, 4, 0, CoordModeOrigin);
  /* Eine schräge Linie mit Punkten */
  XDrawPoints (display, win, mygc, punkte, 50, CoordModeOrigin);
  /* Puffer leeren */
  XFlush (display);    
  /* GC wieder freigeben   */
  XFreeGC (display, mygc);    
}
int main (int argc, char **argv) {
  int quit = 0;
  int pause = 0;
  int td;
  create_window ();
  gettimeofday (&st, NULL);
  while (!quit) {
    gettimeofday (&rt, NULL);
    td = time_diff ();
    pause = delay (FRAME_LEN - td + pause);
    st = rt;
    eventloop ();
  }
  close_window ();
  return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o xgrafik xgrafik.c -L/usr/X11R6/lib -lX11
$ ./xgrafik

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 14.2    Zeichnen einiger geometrischer Formen im X-Fenster


 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern