gtk自定义小部件 - 在Glade中显示,但在构建时不显示

时间:2016-01-04 13:29:07

标签: c widget gtk glade

我在C中为GTK + 3制作了一个简单的自定义小部件,名为AwLed,并将其添加到自定义Glade目录中。它在Glade内部或使用aw_led_new()函数创建时可以正常工作。 但是,当我创建一个加载Glade文件并显示其小部件的简单程序(在主窗口小部件上调用show_all())时,自定义小部件不会显示自己。 我添加了一些printf-fflushs来调试,发现函数Realize,Allocate甚至都没有被调用。看起来整个共享库似乎没有被加载。

现在,除了用GtkBuilder加载小部件之外,Glade还做了什么?为什么忽略这些小部件?我想写一些样板来实现GtkBuildable接口吗?

非常感谢任何帮助。

awled.c

#include <gtk/gtk.h>
#include "awled.h"

enum {
  PROP_0,
  PROP_ACTIVE,
};

static void      aw_led_set_property          (GObject        *object,
                                               guint           prop_id,
                                               const GValue   *value,
                                               GParamSpec     *pspec);
static void      aw_led_get_property          (GObject        *object,
                                               guint           prop_id,
                                               GValue         *value,
                                               GParamSpec     *pspec);
static void      aw_led_realize               (GtkWidget      *widget);
static void      aw_led_unrealize             (GtkWidget      *widget);
static void      aw_led_map                   (GtkWidget      *widget);
static void      aw_led_unmap                 (GtkWidget      *widget);
static void      aw_led_size_allocate         (GtkWidget      *widget,
                                               GtkAllocation  *allocation);
static void      aw_led_get_preferred_width (GtkWidget *widget,
                                              gint      *minimal_width,
                                              gint      *natural_width);
static void      aw_led_get_preferred_height (GtkWidget *widget,
                                              gint      *minimal_height,
                                              gint      *natural_height);
static gboolean  aw_led_draw                (GtkWidget      *widget,
                                             cairo_t *cr);

G_DEFINE_TYPE (AwLed, aw_led, GTK_TYPE_WIDGET)

#define parent_class aw_led_parent_class

static void
aw_led_class_init (AwLedClass *klass)
{
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  object_class->set_property         = aw_led_set_property;
  object_class->get_property         = aw_led_get_property;

  widget_class->realize              = aw_led_realize;
  widget_class->unrealize            = aw_led_unrealize;
  widget_class->map                  = aw_led_map;
  widget_class->unmap                = aw_led_unmap;
  widget_class->size_allocate        = aw_led_size_allocate;
  widget_class->get_preferred_width  = aw_led_get_preferred_width;
  widget_class->get_preferred_height = aw_led_get_preferred_height;
  widget_class->draw                 = aw_led_draw;

  GParamSpec* param_spec;
  param_spec = g_param_spec_boolean ("active", "Active", "LED State",
                                     FALSE, G_PARAM_READWRITE);
  g_object_class_install_property (object_class, PROP_ACTIVE, param_spec);
}


static void
aw_led_init (AwLed *led)
{
  gtk_widget_set_has_window (GTK_WIDGET (led), FALSE);

  led->state           = FALSE;
  led->color_on.red    = 0.0;
  led->color_on.green  = 0.6;
  led->color_on.blue   = 0.0;
  led->color_on.alpha  = 1.0;
  led->color_off.red   = 0.6;
  led->color_off.green = 0.0;
  led->color_off.blue  = 0.0;
  led->color_off.alpha = 1.0;
  /*priv->backing_store       = NULL; //what?? needed?
  priv->backing_store_valid = FALSE;
  priv->pos_redraw_idle_id   = 0;*/ 
}


static void
aw_led_set_property (GObject      *object,
                     guint         prop_id,
                     const GValue *value,
                     GParamSpec   *pspec)
{
  AwLed *led = AW_LED (object);

  switch (prop_id)
  {
    case PROP_ACTIVE:
      led->state = g_value_get_boolean (value);
      gtk_widget_queue_resize (GTK_WIDGET (led));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}


static void
aw_led_get_property (GObject    *object,
                     guint       prop_id,
                     GValue     *value,
                     GParamSpec *pspec)
{
 AwLed *led = AW_LED (object);

  switch (prop_id)
    {
    case PROP_ACTIVE:
      g_value_set_boolean (value, led->state);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}


GtkWidget *
aw_led_new ()
{
  return g_object_new (AW_TYPE_LED,
                       "active", FALSE,
                       NULL);
}


static void
aw_led_realize (GtkWidget *widget)
{
  AwLed         *led = AW_LED (widget);
  GtkAllocation allocation;
  GdkWindowAttr attributes;
  gint          attributes_mask;

  GTK_WIDGET_CLASS (aw_led_parent_class)->realize (widget);

  gtk_widget_get_allocation (widget, &allocation);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x           = allocation.x;
  attributes.y           = allocation.y;
  attributes.width       = allocation.width;
  attributes.height      = allocation.height;
  attributes.wclass      = GDK_INPUT_ONLY;
  attributes.event_mask  = (gtk_widget_get_events (widget) | 
                            GDK_EXPOSURE_MASK);

  attributes_mask = GDK_WA_X | GDK_WA_Y;

  led->input_window = gdk_window_new (gtk_widget_get_window (widget),
                                       &attributes, attributes_mask);
  gdk_window_set_user_data (led->input_window, led);

}


static void
aw_led_unrealize (GtkWidget *widget)
{
  AwLed *led = AW_LED (widget);

  if (led->input_window) {
      gdk_window_destroy (led->input_window);
      led->input_window = NULL;
  }

  GTK_WIDGET_CLASS (aw_led_parent_class)->unrealize (widget);
}


static void
aw_led_map (GtkWidget *widget)
{
  AwLed *led = AW_LED (widget);

  GTK_WIDGET_CLASS (parent_class)->map (widget);

  if (led->input_window)
    gdk_window_show (led->input_window);

}


static void
aw_led_unmap (GtkWidget *widget)
{
  AwLed *led = AW_LED (widget);
  if (led->input_window)
    gdk_window_hide (led->input_window);

  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}


static void
aw_led_size_allocate (GtkWidget     *widget,
                      GtkAllocation *allocation)
{
  AwLed *led = AW_LED (widget);

  gtk_widget_set_allocation (widget, allocation);

  if (gtk_widget_get_realized (widget)) {
      gdk_window_move_resize (led->input_window,
                              allocation->x, allocation->y,
                              allocation->width, allocation->height);
  }
}


static void
aw_led_get_preferred_width (GtkWidget *widget,
                            gint      *minimal_width,
                            gint      *natural_width)
{
  *minimal_width = 20;
  *natural_width = 35;
}


static void
aw_led_get_preferred_height (GtkWidget *widget,
                             gint      *minimal_height,
                             gint      *natural_height)
{
  *minimal_height = 20;
  *natural_height = 35;
}


static gboolean
aw_led_draw (GtkWidget *widget,
             cairo_t   *cr)
{
  gint width, height;
  AwLed* led = AW_LED(widget);

  width = gtk_widget_get_allocated_width (widget);
  height = gtk_widget_get_allocated_height (widget);

  GdkRGBA color = (led->state) ? led->color_on : led->color_off;

  cairo_arc (cr, width / 2.0, height / 2.0,
             MIN (width, height) / 2.0, 0, 2 * G_PI);

  gdk_cairo_set_source_rgba (cr, &color);

  cairo_fill (cr);

  return TRUE;
}

awled.h

#ifndef __AW_LED_H__
#define __AW_LED_H__

#include <gtk/gtk.h>

G_BEGIN_DECLS

#define AW_TYPE_LED             (aw_led_get_type ())
#define AW_LED(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), AW_TYPE_LED, AwLed))
#define AW_LED_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), AW_TYPE_LED, AwLedClass))
#define AW_IS_LED(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AW_TYPE_LED))
#define AW_IS_LED_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), AW_TYPE_LED))
#define AW_LED_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), AW_TYPE_LED, AwLedClass))

typedef struct _AwLed      AwLed;
typedef struct _AwLedClass AwLedClass;

typedef enum {
    OVAL,
    RECTANGULAR
} AwLedShape;

struct _AwLed {
    GtkWidget  parent_instance;
    //public members
    //@TODO Move these to .C file (AwLedPrivate structure)
    GdkRGBA    color_on;
    GdkRGBA    color_off;
    AwLedShape shape;
    gboolean   state;
    GdkWindow  *input_window;
};

struct _AwLedClass {
    GtkWidgetClass parent_class;
};

GType aw_led_get_type (void) G_GNUC_CONST;
GtkWidget* aw_led_new ();
gboolean aw_led_get_state (AwLed* led);
void aw_led_set_state (AwLed* led, gboolean state);

G_END_DECLS

#endif /* __AW_LED_H__ */

test_builder.c

#include <gtk/gtk.h>
#include <awled.h>

int main(int argc, char* argv[]) {
    GtkBuilder* builder;
    GtkWidget *window, *led, *led2, *box;

    gtk_init(&argc, &argv);

    builder = gtk_builder_new();
    gtk_builder_add_from_file(builder, "interface.ui", NULL);

    window = (GtkWidget*) gtk_builder_get_object(builder, "window1");
    led = (GtkWidget*) gtk_builder_get_object(builder, "led1");
    box = (GtkWidget*) gtk_builder_get_object(builder, "box1");

    //weird... if I create only one this way, all of them show themselves!
    //led2 = aw_led_new();
    //gtk_box_pack_end(GTK_BOX(box), led2, 0, 0, 0);

    gtk_widget_show_all(window);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);    

    gtk_main();
}

0 个答案:

没有答案