1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Windows(MSYS2)上でGTK4の開発を始める

Last updated at Posted at 2022-08-30

はじめに

とりあえずC言語でGUIを扱いたい人向け
ほぼ公式ドキュメントそのままですが、微妙に迷う可能性があったので記述

Raspberry Pi (初期のModel B)で動く軽量なGUIアプリを作りたいが、
Linuxデスクトップ環境より慣れたWindowsデスクトップ環境で扱いたかったため、試したきr

MSYS2のインストール

書いてある通りにインストールする。

GTK4を導入

インストール直後、MSYS2のウィンドウが動いているはずである。

以下を打ち込む。(pacmanは、UbuntuやDebianでいうところのapt-getに相当する)

pacman -S mingw-w64-x86_64-gtk4

次に以下。実行後、どのグループを導入するかを聞かれるが、そのままEnterを押せば良い。
途中一部でダウンロード失敗することがあるが、何度か繰り返し入れると進む。

pacman -S mingw-w64-x86_64-toolchain base-devel

参考

ソースをビルドする

MSYS2のウィンドウを閉じて、スタートメニューから MSYS2 MinGW x64 を起動する。
※ここを開き直さずにMSYS2のまま実行すると、pkg-configがエラーになる

エクスプローラから以下のフォルダを開き、ユーザー名のフォルダを開く。
(Linuxでの/homeの位置がMSYSではここになる)

C:\msys64\home\

お試し用に以下をmain.cとして保存する

main.c
static void print_hello(GtkWidget *widget, gpointer data){
	g_print("OK\n");
}

static void activate (GtkApplication* app, gpointer user_data)
{
	GtkWidget *window = gtk_application_window_new(app);
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window),640,480);

	GtkWidget *fixed = gtk_fixed_new();
	gtk_window_set_child(GTK_WINDOW(window),fixed);

	GtkWidget *button = gtk_button_new_with_label("Hello");
	gtk_widget_set_size_request(button,100,100);
	g_signal_connect(button,"clicked",G_CALLBACK(print_hello),NULL);

	gtk_fixed_put (GTK_FIXED(fixed), button, 100, 200);

	gtk_widget_show(window);
}

int main(int argc, char **argv)
{
	GtkApplication *app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
	g_signal_connect (app,"activate", G_CALLBACK(activate),NULL);
	
	int status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}

MSYS2 MinGW x64のウィンドウで以下を打ち込む

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

正常にビルドが終了したら実行する

./main.out

正常にウィンドウが立ち上がればOK

image.png

参考

おまけ: 別スレッドなどからのイベント処理

通常、メインループはGTK4に握られることになる。
そのため、GUIと関係ないイベント(通信など)を拾うにはどうすればよいか。

簡単なのは、別スレッドでイベントが発生したタイミングで、g_idle_addをコールする。
(なお、最低優先度で処理される。優先度を上げたい場合はg_idle_add_fullで優先度を指定する)

//コールバック
static gboolean idlefunc(gpointer user_data){
	g_print("idle\n");
	return false; //falseの場合は単発、trueの場合は繰り返し呼ばれる

    //常にtrueにした場合、かなりCPUを食うので注意。
    //連続した処理が必要な場合を除いて基本的にfalseで使用すべき
}


//GTK4の関数は基本的に別スレッドからのコールが禁止されているが、
//g_idle_add含む一部の関数はスレッドセーフになっている。
//これを呼び出すことで、低い優先度のタスクとしてGTK4のキューに関数が積まれる。タイミングが来るとコールバックが呼ばれる。
g_idle_add(G_SOURCE_FUNC(idlefunc),NULL);

おまけ: タイマー(定期処理、定期画面更新)

定期的なタイマー処理をしたい場合はg_timeout_addが便利。

static gboolean timerfunc(gpointer user_data){
	g_print("timer\n");
	return true; //falseの場合は単発、trueの場合は繰り返し500msごとに呼ばれる
}

int main(int argc, char **argv)
{
    ~~~~~~
	guint tag = g_timeout_add(500,timerfunc,NULL); //初回の呼び出しを500ms後に予約する
	//g_source_remove(tag); //removeで呼び出しを止めることもできる
    ~~~~~~
}


参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?