[Glade-users] How to get to the label field of a button



This is a multi-part message in MIME format.
--------------EA32D12CCED06FA4A95CAC88
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Jered Bolton wrote:

Ed Winchester wrote:

Hi again, all,

I've been trying to get my glade-generated app to compile.  I know, from
something I read, but can't remember where, that Glade itself will not
generate code to change the label for a button.  I remember seeing
somewhere an example, but can't for the life of me remember where I read
that.

What I tried last was:
    gtk_label_set_text (GTK_LABEL(button->label),"New button label");

I got the error:
    structure has no member named `label'

Please help.

No idea how this works (well I kind of have but....), but try the
following:

   GtkWidget        *label;
    GList            *glist;

  widget = lookup_widget(window_widget_is_on, "slider_button"); /* may not
need this as long as you have a pointer to the widget you'll be okay*/

    glist = gtk_container_children( GTK_CONTAINER(widget) );
   label = GTK_WIDGET( glist->data );
    gtk_label_set( GTK_LABEL(label), "FRED");

I found this after trawling through stacks of stuff on the web, all seemed
a bit mysterious to me, as I too had similar problems in setting/changing
the label for the button.
I found the answer in a posting from 1998 from someone complaining about
the lack of useful documentation....
yet I still find myself wandering how the hell did they know to A) use a
GList, and B) that is has a member called data.  Half the time the
documentation states that the structure should only be accessed using the
functions given...  which in turn can only be used with this "extra"
knowledge.
I realise this is more of a GTK problem than glade specific, but I'm sure
there are many other relative "newbies" like myself who feel slightly lost
at times.

Actually Gtk+ is reasonably well documented (GNOME is sometimes a
different matter).  In this specific case the documentation is clear. 
(All quotes are direct cut/paste from
http://developer.gnome.org/doc/API/ )

Reading from the Gtk+ reference for GtkButton :

Object Hierarchy
   GtkObject
    +----GtkWidget
          +----GtkContainer
                +----GtkBin
                      +----GtkButton

Args
   "label"                gchar*               : Read / Write
   "relief"               GtkReliefStyle       : Read / Write

Note that a GtkButton is a GtkBin, so it is a GtkContainer that supports
a single child widget (in this specific/normal case a GtkLabel).

Also note that the "label" Arg is available, which provides an immediate
answer to your question, specifically :

                gtk_object_set(GTK_OBJECT(button), "label", "goodbye", NULL);

You can know this is a gtk_object_* function because you can look in
GGAD, written by Havoc Pennington, and published under an Open licence
(ie, you can dl/read it off the web).  Dead tree version available from
New Riders IIRC.

If, like me, you have merely forgotten the precise syntax, you just need
to look at the reference docs for GtkObject, specifically:

++++++++
gtk_object_set ()

 void        gtk_object_set                  (GtkObject *object,
                                              const gchar
*first_arg_name,
                                              ...);

This function sets multiple arguments of an object.

It takes an object, then a list of name/value pairs in a list, followed
by NULL.

 void set_box_properties(GtkBox* box)
 {
   gtk_object_set(GTK_OBJECT(box), "homogeneous", TRUE,
                                   "spacing", 8,
                                   NULL);
 }
             object :
                     the object whose arguments should be set.
     first_arg_name :
                     the name of the first argument to set.
                ... :
                     the value of the first argument, followed
optionally by more name/value pairs, followed by
                     NULL. 
++++++++

However there are at least two other ways of achiving the same end.  As
the GtkButton appears to it's child as a GtkBin (see inheritance list),
it would make sense that facilities for manipulating it's child would be
associated with GtkBin, not GtkButton.  So if we take a look at GtkBin
we see:

GtkBin -- a container with just one child.
....
Details

struct GtkBin

 struct GtkBin;

The GtkBin struct contains the following fields. (These fields should be
considered read-only. They should
never be set by an application.) 

 GtkWidget *child;            the child widget.

Which immediately suggests the following code :

        gtk_label_set_text(GTK_LABEL(GTK_BIN(button)->child), "hello");

(In actual fact this was my immediate response to the question, it's
just the GtkArg approach is most immediately obvious from the GtkButton
docs)

Of course there is also the child manipulation functions provided by
GtkBin's parent class GtkContainer:

GList*      gtk_container_children          (GtkContainer *container);

I am a little surprised to find this function undocumented, although it
is listed with it's full signature in the GtkContainer reference, and is
sufficiently obvious to hardly require documenting.  I guessed
(correctly) from the signature that it returns a linked list of children
widgets given a container widget.

Taking a look at the GList reference (which is complete except for
complexity info, that is rare in any documentation, but would be useful
in the glib docs sometimes) :

+++++
Description

The GList structure and its associated functions provide a standard
doubly-linked list data structure.

Each element in the list contains a piece of data, together with
pointers which link to the previous and next
elements in the list. <SNIP: lots of useful info on GList's>
Details

struct GList

 struct GList
 {
   gpointer data;
   GList *next;
   GList *prev;
 };

The GList struct is used for each element in a doubly-linked list. The
data field holds the element's data, which
can be a pointer to any kind of data, or any integer value using the
Type Conversion Macros. The next and prev
pointers are the links to the next and previous elements in the list.

+++++

Which makes the following code snippet easy enough to generate:

     GList *child = gtk_container_children(GTK_CONTAINER(button));
     gtk_label_set_text(GTK_LABEL(child->data), "clicked");

I've attached a small libglade based demo that shows the above in
action. (Total project 115 lines in 3 files in 2.6k)

Andrae Muys
--------------EA32D12CCED06FA4A95CAC88
Content-Type: text/plain; charset=us-ascii;
 name="buttonlabel.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="buttonlabel.c"

/*
 * File : buttonlabel.c
 *
 * Description : Simple application to demonstrate the changing of button 
 *         labels.
 *
 * Dependencies : buttonlabel.glade
 *
 * Author : Andrae Muys <andrae humbug org au>
 *
 * Date : 15th May 2001
 *
 * License : GPL.
 *
 */

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

#define FILENAME "buttonlabel.glade"

GladeXML *xml;
GtkWidget *button;

int main(int argc, char *argv[]) {
        gtk_init(&argc, &argv);
        glade_init();

        if (argc == 1) {
                xml = glade_xml_new(FILENAME, "mainWindow");
        } else {
                xml = glade_xml_new(argv[1], "mainWindow");
        }

        if(!xml) {
                g_warning("Could not load interface.");
                return 1;
        }

        button = glade_xml_get_widget(xml, "button");
        gtk_label_set_text(GTK_LABEL(GTK_BIN(button)->child), "hello");

        glade_xml_signal_autoconnect(xml);
        gtk_object_unref(GTK_OBJECT(xml));

        gtk_main();

        return 0;
}

static int clicked = 0;
void on_button_clicked(GtkWidget *button, gpointer data) {
        if (clicked == 0) {
                GList *child = gtk_container_children(GTK_CONTAINER(button));
                gtk_label_set_text(GTK_LABEL(child->data), "clicked");
        } else if (clicked == 1) {
                gtk_object_set(GTK_OBJECT(button), "label", "goodbye", NULL);
        } else {
                gtk_main_quit();
        }
        clicked++;
}

--------------EA32D12CCED06FA4A95CAC88
Content-Type: text/html; charset=us-ascii;
 name="buttonlabel.glade"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="buttonlabel.glade"

<?xml version="1.0"?>
<GTK-Interface>

<project>
  <name>buttonlabel</name>
  <program_name>buttonlabel</program_name>
  <directory></directory>
  <source_directory>src</source_directory>
  <pixmaps_directory>pixmaps</pixmaps_directory>
  <language>C</language>
  <gnome_support>True</gnome_support>
  <gettext_support>True</gettext_support>
</project>

<widget>
  <class>GtkWindow</class>
  <name>mainWindow</name>
  <signal>
    <name>delete_event</name>
    <handler>gtk_main_quit</handler>
    <last_modification_time>Mon, 14 May 2001 23:48:38 GMT</last_modification_time>
  </signal>
  <title>window1</title>
  <type>GTK_WINDOW_TOPLEVEL</type>
  <position>GTK_WIN_POS_NONE</position>
  <modal>False</modal>
  <allow_shrink>False</allow_shrink>
  <allow_grow>True</allow_grow>
  <auto_shrink>False</auto_shrink>

  <widget>
    <class>GtkButton</class>
    <name>button</name>
    <can_focus>True</can_focus>
    <signal>
      <name>clicked</name>
      <handler>on_button_clicked</handler>
      <last_modification_time>Mon, 14 May 2001 23:51:09 GMT</last_modification_time>
    </signal>
    <label>button</label>
  </widget>
</widget>

</GTK-Interface>

--------------EA32D12CCED06FA4A95CAC88
Content-Type: text/plain; charset=us-ascii;
 name="Makefile"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Makefile"

CC=gcc
DEBUG=-g
CFLAGS=$(DEBUG) -W -Wall -ansi-pedantic `gnome-config --cflags glib gtk libglade`
LDFLAGS=`gnome-config --libs glib gtk libglade`

all: buttonlabel

buttonlabel: buttonlabel.o
        $(CC) $(LDFLAGS) -o $@ $^

--------------EA32D12CCED06FA4A95CAC88--






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]