0

我有一些问题,此时我尝试使用 gtkbin 在 gtk 中制作一个自定义小部件,所以我想知道是否可以将 gtkbin 子类化以及如何做到这一点......感谢您的帮助。

4

1 回答 1

0

我终于设法自己实现了这一点。以下是想要获得的人的方法gtkbin widget

1) 了解小部件的层次结构很重要。

>Hierarchy of widgets:  
GtkWidget <- GtkContainer <- GtkBin 

例如,如果Gtkcontainer并且GtkBin不重写 contumize 函数直接派生自的自定义小部件类将使用.GtkWidgetClass->drawGtkBinGtkWidgetClass

2)关于gtkbin的信息:

下载源代码gtk并打开gtkwidget.c,查看所有这些文件中的gtkcontainer.c函数。gtkwindow.cclass_init

GtkWidgetClass

  • 1)我们必须看到,小部件类没有实现“绘制”功能:

     GtkWidgetClass->draw
    
  • 2)我们必须看到,GtkWidgetClass->get_preferred_widthand的实现GtkWidgetClass_preferred_width_height 总是返回“0”,这是不正确的。

  • 我们还看到,GtkWidgetClass->size_allocate它只为您想要派生的小部件分配大小,它不计算自定义小部件的子级。

您必须将这四个函数重写为一切才能正常工作。

由于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);

就这样结束...

于 2013-01-25T12:54:21.590 回答