zoukankan      html  css  js  c++  java
  • Gtk中的文本视图(GtkTexViewWidget)

    Gtk中的文本视图(GtkTexViewWidget)

    Gtk中的文本视图(GtkTexView Widget)

    在本章的Gtk+程序设计教程中,我们将重点介绍 GtkTexView 构件。

    GtkTexView w构件被常常用来显示和编辑多行的文本。正如我们一再提到的, GtkTexBuffer 构件也是给予MVC的设计。GtkTextView 就是显示(view)元素而 GtkTexBuffer 则代表了model 元素。 GtkTexBuffer 常常被用来处理文本数据。GtkTextTag则是一种被用于文本的属性。 GtkTextIter则是代表了两个字符之间的空隙。那么很好理解,文本的排版操作多用iterators。

    简单的例子(Simple example)

    在我们的第一个例子中,我们将向大家展示GtkTexView 的一些功能。我们还将教大家怎么样去应用各种各样的文本标记( tags )。

    #include <gtk/gtk.h>
    
    
    int main( int argc, char *argv[])
    {
    
      GtkWidget *window;
      GtkWidget *view;
      GtkWidget *vbox;
      
      GtkTextBuffer *buffer;
      GtkTextIter start, end;
      GtkTextIter iter;
    
      gtk_init(&argc, &argv);
    
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 250, 200);
      gtk_window_set_title(GTK_WINDOW(window), "TextView");
      gtk_container_set_border_width(GTK_CONTAINER(window), 5);
      GTK_WINDOW(window)->allow_shrink = TRUE;
    
      vbox = gtk_vbox_new(FALSE, 0);
      view = gtk_text_view_new();
      gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
    
      buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
    
      gtk_text_buffer_create_tag(buffer, "gap",
            "pixels_above_lines", 30, NULL);
    
      gtk_text_buffer_create_tag(buffer, "lmarg", 
          "left_margin", 5, NULL);
      gtk_text_buffer_create_tag(buffer, "blue_fg", 
          "foreground", "blue", NULL); 
      gtk_text_buffer_create_tag(buffer, "gray_bg", 
          "background", "gray", NULL); 
      gtk_text_buffer_create_tag(buffer, "italic", 
          "style", PANGO_STYLE_ITALIC, NULL);
      gtk_text_buffer_create_tag(buffer, "bold", 
          "weight", PANGO_WEIGHT_BOLD, NULL);
    
      gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
    
      gtk_text_buffer_insert(buffer, &iter, "Plain text
    ", -1);
      gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, 
            "Colored Text
    ", -1, "blue_fg", "lmarg",  NULL);
      gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
            "Text with colored background
    ", -1, "lmarg", "gray_bg", NULL);
    
      gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
            "Text in italics
    ", -1, "italic", "lmarg",  NULL);
    
      gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
            "Bold text
    ", -1, "bold", "lmarg",  NULL);
    
      gtk_container_add(GTK_CONTAINER(window), vbox);
    
      g_signal_connect_swapped(G_OBJECT(window), "destroy",
            G_CALLBACK(gtk_main_quit), G_OBJECT(window));
    
      gtk_widget_show_all(window);
    
      gtk_main();
    
      return 0;
    }
    

    这个例子展示了如何利用各种各样的文本标记( GtkTextTags)来显示文本。

    view = gtk_text_view_new();
    

    生成一个GtkTextView

    gtk_text_buffer_create_tag(buffer, "blue_fg", 
        "foreground", "blue", NULL); 
    

    这就是一个运用 GtkTextTag的例子,这个标记改变了文本的颜色。

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

    这个代码插入了一些文本,并运用了一个特殊的文本标记blue_fg


    Simple TextView
    Figure: Simple TextView

    行和栏(Lines and Columns)

    在接下来的示例中将要显示文本编辑光标目前处于的行数和列数。

    #include <gtk/gtk.h>
    
    update_statusbar(GtkTextBuffer *buffer,
        GtkStatusbar  *statusbar)
    {
      gchar *msg;
      gint row, col;
      GtkTextIter iter;
    
      gtk_statusbar_pop(statusbar, 0); 
    
      gtk_text_buffer_get_iter_at_mark(buffer,
          &iter, gtk_text_buffer_get_insert(buffer));
    
      row = gtk_text_iter_get_line(&iter);
      col = gtk_text_iter_get_line_offset(&iter);
    
      msg = g_strdup_printf("Col %d Ln %d", col+1, row+1);
    
      gtk_statusbar_push(statusbar, 0, msg);
    
      g_free(msg);
    }
    
    static void
    mark_set_callback(GtkTextBuffer *buffer,
        const GtkTextIter *new_location, GtkTextMark *mark,
        gpointer data)
    {
      update_statusbar(buffer, GTK_STATUSBAR(data));
    }
    
    
    int main( int argc, char *argv[])
    {
    
      GtkWidget *window;
      GtkWidget *vbox;
    
      GtkWidget *toolbar;
      GtkWidget *view;
      GtkWidget *statusbar;
      GtkToolItem *exit;
      GtkTextBuffer *buffer;
    
      gtk_init(&argc, &argv);
    
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 250, 200);
      gtk_window_set_title(GTK_WINDOW(window), "lines & cols");
    
      vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_add(GTK_CONTAINER(window), vbox);
    
      toolbar = gtk_toolbar_new();
      gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
    
      exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
      gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
    
      gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
    
      view = gtk_text_view_new();
      gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
      gtk_widget_grab_focus(view);
    
      buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
    
      statusbar = gtk_statusbar_new();
      gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
    
      g_signal_connect(G_OBJECT(exit), "clicked", 
            G_CALLBACK(gtk_main_quit), NULL);
    
      g_signal_connect(buffer, "changed",
            G_CALLBACK(update_statusbar), statusbar);
    
      g_signal_connect_object(buffer, "mark_set", 
            G_CALLBACK(mark_set_callback), statusbar, 0);
    
      g_signal_connect_swapped(G_OBJECT(window), "destroy",
            G_CALLBACK(gtk_main_quit), NULL);
    
      gtk_widget_show_all(window);
    
      update_statusbar(buffer, GTK_STATUSBAR (statusbar));
    
      gtk_main();
    
      return 0;
    }
    

    在上面的代码示例中,我们完成了在状态栏中显示当前文本编辑光标所处于的行和列数。

    view = gtk_text_view_new();
    

    生成一了 GtkTextView构件。

    g_signal_connect(buffer, "changed",
          G_CALLBACK(update_statusbar), statusbar);
    

    如果我们要更改文本,我们只需要调用回调函数 update_statusbar() 就可以了。

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

    当光标在移动的时候, mark_set 信号就被发射出去了。

    gtk_statusbar_pop(statusbar, 0); 
    

    这段代码功能是清除了先前的任何一些状态栏中的信息。

    gtk_text_buffer_get_iter_at_mark(buffer,
        &iter, gtk_text_buffer_get_insert(buffer));
    
    row = gtk_text_iter_get_line(&iter);
    col = gtk_text_iter_get_line_offset(&iter);
    

    显然上面的代码是在获取当前所处于的行号与列号。

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

    上面的代码准备好,状态栏中显示出来的行号与列号的内容。

    gtk_statusbar_push(statusbar, 0, msg);
    

    然后,我们就在状态栏上显示文本。


    Lines & Columns
    Figure: Lines & Columns

    监测& 突显(Search & Highlight)

    在接下来的例子中,我们将要在 GtkTextBuffer中做一些监测的工作。我们还将把一些文本的内容进行“突显”处理。

    #include <gtk/gtk.h>
    #include <gdk/gdkkeysyms.h>
    
    
    gboolean key_pressed(GtkWidget * window,
        GdkEventKey* event, GtkTextBuffer *buffer) {
    
      GtkTextIter start_sel, end_sel;
      GtkTextIter start_find, end_find;
      GtkTextIter start_match, end_match;
      gboolean selected;	
      gchar *text;		  
      
    
    
      if ((event->type == GDK_KEY_PRESS) && 
         (event->state & GDK_CONTROL_MASK)) {
    
        switch (event->keyval)
        {
          case GDK_m :
            selected = gtk_text_buffer_get_selection_bounds(buffer, 
                &start_sel, &end_sel);
          if (selected) {
            gtk_text_buffer_get_start_iter(buffer, &start_find);
            gtk_text_buffer_get_end_iter(buffer, &end_find);
    
            gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg", 
                &start_find, &end_find);  
            text = (char *) gtk_text_buffer_get_text(buffer, &start_sel,
                &end_sel, FALSE);
    
            while ( gtk_text_iter_forward_search(&start_find, text, 
                    GTK_TEXT_SEARCH_TEXT_ONLY | 
                    GTK_TEXT_SEARCH_VISIBLE_ONLY, 
                    &start_match, &end_match, NULL) ) {
    
              gtk_text_buffer_apply_tag_by_name(buffer, "gray_bg", 
                  &start_match, &end_match);
              int offset = gtk_text_iter_get_offset(&end_match);
              gtk_text_buffer_get_iter_at_offset(buffer, 
                  &start_find, offset);
            }
    
            g_free(text);
          }
    
          break;
    
          case GDK_r:
            gtk_text_buffer_get_start_iter(buffer, &start_find);
            gtk_text_buffer_get_end_iter(buffer, &end_find);
          
            gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg", 
                &start_find, &end_find);  
          break;
        }
      }
    
      return FALSE;
    }
    
    
    int main( int argc, char *argv[])
    {
    
      GtkWidget *window;
      GtkWidget *view;
      GtkWidget *vbox;
      
      GtkTextBuffer *buffer;
      GtkTextIter start, end;
      GtkTextIter iter;
    
      gtk_init(&argc, &argv);
    
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 250, 200);
      gtk_window_set_title(GTK_WINDOW(window), "Search & Highlight");
      gtk_container_set_border_width(GTK_CONTAINER(window), 5);
      GTK_WINDOW(window)->allow_shrink = TRUE;
    
      vbox = gtk_vbox_new(FALSE, 0);
      view = gtk_text_view_new();
      gtk_widget_add_events(view, GDK_BUTTON_PRESS_MASK);
      gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
    
      buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
      gtk_text_buffer_create_tag(buffer, "gray_bg", 
          "background", "gray", NULL); 
      gtk_container_add(GTK_CONTAINER(window), vbox);
    
      g_signal_connect_swapped(G_OBJECT(window), "destroy",
            G_CALLBACK(gtk_main_quit), G_OBJECT(window));
    
      g_signal_connect(G_OBJECT(window), "key-press-event",
            G_CALLBACK(key_pressed), buffer);
    
      gtk_widget_show_all(window);
    
      gtk_main();
    
      return 0;
    }
    

    在我们的示例中,我们用到了键盘的快捷键。Ctrl + M 是用来突显我们当前所选取的文本内容。Ctrl + R 则是用来取消上面的操作。

    gtk_text_buffer_create_tag(buffer, "gray_bg", 
        "background", "gray", NULL); 
    

    我们在例子中会再次用到 GtkTextTag 。这个标记可以使文本的背景反白。

    selected = gtk_text_buffer_get_selection_bounds(buffer, 
        &start_sel, &end_sel);
    

    这里我们得到我们选中的文本所具有的起始和终点位置。

    gtk_text_buffer_get_start_iter(buffer, &start_find);
    gtk_text_buffer_get_end_iter(buffer, &end_find);
    

    我们得到了文本缓冲区(text buffer)的起始和终点位置。

    gtk_text_buffer_remove_tag_by_name(buffer, "gray_bg", 
        &start_find, &end_find);  
    

    上面就是,把先前的标记去处。

    text = (char *) gtk_text_buffer_get_text(buffer, &start_sel,
        &end_sel, FALSE);
    

    接着我们得到了所选择的文本内容,我们将要进行监测。

    while ( gtk_text_iter_forward_search(&start_find, text, 
            GTK_TEXT_SEARCH_TEXT_ONLY | 
            GTK_TEXT_SEARCH_VISIBLE_ONLY, 
            &start_match, &end_match, NULL) ) {
    
      gtk_text_buffer_apply_tag_by_name(buffer, "gray_bg", 
          &start_match, &end_match);
      int offset = gtk_text_iter_get_offset(&end_match);
      gtk_text_buffer_get_iter_at_offset(buffer, 
          &start_find, offset);
    }
    

    这段代码将检测所有我们所选择的文本后的所发生的事件,一旦发现与我们定义的内容有匹配就应用我们设定好的标记。在匹配工作完成之后,单词的尾端将将被成下次监视操作的首端。


    Search & Highlight
    Figure: Search & Highlight
  • 相关阅读:
    github下载速度太慢解决办法
    python做简单的图像文字识别
    RuntimeError: The Session graph is empty. Add operations to the graph before calling run().解决方法
    module 'tensorflow' has no attribute 'ConfigProto'/'Session'解决方法
    list indices must be integers or slices, not tuple解决方案
    每周总结
    python从简介中获取行业分类
    python返回一个列表中出现次数最多的元素
    python提取一段文字的关键词
    PHP-Audit-Labs-Day13学习
  • 原文地址:https://www.cnblogs.com/xchsp/p/4322025.html
Copyright © 2011-2022 走看看