[Previous] [Next] [Up] [Contents] [Feedback]

3. Objekt-Begriff, eigene Klassen


Da GTK komplett in C implementiert ist, muß man sich auf gewisse "Konventionen" einigen, wie die Objekt-Orientierung in der Programmiersprache C abgebildet wird. Es sollte Dinge geben wie:

- Klassen
- Klassenvariablen
- Objekte
- Instanzvariablen
- Methoden
- Vererbung
- dynamische Bindung


Die Basisklasse GtkObject enthält vor allem Mechanismen zur Speicherverwaltung (Rerefenz-Zählung), zum Aufbau von Verbindungen zwischen Objekten (gtk_signal_connect) und zur Debug-Ausgabe.

Um zu verstehen, wie GTK über Objekte und Klassen denkt, hilft es, wenn man einfach mal einen Blick in eine typische Include-Datei wirft. Deshalb hier ein kleiner (aber typischer) Auszug aus gtk/gtkbutton.h:


#define GTK_BUTTON(obj)         ....
#define GTK_IS_BUTTON(obj)      ....

typedef struct _GtkButton       GtkButton;
typedef struct _GtkButtonClass  GtkButtonClass;

struct _GtkButton
{
  GtkBin bin;

  GtkWidget *child /* deprecapted field,
                    * use GTK_BIN (button)->child instead
                    */;

  guint in_button : 1;
  guint button_down : 1;
  guint relief : 2;
};

struct _GtkButtonClass
{
  GtkBinClass        parent_class;

  void (* pressed)  (GtkButton *button);
  void (* released) (GtkButton *button);
  void (* clicked)  (GtkButton *button);
  void (* enter)    (GtkButton *button);
  void (* leave)    (GtkButton *button);
};

GtkType        gtk_button_get_type       (void);
GtkWidget*     gtk_button_new            (void);
GtkWidget*     gtk_button_new_with_label (const gchar *label);
void           gtk_button_pressed        (GtkButton *button);
void           gtk_button_released       (GtkButton *button);
void           gtk_button_clicked        (GtkButton *button);
void           gtk_button_enter          (GtkButton *button);
void           gtk_button_leave          (GtkButton *button);


Die "dynamisch gebundenen Methoden"  wie gtk_button_pressed(button) etc. sind nur Abkürzungen für einen länglichen Ausdruck wie:

GTK_BUTTON_CLASS(GTK_OBJECT(button)->klass)->pressed(button) etc.


Wie mache ich nun eine eigene Klasse?


Als Beispiel für eine eigene Klasse zeige ich hier das Beipiel von vorher mit einem MyButton an Stelle des GtkLabel.


button1.h:

#ifndef MY_BUTTON_H
#define MY_BUTTON_H

#include <gtk/gtk.h>

#define MY_BUTTON(obj)  \
	GTK_CHECK_CAST(obj, my_button_get_type(), MyButton)
#define MY_BUTTON_CLASS(klass)  \
	GTK_CHECK_CLASS_CAST(klass, my_button_get_type(), MyButtonClass)
#define IS_MY_BUTTON(obj)  \
	GTK_CHECK_TYPE(obj, my_button_get_type())

typedef struct _MyButton       MyButton;
typedef struct _MyButtonClass  MyButtonClass;

struct _MyButton
{
    GtkButton button;
};

struct _MyButtonClass
{
    GtkButtonClass parent;
};

guint        my_button_get_type    (void);
GtkWidget*   my_button_new         (const gchar *label);

#endif /* MY_BUTTON_H */


button1.c:

#include <stdio.h>
#include <gtk/gtk.h>
#include "button1.h"

static void  my_button_init (MyButton *button);

guint        my_button_get_type    (void)
{
    static GtkType my_button_type;

    if (!my_button_type)
    {
        GtkTypeInfo type_info =
        {
            "MyButton",
            sizeof (MyButton),
            sizeof (MyButtonClass),
            (GtkClassInitFunc) NULL,
            (GtkObjectInitFunc) my_button_init,
            /* reserved_1 */ NULL,
            /* reserved_2 */ NULL,
            (GtkClassInitFunc) NULL
        };

        my_button_type = gtk_type_unique(gtk_button_get_type(),
                                         &type_info);
    }

    return my_button_type;
}

static void clicked (MyButton *button)
{
    puts(GTK_LABEL(GTK_BIN(button)->child)->label);
}

static void  my_button_init (MyButton *button)
{
    gtk_signal_connect(GTK_OBJECT(button), "clicked",
                       GTK_SIGNAL_FUNC(clicked), NULL);
}

GtkWidget*   my_button_new         (const gchar *label)
{
    MyButton *button = gtk_type_new(my_button_get_type());

    gtk_container_add(GTK_CONTAINER(button), gtk_label_new(label));
    return GTK_WIDGET(button);
}


int main (int argc, char *argv[])
{
    GtkWindow *window;
    MyButton *button;

    gtk_init(&argc, &argv);

    window = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
    button = (MyButton *) my_button_new("Hello, World!");

    gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(button));
    gtk_widget_show_all(GTK_WIDGET(window));

    gtk_signal_connect(GTK_OBJECT(window), "destroy", gtk_main_quit, NULL);

    gtk_main();
    return 0;
}


[Previous] [Next] [Up] [Contents] [Feedback]