关于C#:使用GtkBox中package的GtkTextView自动滚动GtkScrolledWindow

Auto scrolling GtkScrolledWindow with GtkTextView wrapped in GtkBox

当我在GtkScrolledWindow中具有GtkTextView时,当用户在小部件底部添加新行时,它将自动滚动。当我将GtkTextView放在GtkBox中,然后在GtkScrolledWindow中时,我无法使用。我需要在GtkTextView和滚动条之间放置一个框,如果不把整个东西放在另一个框中,我将无法做到这一点。在GtkScrolledWindow中使用GtkBox时,有什么方法可以保留自动滚动行为?

有说明我问题的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <gtk/gtk.h>

int main(int argc, char *argv[]) {
    GtkWidget *window;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window),
        gdk_screen_width()*0.5, gdk_screen_height()*0.5);

    GtkWidget *main = gtk_box_new(0, 0);
    gtk_container_add(GTK_CONTAINER(window), main);
    /*/////////////////////////////////////////////////*/

    /* IMPORTANT PART */

    /* FIRST CASE (this one works correctly) */
    GtkWidget *scrolled_window_first = gtk_scrolled_window_new(NULL, NULL);
    GtkWidget *text_view_first = gtk_text_view_new();

    gtk_container_add(GTK_CONTAINER(scrolled_window_first), text_view_first);
    gtk_box_pack_start(GTK_BOX(main), scrolled_window_first, 1, 1, 0);

    /* SECOND CASE (there is no auto scroll which I need) */
    GtkWidget *scrolled_window_second = gtk_scrolled_window_new(NULL, NULL);
    GtkWidget *text_view_second = gtk_text_view_new();
    GtkWidget *box_from_second_example = gtk_box_new(0, 0);
    GtkWidget *example_box_before_scroller = gtk_box_new(0,0);

    GtkWidget *example_label = gtk_label_new("I need this box badly!");

    gtk_box_pack_start(GTK_BOX(box_from_second_example), text_view_second, 1, 1, 0);
    gtk_container_add(GTK_CONTAINER(scrolled_window_second), box_from_second_example);
    gtk_container_add(GTK_CONTAINER(box_from_second_example), example_box_before_scroller);
    gtk_box_pack_start(GTK_BOX(main), scrolled_window_second, 1, 1, 0);

    /* END IMPORTANT PART */

    /*/////////////////////////////////////////////////*/
    gtk_container_add(GTK_CONTAINER(example_box_before_scroller), example_label);
    g_signal_connect(GTK_WINDOW(window),"destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(window);
    gtk_main ();

    return 0;
}

问题是GtkTextView实现了GtkScrollable,但GtkBox没有实现。这不是一个小问题:如果要使用GtkBox方式,则应将其放入GtkViewport并添加可滚动性内容...相当一些代码,需要深入了解整个内容的滚动方式。 >

无论如何,如果您足够懒惰,您可能还会注意到GtkTextViewGtkContainer。换句话说,您可以在GtkTextView周围添加小部件,而无需混淆GtkBox。并非完全符合您的要求,但可能足以满足您的目的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <gtk/gtk.h>                                                    

gint main(gint argc, gchar **argv)                                      
{                                                                      
    GtkWidget *window, *scrolled_window, *text_view, *label;            

    gtk_init(&argc, &argv);                                            

    text_view = gtk_text_view_new();                                    
    gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)),
                            "1\
\
\
2\
\
\
3\
\
\
4\
\
\
5\
\
\
6\
\
\
7\
\
\
8"
, -1);
    /* Use this to set the size you want to reserve on the right */    
    gtk_text_view_set_border_window_size(GTK_TEXT_VIEW(text_view),      
                                         GTK_TEXT_WINDOW_RIGHT,        
                                         130);                          
    /* Add whatever you want instead of a GtkLabel */                  
    gtk_text_view_add_child_in_window(GTK_TEXT_VIEW(text_view),        
                                      gtk_label_new("You badly need this"),
                                      GTK_TEXT_WINDOW_RIGHT,            
                                      0, 0);                            

    scrolled_window = gtk_scrolled_window_new(NULL, NULL);              
    gtk_container_add(GTK_CONTAINER(scrolled_window), text_view);      

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);                      
    gtk_window_set_default_size(GTK_WINDOW(window), 320, 240);                                                                                                        
    gtk_container_add(GTK_CONTAINER(window), scrolled_window);          
    gtk_widget_show_all(window);                                        

    gtk_main ();                                                        

    return 0;                                                          
}


您是否尝试修改textview默认创建的GtkAdjustment(GtkScrolledWindow实现了GtkScrollable afaik)。

1
GtkAdjustment *     gtk_scrollable_get_hadjustment      (GtkScrollable *scrollable);

我认为最好的方法是检测对GtkTextBuffer的插入(通过

获取视图缓冲区

1
GtkTextBuffer *     gtk_text_view_get_buffer            (GtkTextView *text_view);

并将一个回调(测试\
)挂接到其insert-text g_signal并使用

1
2
void             gtk_adjustment_set_value            (GtkAdjustment *adjustment,
                                                      gdouble value);

修改滚动高度。

请注意,此方法未经测试,可能即将来临。