GTK中在scrolled_window區域用滑輪操作獨立scrollbar的方法

這是我在實習期間改的一個bug,問題是在這樣:

在GTK中 scrolled_window(滾動窗口)是自帶 scrollbar(滾動條)的,但由於項目組代碼架構的問題,系統中的 scrolled_window 自帶的 scrollbar 全部被隱藏了,而通過獨立於滾動窗口之外的 scrollbar 來對 scrolled_window 進行操作。因此造成一個問題,鼠標只有將光標放在 scrollbar 所在區域時,鼠標滑輪的滾動才能起作用,而超出這個範圍,如光標在scrolled_window 的窗口區域時,就不起作用。而正常情況下我們的鼠標不可能一直放在滾動條區域,因此需要改。

在此期間,我想了三種方法:

1、將獨立的 scrollbar 綁定 scrolled_window。經測試,這種方法不可行,當將 scrolled_window 自帶的滾動條隱藏後,獨立的 scrollbar 就不起作用了,只有在不隱藏的情況下,才起作用。

2、讓整個窗口的焦點聚焦於滾動條上。經測試,雖然可以聚焦,缺陷很大,效果不好,而且對於整個系統來說,改動很大,不現實。

3、讓獨立scrollbar 和 scrolled_window所在的總窗口捕捉鼠標滑輪的信號,並通過回調函數來調整scrollbar 的adjustment從而達到控制滾動條移動的目的,經測試效果很好。

以下代碼是第三種方案的測試代碼,其中在註釋部分包含了第二種方案的實現代碼:

#include <gtk/gtk.h>

GtkObject *adj1;
int a=1;

void destroy( GtkWidget *widget, gpointer   data )
{
    gtk_main_quit ();
}

void draw_scroll(GtkWidget *widget, GdkEventScroll *event)
{
    if(event->direction == GDK_SCROLL_UP)    // 滑輪上滑
	{
            g_print("1");                    // 在終端打印1
		gtk_adjustment_set_value(GTK_ADJUSTMENT (adj1),--a);  // 回調函數調整 adj1
	}
    if(event->direction == GDK_SCROLL_DOWN)  // 滑輪下滑
	{
          g_print("2");
	    gtk_adjustment_set_value(GTK_ADJUSTMENT (adj1),++a);
	}
}

int main(int argc,char *argv[])
{
    GtkWidget *window;
    GtkWidget *vbox,*hbox;
    GtkWidget *button;
    GtkWidget *table;
    GtkWidget *scrolled_window;
    GtkWidget *scrollbar;

    char buffer[32];
    int i, j;

    gtk_init(&argc,&argv);

    /*創建window*/
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),"scoll_test");
    gtk_window_set_default_size(GTK_WINDOW(window),300,300);
    //g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL);
    g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window),0);

    /*
    vbox = gtk_vbox_new(FALSE,0);
    gtk_container_add(GTK_CONTAINER(window),vbox);
    gtk_widget_show (vbox);
    */

    /*創建hbox*/
    hbox = gtk_hbox_new(FALSE,0);
    gtk_container_add(GTK_CONTAINER(window),hbox);
    gtk_widget_show (hbox);

    /*創建adjustment*/
    adj1 = gtk_adjustment_new (0, 0, 50, 5, 10,2);

    /*創建scrolled_window*/
    scrolled_window = gtk_scrolled_window_new (NULL,NULL);
    gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER,GTK_POLICY_NEVER);
    // GTK_POLICY_AUTOMATIC,GTK_POLICY_ALWAYS,這三個參數用來表示scrolled_window自帶的滾動條的狀態
    // GTK_POLICY_NEVER表示隱藏,不出現
    gtk_box_pack_start (GTK_BOX (hbox),scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show (scrolled_window);

    /*創建table*/
    table = gtk_table_new (10, 10, FALSE);
    gtk_table_set_row_spacings (GTK_TABLE (table), 10);
    gtk_table_set_col_spacings (GTK_TABLE (table), 10);
    gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
    gtk_widget_show (table);
    /*在table中,循環創建table*/
    for (i = 0; i < 10; i++)
       for (j = 0; j < 10; j++) {
          sprintf (buffer, "button (%d,%d)\n", i, j);
          button = gtk_toggle_button_new_with_label (buffer);
          gtk_table_attach_defaults (GTK_TABLE (table), button, i, i+1, j, j+1);
          gtk_widget_show (button);
       }

    button = gtk_button_new_with_label ("close");
    g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy), window);
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
    gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);//GTK_DIALOG (window)->action_area,放在hbox中
    gtk_widget_grab_default (button);
    gtk_widget_show (button);

    /*創建scrollbar,縱向的*/
    scrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (adj1));   // 可以通過調整adj1,來調整 scrollbar
    //scrollbar = gtk_vscrollbar_new (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW(scrolled_window)));
    gtk_box_pack_start (GTK_BOX (hbox), scrollbar, TRUE, TRUE, 0);//GTK_DIALOG(window)->hbox,scrollbar放在hbox中
    gtk_widget_show (scrollbar);
    //gtk_widget_show_all(window);

    /*
    用於定位窗口焦點在scrollbar上
    gtk_window_set_focus(GTK_WINDOW(window),scrollbar);
    g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
    */

    /* window 捕捉鼠標滾輪的信號,並調用回調函數 draw_scroll*/
    g_signal_connect(G_OBJECT (window), "scroll_event",G_CALLBACK(draw_scroll), NULL);

    /*窗口變化*/
    //g_signal_connect(G_OBJECT (scrollbar) , "configure_event",G_CALLBACK(frame_callback), NULL);

    //g_signal_connect_after(G_OBJECT (window), "scroll_event",G_CALLBACK(draw_scroll), NULL);

    gtk_widget_show (window);
    gtk_main();
    return 0;
}

結果如下:


/*點滴積累,我的一小步O(∩_∩)O~*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章