2014-03-29 112 views
2

當前嘗試創建基於GtkWidget的自定義小部件,將其標記爲可繪製並使用cairo繪製內容。對於上下文來說非常重要。事件回調未在自定義gtk3小部件中執行

當我嘗試處理事件(這樣我就可以實現縮放) - 尤其是滾動事件 - 只是不起作用,我不知道是爲什麼。

回調確實獲得焦點,在/集中了執行(好老的print語句證明),但我從來曾經得到由回調檢測(點擊按鈕的按鍵任何滾輪活動/釋放你也不工作)。

我試圖通過

  • 使用函數指針和分配使用的回調函數(我認爲這是應該做的事)
  • g_signal_connect (mywidget, "event",..)foo_newfoo_init
  • 掛鉤到事件信號

也沒有工作。


Foo INIT:

foo_init (Foo *self) 
{ 
    GtkWidget *widget = GTK_WIDGET (self); 
    gtk_widget_set_has_window (widget, FALSE); 

    self->priv = FOO_GET_PRIVATE (self); 

    gtk_widget_add_events (widget, GDK_ALL_EVENTS_MASK); 
    g_assert ((gtk_widget_get_events (widget) & GDK_SCROLL_MASK) != 0); //just fine 

    /* added some stuff I also tried but did not work */ 
    gtk_widget_set_sensitive (widget, TRUE); 
    gtk_widget_set_can_focus (widget, TRUE); 
    gtk_widget_grab_focus (widget); 
    ... 

我怎樣才能讓我的小部件的所有事件?


分配widget_class->key_press_event = my_handler_callback;實際上按預期工作,我得到我按下鍵,但非常相同的widget_class->button_press_event = my_handler_callback;widget_class->scroll_event = my_handler_callback;分配不工作!

widget_class->key_press_event = my_handler_callback; // works 
widget_class->key_release_event = my_handler_callback; // works 
widget_class->button_press_event = my_handler_callback; // NOT 
widget_class->button_release_event = my_handler_callback; // NOT 
widget_class->scroll_event = my_handler_callback; // NOT 

這讓我懷疑。

要接收該信號,關聯到插件的GdkWindow需要 啓用GDK_BUTTON_PRESS_MASK掩模。

是否有必要在gtk_widget_add_events「作品」之前實現小部件...?


更新:試過gtk_widget_show_all之後調用gtk_widget_add_events。不用找了。


更新:完全可編譯例子

#ifndef __FOO_H__ 
#define __FOO_H__ 

#include <gtk/gtk.h> 

G_BEGIN_DECLS 

#define FOO_TYPE   (foo_get_type()) 
#define FOO(obj)   (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOO_TYPE, Foo)) 
#define FOO_CONST(obj)  (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOO_TYPE, Foo const)) 
#define FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOO_TYPE, FooClass)) 
#define FOO_IS(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOO_TYPE)) 
#define FOO_IS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOO_TYPE)) 
#define FOO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOO_TYPE, FooClass)) 

typedef struct _Foo   Foo; 
typedef struct _FooClass FooClass; 
typedef struct _FooPrivate FooPrivate; 

struct _Foo 
{ 
    GtkWidget parent; 

    FooPrivate *priv; 
}; 

struct _FooClass 
{ 
    GtkWidgetClass parent_class; 
}; 

GType foo_get_type (void) G_GNUC_CONST; 
Foo *foo_new (void); 


G_END_DECLS 

#endif /* __FOO_H__ */ 

#include "foo.h" 


gboolean 
scroll_hook (GtkWidget *widget, GdkEventScroll *event) 
{ 
    g_print ("%p registered a scroll event\n"); 
    return TRUE; 
} 


#define FOO_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), FOO_TYPE, FooPrivate)) 

struct _FooPrivate 
{ 
    char to_silence_warning; 
}; 

G_DEFINE_TYPE (Foo, foo, GTK_TYPE_WIDGET) 

static void 
foo_finalize (GObject *object) 
{ 
    G_OBJECT_CLASS (foo_parent_class)->finalize (object); 
} 

static void 
foo_class_init (FooClass *klass) 
{ 
    GObjectClass *object_class = G_OBJECT_CLASS (klass); 
    object_class->finalize = foo_finalize; 

    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); 
    widget_class->scroll_event = scroll_hook; 
    g_type_class_add_private (object_class, sizeof (FooPrivate)); 
} 

static void 
foo_init (Foo *self) 
{ 
    self->priv = FOO_GET_PRIVATE (self); 
    gtk_widget_set_has_window(GTK_WIDGET(self), FALSE); 
} 

Foo * 
foo_new() 
{ 
    return g_object_new (FOO_TYPE, NULL); 
} 

#include <gtk/gtk.h> 
#include "foo.h" 
#include <stdlib.h> 

gboolean 
chicken_out (GtkWidget *widget, GdkEvent *event, gpointer user_data) 
{ 
    g_print ("bye"); 
    gtk_main_quit(); 
    return TRUE; 
} 

int 
main (int argc, char *argv[]) 
{ 
    GtkWidget *window; 
    Foo *my; 
    int i; 

    gtk_init (&argc, &argv); 

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    my = foo_new(); 

    gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (my)); 
    gtk_widget_show_all (window); 

    gtk_widget_add_events (GTK_WIDGET (my), GDK_ALL_EVENTS_MASK); 
    g_assert ((gtk_widget_get_events (GTK_WIDGET (my)) & GDK_SCROLL_MASK) != 0); 

    g_signal_connect (window, "delete-event", G_CALLBACK(chicken_out), NULL); 
    gtk_main(); 

    return EXIT_SUCCESS; 
} 

使用

gcc `pkg-config --cflags --libs gtk+-3.0` -I. ./foo.c ./foo_test.c -o foo.bin 

編譯(當然,所有文件都在你的CWD)

+0

作爲開始使用的主要來源,我起訴了@ptomato爲gtk3定製的小部件教程http://ptomato.name/advanced-gtk-techniques/html/custom-container.html – drahnr

回答

1

GtkWidget移動到GtkDrawingArea被要求,因爲沒有它就會崩潰。根本原因是沒有適當的realize默認回調 - 我沒有實現的->window小部件的私有變量沒有被填充。