gtk4 使用c语言开发界面之自定义组件

鉴于网上关于gtk4的文章很少,有关自定义组件的文章更是少的可怜,有好多都不能用了。所以写此文章以做记录。写此文章时,使用的gtk版本为4.8.3。

自定义组件步骤

1、定义控件的类型

定义控件类型有两种方式,
(1)、直接在c文件中定义类型;
(2)、先在头文件中使用G_DECLARE_FINAL_TYPE宏声明一个最终类型的结构体和类结构体。

1.1、直接在c文件中定义类型

typedef struct
{
    GtkBox parent_instance;
} MyWidget;

typedef struct
{
    GtkBoxClass klass;
} MyWidgetClass;
// 使用**G_DEFINE_TYPE**宏定义新控件的类型。这个宏会生成必要的类型定义和初始化函数。
G_DEFINE_TYPE(MyWidget, my_widget, GTK_TYPE_BOX);

1.2、在头文件中使用G_DECLARE_FINAL_TYPE宏声明一个最终类型的结构体和类结构体。

// .h文件
G_DECLARE_FINAL_TYPE(MyWidget, my_widget, MY, WIDGET, GtkBox)
// .c文件
struct _MyWidget
{
    GtkBox parent_instance;
};

struct _MyWidgetClass
{
    GtkBoxClass klass;
} ;
// 使用**G_DEFINE_TYPE**宏定义新控件的类型。这个宏会生成必要的类型定义和初始化函数。
G_DEFINE_TYPE(MyWidget, my_widget, GTK_TYPE_BOX);

2、实现初始化函数

由上步G_DEFINE_TYPE宏定义好一个MyWidget控件,该宏内部定义和实现了一系列方法(方法命名规则:控件名称_方法名称,如:my_widget_init),我们只需要重写我们需要的方法即可。以下只列举其中几个。

// 实例初始化函数,可以设置自定义控件的实例属性。
static void my_widget_init(MyWidget *self)
{
}
// 类初始化函数,可以设置自定义控件的类属性和方法。
static void my_widget_class_init(MyWidgetClass *klass)
{
}

3、创建自定义控件的实例化函数

使用g_object_new创建控件的实例。在创建之前需要定义一个宏,该宏指的是自定义控件的类型。

// MY_WIDGET_TYPE 自定义宏
// my_widget_get_type() G_DEFINE_TYPE 内部实现的一个方法
#define MY_WIDGET_TYPE my_widget_get_type() 
GtkWidget *my_widget_new(void)
{
    return g_object_new(MY_WIDGET_TYPE, NULL);
}

4、创建一个控件的实例,并将其添加到其他控件中。例如,将其添加到GtkWindow

    GtkWindow *win = GTK_WINDOW(gtk_builder_get_object(builder, "win"));
    gtk_application_add_window(app, win);
    // 创建一个控件实例
    GtkWidget *myWidget = my_widget_new();
    // 添加到窗口中
    gtk_window_set_child(win, myWidget);
    //
    gtk_window_present(win);

5、向自定义组件中填充内容

  • 重写snapshot方法
    gtk4中没有draw方法,取而代之的是snapshot方法,当需要重写绘制逻辑的时候就需要重写它。
//
static void on_override_snapshot(GtkWidget *widget, GtkSnapshot *snapshot)
{
    gtk_snapshot_append_color(snapshot, &(GdkRGBA){1.0, 0.0, 0.0, 1.0}, &GRAPHENE_RECT_INIT(100, 100, 100, 100));
    gtk_snapshot_save(snapshot);
}
//
static void my_widget_class_init(MyWidgetClass *klass)
{
    GtkWidgetClass *class = GTK_WIDGET_CLASS(klass);
    class->snapshot = on_override_snapshot;
}
  • 添加其他现有的控件
//
static void my_widget_init(MyWidget *self)
{
    GtkWidget *button = gtk_button_new_with_label("Button");
    gtk_box_append(GTK_BOX(self), button);
    gtk_widget_set_size_request(button, 400, 40);
}
//
static void my_widget_class_init(MyWidgetClass *klass)
{
}

6、在UI文件中加载自定义组件

要想在ui文件中加载自定义的组件,需要先注册自定义组件(一般在加载ui文件之前注册),注册的方法有两种:g_type_register_staticg_type_ensure
6.1、使用g_type_ensure宏注册组件

g_type_ensure(MY_WIDGET_TYPE); 

6.2、使用g_type_register_static函数注册组件

const GTypeInfo widget_info = {
    sizeof(MyWidgetClass),
    NULL, // base_init
    NULL, // base_finalize
    (GClassInitFunc)my_widget_class_init,
    NULL, // class_finalize
    NULL, // class_data
    sizeof(MyWidget),
    0, // n_preallocs
    (GInstanceInitFunc)my_widget_init,
    NULL // value_table
};
g_type_register_static(GTK_TYPE_BOX, "MyWidget", &widget_info, 0);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值