いくつか質問があります。現時点では、gtkbin を使用して gtk でカスタム ウィジェットを作成しようとしているので、gtkbin をサブクラス化できるかどうか、およびその方法を知りたいです...助けてくれてありがとう。
1 に答える
私はついにこれを自分で実装することができました。導出したい方はこちらgtkbin widget。
1) ウィジェットの階層を理解することが重要です。
>Hierarchy of widgets:  
GtkWidget <- GtkContainer <- GtkBin 
たとえば、の contumize 関数を書き直さない場合Gtkcontainer、から直接派生するカスタム ウィジェット クラスは、 のデフォルトの描画関数を使用します。GtkBinGtkWidgetClass->drawGtkBinGtkWidgetClass
2) gtkbin に関する情報:
のソース コードをダウンロードしてgtk開きgtkwidget.c、このすべてのファイルの関数をgtkcontainer.c確認gtkwindow.cします。class_init
でGtkWidgetClass:
- 1)ウィジェットクラスが「描画」機能を実装していないことを確認する必要があります。 - GtkWidgetClass->draw
- GtkWidgetClass->get_preferred_width2) 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);
結論は…