window 最小化时如何自动将滚动条滚动到底部
how to auto scroll the scrollbar to bottom when window get minimized
我正在做一个必须在 GTK-2.0
中的项目,我面临的问题是如果 window 在最大化后最小化,滚动条不再回到底部.
下面是可以查看和测试的部分代码:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextBuffer *buffer;
GtkTextMark *mark;
GtkTextIter iter, start, end;
const gchar *text;
/// ***
buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
gtk_text_buffer_get_bounds ( buffer, &start, &end );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
/// ***
mark = gtk_text_buffer_create_mark ( buffer, NULL, &iter, FALSE );
gtk_text_view_scroll_mark_onscreen ( GTK_TEXT_VIEW ( widg->textview ), mark );
gtk_text_buffer_delete_mark ( buffer, mark );
}
我的猜测是我以某种方式混淆了 chatMSG()
函数中的内容。
如何在用户最小化 Window 后将滚动条保持在底部?
我还尝试了以下方法:
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
gtk_adjustment_set_value ( adj, adj->upper );
但它也不起作用。
经过大量搜索并尝试了不同的方法但没有帮助,我搜索了 Gnome-Team 的帮助并设法修复了它。
我决定在这里分享这两个,因为它对以后的其他人也有帮助。
这是一个工作示例:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data );
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
double from_bottom = 0.0;
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
g_signal_connect ( scrolled_win, "size-allocate", ( GCallback ) scroll_bottom_gravity, &from_bottom );
g_signal_connect ( adjustment, "value-changed", ( GCallback ) scroll_value_changed, &from_bottom );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextMark *mark;
GtkTextIter iter;
/// ***
GtkTextBuffer *buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
const gchar *text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen ( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
}
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data )
{
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_window ) );
double *from_bottom = user_data;
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
gtk_adjustment_set_value ( adjustment, upper - page_size - *from_bottom );
}
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data )
{
double *from_bottom = user_data;
double value = gtk_adjustment_get_value ( adjustment );
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
*from_bottom = upper - page_size - value;
}
我正在做一个必须在 GTK-2.0
中的项目,我面临的问题是如果 window 在最大化后最小化,滚动条不再回到底部.
下面是可以查看和测试的部分代码:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextBuffer *buffer;
GtkTextMark *mark;
GtkTextIter iter, start, end;
const gchar *text;
/// ***
buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
gtk_text_buffer_get_bounds ( buffer, &start, &end );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
/// ***
mark = gtk_text_buffer_create_mark ( buffer, NULL, &iter, FALSE );
gtk_text_view_scroll_mark_onscreen ( GTK_TEXT_VIEW ( widg->textview ), mark );
gtk_text_buffer_delete_mark ( buffer, mark );
}
我的猜测是我以某种方式混淆了 chatMSG()
函数中的内容。
如何在用户最小化 Window 后将滚动条保持在底部?
我还尝试了以下方法:
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
gtk_adjustment_set_value ( adj, adj->upper );
但它也不起作用。
经过大量搜索并尝试了不同的方法但没有帮助,我搜索了 Gnome-Team 的帮助并设法修复了它。
我决定在这里分享这两个,因为它对以后的其他人也有帮助。 这是一个工作示例:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data );
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
double from_bottom = 0.0;
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
g_signal_connect ( scrolled_win, "size-allocate", ( GCallback ) scroll_bottom_gravity, &from_bottom );
g_signal_connect ( adjustment, "value-changed", ( GCallback ) scroll_value_changed, &from_bottom );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextMark *mark;
GtkTextIter iter;
/// ***
GtkTextBuffer *buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
const gchar *text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen ( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
}
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data )
{
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_window ) );
double *from_bottom = user_data;
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
gtk_adjustment_set_value ( adjustment, upper - page_size - *from_bottom );
}
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data )
{
double *from_bottom = user_data;
double value = gtk_adjustment_get_value ( adjustment );
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
*from_bottom = upper - page_size - value;
}