四、Gtk4-Widgets (2)

文章展示了如何使用GTK4库创建一个简单的文本编辑器,通过GtkTextView进行文本显示和编辑,利用GtkTextBuffer存储文本内容,并通过添加GtkScrolledWindow解决窗口大小固定的问题,实现文本超出时的滚动功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 GtkTextView,GtkTextBuffer and GtkScrolledWindow

GtkTextView and GtkTextBuffer

GtkTextView是一个用于多行文本编辑的构件。GtkTextBuffer是一个连接到GtkTextView的文本缓冲区。请参阅下面的示例程序tfv1.c。

 1 #include <gtk/gtk.h>
 2 
 3 static void
 4 app_activate (GApplication *app) {
 5   GtkWidget *win;
 6   GtkWidget *tv;
 7   GtkTextBuffer *tb;
 8   gchar *text;
 9 
10   text =
11       "Once upon a time, there was an old man who was called Taketori-no-Okina. "
12       "It is a japanese word that means a man whose work is making bamboo baskets.\n"
13       "One day, he went into a mountain and found a shining bamboo. "
14       "\"What a mysterious bamboo it is!,\" he said. "
15       "He cut it, then there was a small cute baby girl in it. "
16       "The girl was shining faintly. "
17       "He thought this baby girl is a gift from Heaven and took her home.\n"
18       "His wife was surprized at his story. "
19       "They were very happy because they had no children. "
20       ;
21   win = gtk_application_window_new (GTK_APPLICATION (app));
22   gtk_window_set_title (GTK_WINDOW (win), "Taketori");
23   gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
24 
25   tv = gtk_text_view_new ();
26   tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
27   gtk_text_buffer_set_text (tb, text, -1);
28   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
29 
30   gtk_window_set_child (GTK_WINDOW (win), tv);
31 
32   gtk_window_present (GTK_WINDOW (win));
33 }
34 
35 int
36 main (int argc, char **argv) {
37   GtkApplication *app;
38   int stat;
39 
40   app = gtk_application_new ("com.github.ToshioCP.tfv1", G_APPLICATION_DEFAULT_FLAGS);
41   g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
42   stat = g_application_run (G_APPLICATION (app), argc, argv);
43   g_object_unref (app);
44   return stat;
45 }

请看第25行。创建了一个GtkTextView实例,并将其指针赋值给tv。当GtkTextView实例被创建时,一个GtkTextBuffer实例也被创建并自动连接到GtkTextView。“GtkTextBuffer实例”将被简称为“GtkTextBuffer”或“buffer”。在下一行,指向缓冲区的指针被赋值为tb。然后,第10 ~ 20行的文本被分配给缓冲区。如果gtk_text_buffer_set_text的第三个参数是一个正整数,则它是文本的长度。如果是-1,字符串以NULL结束(\0结束)。

GtkTextView有一个wrap换行模式。当设置为GTK_WRAP_WORD_CHAR时,文本换行在单词之间,如果这还不够,还可以换行在字母之间。

换行模式是用GTK 4 API文档中的Gtk_WrapMode编写的。

第30行,tv添加到了win,作为一个子构件。

现在编译并运行它。

$ cd src/tfv
$ comp tfv1
$ ./a.out

在窗口里有一个光标。在GtkTextView里面,您可以添加或删除任何字符,和您的增删可以保存在GtkTextBuffer。如果你添加的字符超过了窗口的限制,高度会增加,窗口会扩展。如果窗口的高度大于显示屏幕的高度,你将无法控制窗口的大小或将其更改为原始大小。这是一个问题,也就是bug。这可以通过在GtkApplicationWindow和GtkTextView之间添加一个GtkScrolledWindow来解决。

GtkScrolledWindow

我们需要做的是:

  • 创建一个GtkScrolledWindow,并将其作为GtkApplicationWindow的一个子构件插入
  • 将GtkTextView构件作为子窗口插入到GtkScrolledWindow。

修改tfv1.c并保存为tfv2.c。这两个文件只有一点不同。

$ cd tfv; diff tfv1.c tfv2.c
5a6
>   GtkWidget *scr;
24a26,28
>   scr = gtk_scrolled_window_new ();
>   gtk_window_set_child (GTK_WINDOW (win), scr);
> 
30c34
<   gtk_window_set_child (GTK_WINDOW (win), tv);
---
>   gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
40c44
<   app = gtk_application_new ("com.github.ToshioCP.tfv1", G_APPLICATION_DEFAULT_FLAGS);
---
>   app = gtk_application_new ("com.github.ToshioCP.tfv2", G_APPLICATION_DEFAULT_FLAGS);

tfv2.c的整个代码如下:

 1 #include <gtk/gtk.h>
 2 
 3 static void
 4 app_activate (GApplication *app) {
 5   GtkWidget *win;
 6   GtkWidget *scr;
 7   GtkWidget *tv;
 8   GtkTextBuffer *tb;
 9   gchar *text;
10 
11   text =
12       "Once upon a time, there was an old man who was called Taketori-no-Okina. "
13       "It is a japanese word that means a man whose work is making bamboo baskets.\n"
14       "One day, he went into a mountain and found a shining bamboo. "
15       "\"What a mysterious bamboo it is!,\" he said. "
16       "He cut it, then there was a small cute baby girl in it. "
17       "The girl was shining faintly. "
18       "He thought this baby girl is a gift from Heaven and took her home.\n"
19       "His wife was surprized at his story. "
20       "They were very happy because they had no children. "
21       ;
22   win = gtk_application_window_new (GTK_APPLICATION (app));
23   gtk_window_set_title (GTK_WINDOW (win), "Taketori");
24   gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
25 
26   scr = gtk_scrolled_window_new ();
27   gtk_window_set_child (GTK_WINDOW (win), scr);
28 
29   tv = gtk_text_view_new ();
30   tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
31   gtk_text_buffer_set_text (tb, text, -1);
32   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
33 
34   gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
35 
36   gtk_window_present (GTK_WINDOW (win));
37 }
38 
39 int
40 main (int argc, char **argv) {
41   GtkApplication *app;
42   int stat;
43 
44   app = gtk_application_new ("com.github.ToshioCP.tfv2", G_APPLICATION_DEFAULT_FLAGS);
45   g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
46   stat = g_application_run (G_APPLICATION (app), argc, argv);
47   g_object_unref (app);
48   return stat;
49 }

编译并运行它。

现在,即使你输入了很多字符,窗口也不会扩展,它只是滚动。

参考:Gtk4-tutorial Widgets (2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值