GTK
GNOMEデスクトップ環境の基盤となるマルチプラットフォームGUIツールキット。オブジェクト指向設計とテーマシステムによる高いカスタマイズ性。アクセシビリティサポートと国際化機能が充実。
GitHub概要
GNOME/gtk
Read-only mirror of https://gitlab.gnome.org/GNOME/gtk
スター1,561
ウォッチ79
フォーク389
作成日:2012年6月3日
言語:C
ライセンス:Other
トピックス
なし
スター履歴
データ取得日時: 2025/7/15 22:54
フレームワーク
GTK
概要
GTKは、GNOMEデスクトップ環境の基盤となっているクロスプラットフォームGUIツールキットです。C言語で開発され、GObject型システムに基づいて構築されており、Linux/Unix系システムでのデスクトップアプリケーション開発において標準的な位置を占めています。
詳細
GTKは2025年現在、GTK 4が安定版として提供されており、30年以上の歴史を持つ成熟したGUIフレームワークです。GNOME、XFCE、LXDEなどの主要なLinuxデスクトップ環境で使用され、多くのオープンソースアプリケーションの基盤として採用されています。
GTKの主要な特徴:
- ネイティブパフォーマンス: C言語による高性能なネイティブ実行
- 豊富なウィジェット: 包括的なGUIコンポーネントセット
- テーマ対応: CSS-likeスタイルシステムによる柔軟なカスタマイズ
- アクセシビリティ: AT-SPIによる優秀なアクセシビリティサポート
- 国際化: 完全なi18n/l10nサポート
- クロスプラットフォーム: Linux、Windows、macOSでの動作
2025年現在、Firefox、GIMP、LibreOffice(一部)、VSCodeなど、多くの主要アプリケーションがGTKを採用しています。
メリット・デメリット
メリット
- Linux統合: Linux/UNIXシステムでの完全なネイティブ体験
- 高性能: C言語による最適化されたパフォーマンス
- 安定性: 30年以上の実績による高い安定性
- 豊富な機能: 包括的なウィジェットセットとレイアウトマネージャー
- フリーソフトウェア: LGPLライセンスによる自由な利用
- コミュニティ: 大規模で活発な開発コミュニティ
- ドキュメント: 豊富な公式ドキュメントとチュートリアル
- バインディング: Python、Rust、Vala等の多言語バインディング
デメリット
- 学習曲線: C言語とGObjectシステムの理解が必要
- Windows/macOS体験: ネイティブルック&フィールが制限される
- 開発ツール: IDEサポートがQt等と比較して限定的
- パッケージング: 各プラットフォームでの配布が複雑
- モダンUI: 最新のUIデザイントレンドへの対応が限定的
- メモリ使用量: GObjectシステムによるオーバーヘッド
主要リンク
書き方の例
基本的なGTKアプリケーション
// main.c
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;
// メインウィンドウを作成
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "GTK Hello World");
gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
// レイアウトコンテナを作成
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
gtk_window_set_child (GTK_WINDOW (window), box);
// ボタンを作成
button = gtk_button_new_with_label ("Hello World");
// シグナルの接続
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_box_append (GTK_BOX (box), button);
// ウィンドウを表示
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.example.HelloWorld", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
GtkBuilderを使用したUI設計
<!-- interface.ui -->
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object id="window" class="GtkWindow">
<property name="title">GTK Builder Example</property>
<property name="default-width">400</property>
<property name="default-height">300</property>
<child>
<object id="main_box" class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">10</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<child>
<object id="header_label" class="GtkLabel">
<property name="label">GTK Builder Demo</property>
<property name="halign">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object id="input_frame" class="GtkFrame">
<property name="label">入力エリア</property>
<child>
<object id="input_grid" class="GtkGrid">
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object id="name_label" class="GtkLabel">
<property name="label">名前:</property>
<property name="halign">end</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object id="name_entry" class="GtkEntry">
<property name="placeholder-text">お名前を入力してください</property>
<property name="hexpand">true</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object id="message_label" class="GtkLabel">
<property name="label">メッセージ:</property>
<property name="halign">end</property>
<property name="valign">start</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object id="message_textview" class="GtkTextView">
<property name="height-request">100</property>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object id="button_box" class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">10</property>
<property name="halign">center</property>
<child>
<object id="submit_button" class="GtkButton">
<property name="label">送信</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<child>
<object id="clear_button" class="GtkButton">
<property name="label">クリア</property>
</object>
</child>
</object>
</child>
<child>
<object id="output_frame" class="GtkFrame">
<property name="label">出力</property>
<child>
<object id="output_label" class="GtkLabel">
<property name="label">ここに結果が表示されます</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="wrap">true</property>
<property name="selectable">true</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
// builder_app.c
#include <gtk/gtk.h>
typedef struct {
GtkWidget *window;
GtkWidget *name_entry;
GtkWidget *message_textview;
GtkWidget *output_label;
GtkTextBuffer *text_buffer;
} AppWidgets;
static void
on_submit_clicked (GtkButton *button, AppWidgets *widgets)
{
const char *name;
char *message;
char *output_text;
GtkTextIter start, end;
// 名前を取得
name = gtk_editable_get_text (GTK_EDITABLE (widgets->name_entry));
// メッセージを取得
gtk_text_buffer_get_bounds (widgets->text_buffer, &start, &end);
message = gtk_text_buffer_get_text (widgets->text_buffer, &start, &end, FALSE);
// 出力テキストを作成
if (strlen (name) > 0 && strlen (message) > 0) {
output_text = g_strdup_printf ("名前: %s\nメッセージ: %s", name, message);
} else {
output_text = g_strdup ("名前とメッセージを入力してください。");
}
// 結果を表示
gtk_label_set_text (GTK_LABEL (widgets->output_label), output_text);
g_free (message);
g_free (output_text);
}
static void
on_clear_clicked (GtkButton *button, AppWidgets *widgets)
{
// フィールドをクリア
gtk_editable_set_text (GTK_EDITABLE (widgets->name_entry), "");
gtk_text_buffer_set_text (widgets->text_buffer, "", -1);
gtk_label_set_text (GTK_LABEL (widgets->output_label), "ここに結果が表示されます");
}
static void
activate (GtkApplication *app, gpointer user_data)
{
AppWidgets *widgets = g_new0 (AppWidgets, 1);
GtkBuilder *builder;
GtkWidget *submit_button, *clear_button;
GError *error = NULL;
// BuilderでUIを読み込み
builder = gtk_builder_new ();
if (!gtk_builder_add_from_file (builder, "interface.ui", &error)) {
g_printerr ("UIファイルの読み込みエラー: %s\n", error->message);
g_error_free (error);
return;
}
// ウィジェットを取得
widgets->window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
widgets->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
widgets->message_textview = GTK_WIDGET (gtk_builder_get_object (builder, "message_textview"));
widgets->output_label = GTK_WIDGET (gtk_builder_get_object (builder, "output_label"));
submit_button = GTK_WIDGET (gtk_builder_get_object (builder, "submit_button"));
clear_button = GTK_WIDGET (gtk_builder_get_object (builder, "clear_button"));
// TextBufferを取得
widgets->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widgets->message_textview));
// アプリケーションとウィンドウを関連付け
gtk_window_set_application (GTK_WINDOW (widgets->window), app);
// シグナルの接続
g_signal_connect (submit_button, "clicked", G_CALLBACK (on_submit_clicked), widgets);
g_signal_connect (clear_button, "clicked", G_CALLBACK (on_clear_clicked), widgets);
// ウィンドウを表示
gtk_window_present (GTK_WINDOW (widgets->window));
// Builderのクリーンアップ
g_object_unref (builder);
}
int
main (int argc, char *argv[])
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.example.BuilderApp", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
描画とCanvasアプリケーション
// drawing_app.c
#include <gtk/gtk.h>
/* 描画用のサーフェス */
static cairo_surface_t *surface = NULL;
static void
clear_surface (void)
{
cairo_t *cr;
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1, 1, 1); // 白で塗りつぶし
cairo_paint (cr);
cairo_destroy (cr);
}
/* 描画エリアのリサイズ */
static void
resize_cb (GtkWidget *widget,
int width,
int height,
gpointer data)
{
if (surface) {
cairo_surface_destroy (surface);
surface = NULL;
}
if (gtk_native_get_surface (gtk_widget_get_native (widget))) {
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
gtk_widget_get_width (widget),
gtk_widget_get_height (widget));
clear_surface ();
}
}
/* 描画コールバック */
static void
draw_cb (GtkDrawingArea *drawing_area,
cairo_t *cr,
int width,
int height,
gpointer data)
{
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
}
/* ブラシで描画 */
static void
draw_brush (GtkWidget *widget, double x, double y)
{
cairo_t *cr;
if (surface == NULL)
return;
cr = cairo_create (surface);
cairo_rectangle (cr, x - 3, y - 3, 6, 6);
cairo_fill (cr);
cairo_destroy (cr);
/* 描画エリアを更新 */
gtk_widget_queue_draw (widget);
}
/* ドラッグ開始 */
static void
drag_begin (GtkGestureDrag *gesture,
double x,
double y,
GtkWidget *area)
{
draw_brush (area, x, y);
}
/* ドラッグ更新 */
static void
drag_update (GtkGestureDrag *gesture,
double x,
double y,
GtkWidget *area)
{
double start_x, start_y;
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
draw_brush (area, start_x + x, start_y + y);
}
/* 右クリックでクリア */
static void
pressed (GtkGestureClick *gesture,
int n_press,
double x,
double y,
GtkWidget *area)
{
clear_surface ();
gtk_widget_queue_draw (area);
}
/* ウィンドウクローズ時のクリーンアップ */
static void
close_window (void)
{
if (surface)
cairo_surface_destroy (surface);
}
static void
activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *frame;
GtkWidget *drawing_area;
GtkGesture *drag;
GtkGesture *press;
// メインウィンドウを作成
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "描画アプリケーション");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
// フレームを作成
frame = gtk_frame_new (NULL);
gtk_window_set_child (GTK_WINDOW (window), frame);
// 描画エリアを作成
drawing_area = gtk_drawing_area_new ();
gtk_widget_set_size_request (drawing_area, 100, 100);
gtk_frame_set_child (GTK_FRAME (frame), drawing_area);
// 描画コールバックを設定
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), draw_cb, NULL, NULL);
// リサイズシグナルを接続
g_signal_connect_after (drawing_area, "resize", G_CALLBACK (resize_cb), NULL);
// ドラッグジェスチャーを設定(左ボタン)
drag = gtk_gesture_drag_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (drag));
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), drawing_area);
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_update), drawing_area);
// クリックジェスチャーを設定(右ボタン)
press = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (press), GDK_BUTTON_SECONDARY);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (press));
g_signal_connect (press, "pressed", G_CALLBACK (pressed), drawing_area);
// ウィンドウを表示
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.example.DrawingApp", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
リストビューとモデル
// listview_app.c
#include <gtk/gtk.h>
/* データアイテムの構造 */
typedef struct {
GObject parent_instance;
char *name;
char *description;
int priority;
} TaskItem;
typedef struct {
GObjectClass parent_class;
} TaskItemClass;
G_DEFINE_TYPE (TaskItem, task_item, G_TYPE_OBJECT)
static void
task_item_finalize (GObject *object)
{
TaskItem *item = (TaskItem *)object;
g_free (item->name);
g_free (item->description);
G_OBJECT_CLASS (task_item_parent_class)->finalize (object);
}
static void
task_item_class_init (TaskItemClass *class)
{
G_OBJECT_CLASS (class)->finalize = task_item_finalize;
}
static void
task_item_init (TaskItem *item)
{
// 初期化処理
}
static TaskItem *
task_item_new (const char *name, const char *description, int priority)
{
TaskItem *item = g_object_new (task_item_get_type (), NULL);
item->name = g_strdup (name);
item->description = g_strdup (description);
item->priority = priority;
return item;
}
/* リストアイテムの設定 */
static void
setup_listitem (GtkSignalListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *name_label, *desc_label, *priority_label;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_widget_set_margin_top (box, 8);
gtk_widget_set_margin_bottom (box, 8);
gtk_widget_set_margin_start (box, 12);
gtk_widget_set_margin_end (box, 12);
name_label = gtk_label_new (NULL);
gtk_label_set_xalign (GTK_LABEL (name_label), 0.0);
gtk_widget_add_css_class (name_label, "heading");
desc_label = gtk_label_new (NULL);
gtk_label_set_xalign (GTK_LABEL (desc_label), 0.0);
gtk_widget_add_css_class (desc_label, "dim-label");
priority_label = gtk_label_new (NULL);
gtk_label_set_xalign (GTK_LABEL (priority_label), 1.0);
gtk_widget_add_css_class (priority_label, "caption");
gtk_box_append (GTK_BOX (box), name_label);
gtk_box_append (GTK_BOX (box), desc_label);
gtk_box_append (GTK_BOX (box), priority_label);
gtk_list_item_set_child (list_item, box);
g_object_set_data (G_OBJECT (list_item), "name_label", name_label);
g_object_set_data (G_OBJECT (list_item), "desc_label", desc_label);
g_object_set_data (G_OBJECT (list_item), "priority_label", priority_label);
}
/* リストアイテムのデータバインディング */
static void
bind_listitem (GtkSignalListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *name_label, *desc_label, *priority_label;
TaskItem *item;
char *priority_text;
item = gtk_list_item_get_item (list_item);
name_label = g_object_get_data (G_OBJECT (list_item), "name_label");
desc_label = g_object_get_data (G_OBJECT (list_item), "desc_label");
priority_label = g_object_get_data (G_OBJECT (list_item), "priority_label");
gtk_label_set_text (GTK_LABEL (name_label), item->name);
gtk_label_set_text (GTK_LABEL (desc_label), item->description);
priority_text = g_strdup_printf ("優先度: %d", item->priority);
gtk_label_set_text (GTK_LABEL (priority_label), priority_text);
g_free (priority_text);
}
static void
activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *scrolled_window;
GtkWidget *list_view;
GListStore *model;
GtkListItemFactory *factory;
GtkSingleSelection *selection_model;
// メインウィンドウを作成
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "タスクリスト");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
// スクロールウィンドウを作成
scrolled_window = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), scrolled_window);
// リストモデルを作成
model = g_list_store_new (task_item_get_type ());
// サンプルデータを追加
g_list_store_append (model, task_item_new ("ドキュメント作成", "プロジェクトの技術仕様書を作成する", 1));
g_list_store_append (model, task_item_new ("コードレビュー", "チームメンバーのコードをレビューする", 2));
g_list_store_append (model, task_item_new ("バグ修正", "報告されたバグを修正する", 1));
g_list_store_append (model, task_item_new ("新機能開発", "ユーザー認証機能を実装する", 3));
g_list_store_append (model, task_item_new ("テスト作成", "単体テストとE2Eテストを作成する", 2));
// セレクションモデルを作成
selection_model = gtk_single_selection_new (G_LIST_MODEL (model));
// リストアイテムファクトリーを作成
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem), NULL);
// リストビューを作成
list_view = gtk_list_view_new (GTK_SELECTION_MODEL (selection_model), factory);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), list_view);
// ウィンドウを表示
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.example.TaskListApp", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
CSSスタイリング
/* style.css */
@import url("resource:///org/gtk/libgtk/theme/Adwaita/gtk.css");
.main-window {
background-color: #f6f5f4;
color: #2e3436;
}
.title-1 {
font-size: 2em;
font-weight: bold;
color: #1c71d8;
margin-bottom: 1em;
}
.card {
background-color: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
margin: 12px;
padding: 16px;
}
.header-bar {
background: linear-gradient(to bottom, #3584e4, #1c71d8);
color: white;
}
.sidebar {
background-color: #fafafa;
border-right: 1px solid #d3d3d3;
min-width: 250px;
}
.content-area {
padding: 20px;
background-color: white;
}
.suggested-action {
background: linear-gradient(to bottom, #57e389, #33d17a);
color: white;
border: none;
border-radius: 6px;
padding: 8px 16px;
font-weight: bold;
}
.suggested-action:hover {
background: linear-gradient(to bottom, #33d17a, #26a269);
}
.destructive-action {
background: linear-gradient(to bottom, #f66151, #e01b24);
color: white;
border: none;
border-radius: 6px;
padding: 8px 16px;
font-weight: bold;
}
.destructive-action:hover {
background: linear-gradient(to bottom, #e01b24, #a51d2d);
}
.entry {
border: 1px solid #d3d3d3;
border-radius: 6px;
padding: 8px 12px;
background-color: white;
}
.entry:focus {
border-color: #3584e4;
box-shadow: 0 0 0 2px rgba(53, 132, 228, 0.3);
}
.frame {
border: 1px solid #d3d3d3;
border-radius: 6px;
background-color: white;
}
.frame > label {
color: #5e5c64;
font-weight: bold;
padding: 0 6px;
background-color: white;
}
listview row {
border-bottom: 1px solid #f0f0f0;
padding: 8px;
}
listview row:hover {
background-color: rgba(53, 132, 228, 0.1);
}
listview row:selected {
background-color: #3584e4;
color: white;
}
.dim-label {
opacity: 0.65;
}
.caption {
font-size: 0.8em;
opacity: 0.75;
}
.status-bar {
background-color: #f0f0f0;
border-top: 1px solid #d3d3d3;
padding: 4px 8px;
}
.toolbar {
background: linear-gradient(to bottom, #fafafa, #ededed);
border-bottom: 1px solid #d3d3d3;
padding: 6px;
}
.circular {
border-radius: 50%;
}
.warning {
color: #e5a50a;
}
.error {
color: #e01b24;
}
.success {
color: #26a269;
}
Mesonビルド設定
# meson.build
project('gtk-demo-app', 'c',
version : '1.0.0',
default_options : ['warning_level=3',
'c_std=c11'])
# 依存関係
gtk_dep = dependency('gtk4')
glib_dep = dependency('glib-2.0')
# リソースファイルの処理
gnome = import('gnome')
resources = gnome.compile_resources('app-resources',
'resources.gresource.xml',
source_dir: 'resources')
# 実行ファイル
executable('gtk-demo-app',
['main.c', 'window.c'] + resources,
dependencies : [gtk_dep, glib_dep],
install : true)
# デスクトップファイル
install_data('org.example.GtkDemoApp.desktop',
install_dir : get_option('datadir') / 'applications')
# アイコン
install_data('icons/org.example.GtkDemoApp.svg',
install_dir : get_option('datadir') / 'icons/hicolor/scalable/apps')
<!-- resources.gresource.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/example/GtkDemoApp">
<file preprocess="xml-stripblanks">ui/window.ui</file>
<file preprocess="xml-stripblanks">ui/preferences.ui</file>
<file>css/style.css</file>
<file>icons/preferences-symbolic.svg</file>
<file>icons/help-symbolic.svg</file>
</gresource>
</gresources>
ビルドとインストール
# Mesonプロジェクトの設定
meson setup builddir
# ビルド
meson compile -C builddir
# テスト実行
meson test -C builddir
# インストール
meson install -C builddir
# 開発用実行
./builddir/gtk-demo-app
# クリーンビルド
rm -rf builddir
meson setup builddir
meson compile -C builddir
pkg-configを使用したコンパイル
# 単一ファイルのコンパイル
gcc -o hello `pkg-config --cflags --libs gtk4` hello.c
# 複数ファイルのコンパイル
gcc -o myapp `pkg-config --cflags --libs gtk4` main.c window.c
# デバッグビルド
gcc -g -O0 -o myapp `pkg-config --cflags --libs gtk4` *.c
# 最適化ビルド
gcc -O2 -o myapp `pkg-config --cflags --libs gtk4` *.c
プラットフォーム別の特別な考慮事項
Linux
- パッケージマネージャーでの簡単インストール
- 豊富なテーマとアイコンセット
- Waylandプロトコル完全サポート
- システム統合(デスクトップファイル、DBus)
Windows
- MSYS2やVcpkgでの開発環境構築
- Windows APIとの相互運用性
- HiDPIサポート
- MSIインストーラー作成
macOS
- Homebrewでのインストール
- macOSルック&フィール調整
- App Bundleパッケージング
- macOS特有のUI/UXガイドライン対応