いくつか質問があります。現時点では、gtkbin を使用して gtk でカスタム ウィジェットを作成しようとしているので、gtkbin をサブクラス化できるかどうか、およびその方法を知りたいです...助けてくれてありがとう。
1 に答える
私はついにこれを自分で実装することができました。導出したい方はこちらgtkbin widget
。
1) ウィジェットの階層を理解することが重要です。
>Hierarchy of widgets:
GtkWidget <- GtkContainer <- GtkBin
たとえば、の contumize 関数を書き直さない場合Gtkcontainer
、から直接派生するカスタム ウィジェット クラスは、 のデフォルトの描画関数を使用します。GtkBin
GtkWidgetClass->draw
GtkBin
GtkWidgetClass
2) gtkbin に関する情報:
のソース コードをダウンロードしてgtk
開きgtkwidget.c
、このすべてのファイルの関数をgtkcontainer.c
確認gtkwindow.c
します。class_init
でGtkWidgetClass
:
1)ウィジェットクラスが「描画」機能を実装していないことを確認する必要があります。
GtkWidgetClass->draw
GtkWidgetClass->get_preferred_width
2) andの実装はGtkWidgetClass_preferred_width_height
常に正しくない "0" を返すことを確認する必要があります。GtkWidgetClass->size_allocate
また、派生させたいウィジェットのサイズのみを割り当て、カスタマイズ ウィジェットの子をカウントしないこともわかります。
これら 4 つの関数を適切に動作させるには、すべてを書き直す必要があります。
はからGtkWindow
直接派生するウィジェットであるため、ファイル内GtkBin
の対応する実装をGtkWindow.c
表示していくつかの変更を加えることで、関数を実装できます。
これが私の実装です:
widget_class->get_preferred_width = item_list_get_preferred_width;
widget_class->get_preferred_height = item_list_get_preferred_height;
widget_class->draw = dsn_itemlist_draw;
widget_class->size_allocate = item_list_size_allocate;
void item_list_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkAllocation child_allocation;
GtkWidget *child;
guint border_width;
gtk_widget_set_allocation (widget, allocation);
child = gtk_bin_get_child (GTK_BIN(widget));
if (child && gtk_widget_get_visible (child))
{
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
child_allocation.x = border_width;
child_allocation.y = border_width;
child_allocation.width = MAX (1, allocation->width - border_width * 2);
child_allocation.height = MAX (1, allocation->height - border_width * 2);
gtk_widget_size_allocate (child, &child_allocation);
}
}
gboolean dsn_itemlist_draw( GtkWidget *widget, cairo_t *cr)
{
GtkWidget *child;
GtkBin *bin = GTK_BIN(widget);
GtkContainer *container = GTK_CONTAINER(widget);
child = gtk_bin_get_child(bin);
gtk_container_propagate_draw(container, child, cr);
printf("bonnnnnnn\n");
return TRUE;
}
void item_list_get_preferred_width(GtkWidget *widget,
gint *minimum_size,
gint *natural_size)
{
//GtkWindow *window;
GtkWidget *child;
guint border_width;
//window = GTK_WINDOW (widget);
child = gtk_bin_get_child (GTK_BIN (widget)/*(window)*/);
border_width = 0;//gtk_container_get_border_width (GTK_CONTAINER (window));
*minimum_size = border_width * 2;
*natural_size = border_width * 2;
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
*minimum_size += child_min;
*natural_size += child_nat;
}
}
void item_list_get_preferred_height(GtkWidget *widget,
gint *minimum_size,
gint *natural_size)
{
//GtkWindow *window;
GtkWidget *child;
guint border_width;
//window = GTK_WINDOW (widget);
child = gtk_bin_get_child (GTK_BIN (widget)/*(window)*/);
border_width = 0;//gtk_container_get_border_width (GTK_CONTAINER (window));
*minimum_size = border_width * 2;
*natural_size = border_width * 2;
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
*minimum_size += child_min;
*natural_size += child_nat;
}
}
Note:
このinit
関数では、ウィンドウ ( ) を所有しgtk
てwidget
いないgdkwindow
が、呼び出して親ウィジェットからウィンドウを継承していることを伝える必要があります。
gtk_widget_set_has_window (GTK_WIDGET (this_instance), FALSE);
結論は…