原文: http://zetcode.com/gui/gtk2/gtktextview/

在 GTK+ 编程教程的这一部分中,我们使用GtkTextView小部件。

GtkTextView小部件用于显示和编辑多行文本。 GtkTextView小部件也具有 MVC 设计。 GtkTextView代表视图组件,GtkTextBuffer代表模型组件。 GtkTextBuffer用于处理文本数据。 GtkTextTag是可以应用于文本的属性。 GtkTextIter表示文本中两个字符之间的位置。 所有使用文本的操作都是使用文本迭代器完成的。

简单的例子

在第一个示例中,我们显示一些GtkTextView's函数。 我们展示了如何将各种文本标签应用于文本数据。

simpletextview.c

  1. #include <gtk/gtk.h>
  2. int main(int argc, char *argv[]) {
  3. GtkWidget *window;
  4. GtkWidget *view;
  5. GtkWidget *vbox;
  6. GtkTextBuffer *buffer;
  7. GtkTextIter start, end;
  8. GtkTextIter iter;
  9. gtk_init(&argc, &argv);
  10. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  11. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  12. gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  13. gtk_window_set_title(GTK_WINDOW(window), "GtkTextView");
  14. vbox = gtk_vbox_new(FALSE, 0);
  15. view = gtk_text_view_new();
  16. gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
  17. buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  18. gtk_text_buffer_create_tag(buffer, "gap",
  19. "pixels_above_lines", 30, NULL);
  20. gtk_text_buffer_create_tag(buffer, "lmarg",
  21. "left_margin", 5, NULL);
  22. gtk_text_buffer_create_tag(buffer, "blue_fg",
  23. "foreground", "blue", NULL);
  24. gtk_text_buffer_create_tag(buffer, "gray_bg",
  25. "background", "gray", NULL);
  26. gtk_text_buffer_create_tag(buffer, "italic",
  27. "style", PANGO_STYLE_ITALIC, NULL);
  28. gtk_text_buffer_create_tag(buffer, "bold",
  29. "weight", PANGO_WEIGHT_BOLD, NULL);
  30. gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
  31. gtk_text_buffer_insert(buffer, &iter, "Plain text\n", -1);
  32. gtk_text_buffer_insert_with_tags_by_name(buffer, &iter,
  33. "Colored Text\n", -1, "blue_fg", "lmarg", NULL);
  34. gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
  35. "Text with colored background\n", -1, "lmarg", "gray_bg", NULL);
  36. gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
  37. "Text in italics\n", -1, "italic", "lmarg", NULL);
  38. gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
  39. "Bold text\n", -1, "bold", "lmarg", NULL);
  40. gtk_container_add(GTK_CONTAINER(window), vbox);
  41. g_signal_connect(G_OBJECT(window), "destroy",
  42. G_CALLBACK(gtk_main_quit), NULL);
  43. gtk_widget_show_all(window);
  44. gtk_main();
  45. return 0;
  46. }

该示例显示了一些应用了不同GtkTextTags的文本。

  1. view = gtk_text_view_new();

gtk_text_view_new()函数创建一个新的GtkTextView小部件。

  1. gtk_text_buffer_create_tag(buffer, "blue_fg",
  2. "foreground", "blue", NULL);

gtk_text_buffer_create_tag()函数创建一个标签,并将其添加到缓冲区的标签表中。 第二个参数是标签名称。 标签将文本的颜色更改为蓝色。

  1. gtk_text_buffer_insert_with_tags_by_name(buffer, &iter,
  2. "Colored Text\n", -1, "blue_fg", "lmarg", NULL);

gtk_text_buffer_insert_with_tags_by_name()函数插入带有blue_fglmarg文本标签的文本。 标签通过其名称识别。

`GtkTextView`小部件 - 图1

图:GtkTextView

行和列

下面的示例显示文本光标的当前行和列。

linescols.c

  1. #include <gtk/gtk.h>
  2. update_statusbar(GtkTextBuffer *buffer,
  3. GtkStatusbar *statusbar) {
  4. gchar *msg;
  5. gint row, col;
  6. GtkTextIter iter;
  7. gtk_statusbar_pop(statusbar, 0);
  8. gtk_text_buffer_get_iter_at_mark(buffer,
  9. &iter, gtk_text_buffer_get_insert(buffer));
  10. row = gtk_text_iter_get_line(&iter);
  11. col = gtk_text_iter_get_line_offset(&iter);
  12. msg = g_strdup_printf("Col: %d Ln: %d", col+1, row+1);
  13. gtk_statusbar_push(statusbar, 0, msg);
  14. g_free(msg);
  15. }
  16. void mark_set_callback(GtkTextBuffer *buffer,
  17. const GtkTextIter *new_location, GtkTextMark *mark, gpointer data) {
  18. update_statusbar(buffer, GTK_STATUSBAR(data));
  19. }
  20. int main(int argc, char *argv[]) {
  21. GtkWidget *window;
  22. GtkWidget *vbox;
  23. GtkWidget *toolbar;
  24. GtkWidget *view;
  25. GtkWidget *statusbar;
  26. GtkToolItem *exit;
  27. GtkTextBuffer *buffer;
  28. gtk_init(&argc, &argv);
  29. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  30. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  31. gtk_window_set_default_size(GTK_WINDOW(window), 350, 300);
  32. gtk_window_set_title(GTK_WINDOW(window), "Lines & columns");
  33. vbox = gtk_vbox_new(FALSE, 0);
  34. gtk_container_add(GTK_CONTAINER(window), vbox);
  35. toolbar = gtk_toolbar_new();
  36. gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
  37. exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
  38. gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
  39. gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
  40. view = gtk_text_view_new();
  41. gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
  42. gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
  43. gtk_widget_grab_focus(view);
  44. buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  45. statusbar = gtk_statusbar_new();
  46. gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
  47. g_signal_connect(G_OBJECT(exit), "clicked",
  48. G_CALLBACK(gtk_main_quit), NULL);
  49. g_signal_connect(buffer, "changed",
  50. G_CALLBACK(update_statusbar), statusbar);
  51. g_signal_connect_object(buffer, "mark_set",
  52. G_CALLBACK(mark_set_callback), statusbar, 0);
  53. g_signal_connect_swapped(G_OBJECT(window), "destroy",
  54. G_CALLBACK(gtk_main_quit), NULL);
  55. gtk_widget_show_all(window);
  56. update_statusbar(buffer, GTK_STATUSBAR(statusbar));
  57. gtk_main();
  58. return 0;
  59. }

在此代码示例中,我们在状态栏中显示文本光标的当前位置。

  1. g_signal_connect(buffer, "changed",
  2. G_CALLBACK(update_statusbar), statusbar);

更改文本时,我们将调用update_statusbar()处理器。

  1. g_signal_connect_object(buffer, "mark_set",
  2. G_CALLBACK(mark_set_callback), statusbar, 0);

光标移动时会发出mark_set信号。

  1. gtk_statusbar_pop(statusbar, 0);

此代码行从状态栏中清除上下文标识为 0 的消息。

  1. gtk_text_buffer_get_iter_at_mark(buffer,
  2. &iter, gtk_text_buffer_get_insert(buffer));
  3. row = gtk_text_iter_get_line(&iter);
  4. col = gtk_text_iter_get_line_offset(&iter);

这些行确定当前行和列。

  1. msg = g_strdup_printf("Col %d Ln %d", col+1, row+1);

g_strdup_printf()用于构建要在状态栏上显示的文本。

  1. gtk_statusbar_push(statusbar, 0, msg);

我们使用gtk_statusbar_push()函数在状态栏上显示文本。

`GtkTextView`小部件 - 图2

图:直线 and columns

搜索和高亮

在下一个示例中,我们在GtkTextBuffer中进行了一些搜索; 我们在文本缓冲区中高亮一些文本模式。

search.c

  1. #include <gtk/gtk.h>
  2. #include <gdk/gdkkeysyms.h>
  3. gboolean key_pressed(GtkWidget *window,
  4. GdkEventKey* event, GtkTextBuffer *buffer) {
  5. GtkTextIter start_sel, end_sel;
  6. GtkTextIter start_find, end_find;
  7. GtkTextIter start_match, end_match;
  8. gboolean selected;
  9. gchar *text;
  10. if ((event->type == GDK_KEY_PRESS) &&
  11. (event->state & GDK_CONTROL_MASK)) {
  12. switch (event->keyval) {
  13. case GDK_m :
  14. selected = gtk_text_buffer_get_selection_bounds(buffer,
  15. &start_sel, &end_sel);
  16. if (selected) {
  17. gtk_text_buffer_get_start_iter(buffer, &start_find);
  18. gtk_text_buffer_get_end_iter(buffer, &end_find);
  19. gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg",
  20. &start_find, &end_find);
  21. text = (gchar *) gtk_text_buffer_get_text(buffer, &start_sel,
  22. &end_sel, FALSE);
  23. while (gtk_text_iter_forward_search(&start_find, text,
  24. GTK_TEXT_SEARCH_TEXT_ONLY |
  25. GTK_TEXT_SEARCH_VISIBLE_ONLY,
  26. &start_match, &end_match, NULL)) {
  27. gtk_text_buffer_apply_tag_by_name(buffer, "gray_bg",
  28. &start_match, &end_match);
  29. gint offset = gtk_text_iter_get_offset(&end_match);
  30. gtk_text_buffer_get_iter_at_offset(buffer,
  31. &start_find, offset);
  32. }
  33. g_free(text);
  34. }
  35. break;
  36. case GDK_r:
  37. gtk_text_buffer_get_start_iter(buffer, &start_find);
  38. gtk_text_buffer_get_end_iter(buffer, &end_find);
  39. gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg",
  40. &start_find, &end_find);
  41. break;
  42. }
  43. }
  44. return FALSE;
  45. }
  46. int main(int argc, gchar *argv[]) {
  47. GtkWidget *window;
  48. GtkWidget *view;
  49. GtkWidget *vbox;
  50. GtkTextBuffer *buffer;
  51. GtkTextIter start, end;
  52. GtkTextIter iter;
  53. gtk_init(&argc, &argv);
  54. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  55. gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  56. gtk_window_set_default_size(GTK_WINDOW(window), 350, 300);
  57. gtk_window_set_title(GTK_WINDOW(window), "Search & highlight");
  58. GTK_WINDOW(window)->allow_shrink = TRUE;
  59. vbox = gtk_vbox_new(FALSE, 0);
  60. view = gtk_text_view_new();
  61. gtk_widget_add_events(view, GDK_BUTTON_PRESS_MASK);
  62. gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
  63. buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  64. gtk_text_buffer_create_tag(buffer, "gray_bg",
  65. "background", "lightgray", NULL);
  66. gtk_container_add(GTK_CONTAINER(window), vbox);
  67. g_signal_connect(G_OBJECT(window), "destroy",
  68. G_CALLBACK(gtk_main_quit), NULL);
  69. g_signal_connect(G_OBJECT(window), "key-press-event",
  70. G_CALLBACK(key_pressed), buffer);
  71. gtk_widget_show_all(window);
  72. gtk_main();
  73. return 0;
  74. }

在我们的代码示例中,我们使用键盘快捷键。 Ctrl + M 快捷键高亮所有当前选中的文本。 Ctrl + R 从文本中删除高亮的内容。

  1. gtk_text_buffer_create_tag(buffer, "gray_bg",
  2. "background", "lightgray", NULL);

这是我们在示例中使用的GtkTextTag。 标签将文本的背景设为灰色。

  1. selected = gtk_text_buffer_get_selection_bounds(buffer,
  2. &start_sel, &end_sel);

使用gtk_text_buffer_get_selection_bounds()函数,我们可以获得所选文本的开始和结束位置。

  1. gtk_text_buffer_get_start_iter(buffer, &start_find);
  2. gtk_text_buffer_get_end_iter(buffer, &end_find);

我们获得文本缓冲区中的第一个和最后一个位置。

  1. gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg",
  2. &start_find, &end_find);

使用gtk_text_buffer_remove_tag_by_name()函数,我们可以删除所有以前的文本标签。

  1. text = (gchar *) gtk_text_buffer_get_text(buffer, &start_sel,
  2. &end_sel, FALSE);

我们获得选定的文本。 这是我们要搜索的文本。

  1. while (gtk_text_iter_forward_search(&start_find, text,
  2. GTK_TEXT_SEARCH_TEXT_ONLY |
  3. GTK_TEXT_SEARCH_VISIBLE_ONLY,
  4. &start_match, &end_match, NULL)) {
  5. gtk_text_buffer_apply_tag_by_name(buffer, "gray_bg",
  6. &start_match, &end_match);
  7. gint offset = gtk_text_iter_get_offset(&end_match);
  8. gtk_text_buffer_get_iter_at_offset(buffer,
  9. &start_find, offset);
  10. }

此代码搜索所有出现的所选文本。 如果找到任何匹配项,则应用文本标签。 匹配之后,单词的终点成为下一次搜索的起点。

`GtkTextView`小部件 - 图3

图:搜索和突出显示

在本章中,我们介绍了GtkTextView小部件。