GTK4   トグルボタン

ホーム   C/C++チュートリアル  

トグルボタン

トグルボタンもオンとオフの状態を持てるボタンです。

以下のファイルを toggle.c というファイル名で記述して任意の場所に保存してください。

コードが少し簡単になりました

toggle.c


/*************************************
    toggle.c
    copyright    :  vivacocoa.jp
    last modified:  Mar. 19, 2025
************************************/

#include <gtk/gtk.h>

guchar  r, g, b;

static void
color (GtkWidget *btn, GtkWidget *area)
{
	if (g_strcmp0 (gtk_widget_get_name (btn), "red") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{r = 255;} else {r = 0;}
		gtk_widget_queue_draw (area);
	}
	if (g_strcmp0 (gtk_widget_get_name (btn), "green") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{g = 255;} else {g = 0;}
		gtk_widget_queue_draw (area);
	}
	if (g_strcmp0 (gtk_widget_get_name (btn), "blue") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{b = 255;} else {b = 0;}
		gtk_widget_queue_draw (area);
	}
}

static void
draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
{
    GdkRGBA     color;
    gchar       *rgb;
    
    rgb     =   g_strdup_printf     ("rgb(%d,%d,%d)", r, g, b);
    gdk_rgba_parse                  (&color, rgb);
    g_free                          (rgb);
    gdk_cairo_set_source_rgba       (cr, &color);
    cairo_paint                     (cr);
}

static void
activate(GtkApplication *app, gpointer data)
{
    GtkWidget *win   = gtk_application_window_new (GTK_APPLICATION (app));
    GtkWidget *vbox  = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
    GtkWidget *hbox  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
    GtkWidget *area  = gtk_drawing_area_new ();
    GtkWidget *red   = gtk_toggle_button_new_with_label("Red");
    GtkWidget *green = gtk_toggle_button_new_with_label("Green");
    GtkWidget *blue  = gtk_toggle_button_new_with_label("Blue");
    
    gtk_window_set_child (GTK_WINDOW(win), vbox);
    
    gtk_box_append (GTK_BOX (vbox), hbox);
    gtk_box_append (GTK_BOX (hbox), red);
    gtk_box_append (GTK_BOX (hbox), green);
    gtk_box_append (GTK_BOX (hbox), blue);
    gtk_box_append (GTK_BOX (vbox), area);
    
    gtk_window_set_title (GTK_WINDOW(win), "Toggle");
    gtk_window_set_default_size (GTK_WINDOW(win), 300, 200);
    
    gtk_widget_set_name (red,   "red");
    gtk_widget_set_name (green, "green");
    gtk_widget_set_name (blue,  "blue");

    gtk_widget_set_size_request (area, 100, 110);
    gtk_widget_set_hexpand (area, TRUE);
    gtk_widget_set_vexpand (area, TRUE);
    
		gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw, NULL, NULL);
    g_signal_connect (red,   "toggled", G_CALLBACK (color), area);
    g_signal_connect (green, "toggled", G_CALLBACK (color), area);
    g_signal_connect (blue,  "toggled", G_CALLBACK (color), area);
    
    gtk_window_present (GTK_WINDOW (win));
}

int main(int argc, char **argv)
{
    GtkApplication  *app;
    int             stat;
    
    app  = gtk_application_new ("jp.vivacocoa.togglebutton", 0 );
    g_signal_connect (app, "activate", G_CALLBACK( activate), NULL);
    stat = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    
    return stat;
}

コード説明

  1. static void
    color (GtkWidget *btn, GtkWidget *area)
    トグルボタンがクリックされたときに呼び出さる関数です。この関数で、グローバル変数 r, g, b の値を変更して、 実際の描画を gtk_widget_queue_draw 関数で draw 関数に依頼しています。
  2. static void
    draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
    実際に描画を担当している関数です。この関数の説明は「GTK4 カイロ」で詳しく説明します。この関数は ドローイングエリアが最初に表示されたときと、ドローイングエリアがリサイズされたときと、gtk_widget_queue_draw 関数が呼びだれたときに呼び出されます。
  3. gtk_widget_set_name (red, "red");
    どのトグルボタンかを識別できるように名前をつけています。static void color 関数では、この名前を利用して、 どの色の値を変更すれば良いかを判断しています。
  4. g_signal_connect (red, "toggled", G_CALLBACK (color), area);
    red トグルボタンで toggled イベントが発生したときに color 関数を呼び出します。color 関数の第1引数には red トグルボタンのポインターが渡され、color 関数の第2引数には g_signal_connect の第4引数のドローイングエリア (area) が渡されます。なお toggled イベントは、トグルボタンをクリックして、オンにしたときと、 オフにしたときに発生します。

コンパイルと実行

以下のとおりです。Windows の場合は通常版でも ARM64版 でも mingw64 で行ってください。


// コンパイル
cc `pkg-config --cflags gtk4` toggle.c -o toggle `pkg-config --libs gtk4`

もしくは

gcc $(pkg-config --cflags gtk4) -o toggle toggle.c $(pkg-config --libs gtk4)

もしくは

cc toggle.c -o toggle `pkg-config --cflags --libs gtk4`

// 実行
./toggle

何もオンにしていない時は黒色になります。

Blue をオンにすると青色が表示されます。

Green と Blue オンにすると、シアンという色になります。

Blue をオフにして Green だけをオンにすると、緑色になります。

光の三原色になっています。いろいろと試してみてください。

難しいほうのコードも残しておきます

toggle.c


/*************************************
    toggle.c
    copyright    :  vivacocoa.jp
    last modified:  Mar. 19, 2025
************************************/

#include <gtk/gtk.h>

static cairo_surface_t *surface = NULL;

static void
color (GtkWidget *btn, GtkWidget *area)
{
  static double r, g, b;
  
	if (g_strcmp0 (gtk_widget_get_name (btn), "red") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{r = 1.0;} else {r = 0.0;}
		gtk_widget_queue_draw (area);
	}
	if (g_strcmp0 (gtk_widget_get_name (btn), "green") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{g = 1.0;} else {g = 0.0;}
		gtk_widget_queue_draw (area);
	}
	if (g_strcmp0 (gtk_widget_get_name (btn), "blue") == 0)
	{
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn)))
		{b = 1.0;} else {b = 0.0;}
		gtk_widget_queue_draw (area);
	}
	cairo_t *cr;
	cr = cairo_create (surface);
	cairo_set_source_rgb (cr, r, g, b);
	cairo_paint (cr);
	cairo_destroy (cr);
}

static void
resize (GtkWidget *widget, int width, int height, gpointer data)
{
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
        gtk_widget_get_width (widget),
        gtk_widget_get_height (widget));
  color (widget, widget);
}

static void
draw (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data)
{
    cairo_set_source_surface (cr, surface, 0, 0);
    cairo_paint (cr);
}

static void
activate(GtkApplication *app, gpointer data)
{
    GtkWidget *win   = gtk_application_window_new (GTK_APPLICATION (app));
    GtkWidget *vbox  = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
    GtkWidget *hbox  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
    GtkWidget *area  = gtk_drawing_area_new ();
    GtkWidget *red   = gtk_toggle_button_new_with_label("Red");
    GtkWidget *green = gtk_toggle_button_new_with_label("Green");
    GtkWidget *blue  = gtk_toggle_button_new_with_label("Blue");
    
    gtk_window_set_child (GTK_WINDOW(win), vbox);
    
    gtk_box_append (GTK_BOX (vbox), hbox);
    gtk_box_append (GTK_BOX (hbox), red);
    gtk_box_append (GTK_BOX (hbox), green);
    gtk_box_append (GTK_BOX (hbox), blue);
    gtk_box_append (GTK_BOX (vbox), area);
    
    gtk_window_set_title (GTK_WINDOW(win), "Toggle");
    gtk_window_set_default_size (GTK_WINDOW(win), 300, 200);
    
    gtk_widget_set_name (red,   "red");
    gtk_widget_set_name (green, "green");
    gtk_widget_set_name (blue,  "blue");

    gtk_widget_set_size_request (area, 100, 100);
    gtk_widget_set_hexpand (area, TRUE);
    gtk_widget_set_vexpand (area, TRUE);
    
    g_signal_connect_after (area, "resize", G_CALLBACK (resize), NULL);
		gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw, NULL, NULL);
    g_signal_connect (red,   "toggled", G_CALLBACK (color), area);
    g_signal_connect (green, "toggled", G_CALLBACK (color), area);
    g_signal_connect (blue,  "toggled", G_CALLBACK (color), area);
    
    gtk_window_present (GTK_WINDOW (win));
}

int main(int argc, char **argv)
{
    GtkApplication  *app;
    int             stat;
    
    app  = gtk_application_new ("jp.vivacocoa.toggle", 0 );
    g_signal_connect (app, "activate", G_CALLBACK( activate), NULL);
    stat = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    
    return stat;
}


231 visits
Posted: Mar. 17, 2025
Update: Mar. 22, 2025

ホーム   C/C++チュートリアル   目次