読者です 読者をやめる 読者になる 読者になる

[GTK+] 描画する色を指定する

線を描画するの続き。


前回のプログラムでは、線の色として、そのウィジェットの前景色として指定されていたものをそのまま使っていた。しかし、描画する色を明示的に指定したい場面も多々ある。そこで今回は描画色を指定する方法について。

点を打つときに使う関数 gdk_draw_point() の仕様は以下のとおりだった。

void                gdk_draw_point        (GdkDrawable *drawable,
                                                         GdkGC *gc,
                                                         gint x,
                                                         gint y);

第2引数の gc はグラフィックコンテキストというもので、描画のスタイルについていろいろな指定ができるオブジェクト。前回は、GtkDrawingArea ウィジェットに設定されていた値を取り出してきて指定していたが、もちろん新たにGdkGCオブジェクトを生成して、そこで値を指定して gdk_draw_point に渡すこともできる。

前回から変更した関数のみ示す。

void draw_point(
    GtkWidget *area,
    gint x,
    gint y,
    guint16 red,
    guint16 green,
    guint16 blue ) 
{
    GdkGC  *gc;
    GdkColor color;

    color.red   = red;
    color.green = green;
    color.blue  = blue;

    gc = gdk_gc_new(area->window);
    gdk_gc_set_rgb_fg_color(gc, &color);

    gdk_draw_point(area->window,
                   gc,
                   x, y);

    g_object_unref(gc);
}

static gboolean
expose_event(GtkWidget *area, GdkEventExpose *event, gpointer data)
{
    gint x;

    for (x = 0; x < 200; x++)
        draw_point(area, x, x, x * 300, 0, 65535);

    return TRUE;
}
    GdkGC  *gc;
    ....
    gc = gdk_gc_new(area->window);

点を打つための関数 gdk_draw_point() の第2引数に渡す GdkGC オブジェクトを生成し、ポインタを gc に格納する。なお、順番が前後するが、生成した GdkGC オブジェクトは使用後に開放する必要があるため、関数の最後で

    g_object_unref(gc);

としている。

    GdkColor color;

    color.red   = red;
    color.green = green;
    color.blue  = blue;

    ....
    gdk_gc_set_rgb_fg_color(gc, &color);

GdkColor 構造体の各要素にRGB値を設定している。GdkColor 構造体は以下のような構造となっている。

typedef struct {
  guint32 pixel;
  guint16 red;
  guint16 green;
  guint16 blue;
} GdkColor;

red, green, blue に各RGB値の配合度合いを 0 〜 65535 の整数値で指定する。

そして、gc に対して前景色の設定を行うため、gdk_gc_set_rgb_fg_color() という関数を呼び出す。このとき、今生成した GdkColor 構造体のポインタを引数として渡す。

これで、独自のグラフィックコンテキストの準備が出来た。あとは gdk_draw_point() にこの gc を渡せば、指定した色で点を打つことができる。



ソース全体

#include <gtk/gtk.h>

static void destroy(GtkWidget *window, gpointer data)
{
    gtk_main_quit();
}

void draw_point(
    GtkWidget *area, 
    gint x, 
    gint y, 
    guint16 red, 
    guint16 green, 
    guint16 blue) 
{
    GdkGC  *gc;
    GdkColor color;

    color.red   = red;
    color.green = green;
    color.blue  = blue;

    gc = gdk_gc_new(area->window);
    gdk_gc_set_rgb_fg_color(gc, &color);

    gdk_draw_point(area->window, 
                   gc,
                   x, y);

    g_object_unref(gc);
}

static gboolean 
expose_event(GtkWidget *area, GdkEventExpose *event, gpointer data)
{
    gint x;
    
    for (x = 0; x < 200; x++)
        draw_point(area, x, x, x * 300, 0, 65535);

    return TRUE;
}

int main(int argc, char *argv[]) 
{
    GtkWidget *window, *area;
    
    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Drawing Line");
    gtk_widget_set_size_request(window, 200, 200);
    g_signal_connect(G_OBJECT(window), "destroy", 
                     G_CALLBACK(destroy), NULL);

    area = gtk_drawing_area_new();
    g_signal_connect(G_OBJECT(area), "expose_event", 
                     G_CALLBACK(expose_event), NULL);

    gtk_container_add(GTK_CONTAINER(window), area);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}