Back to Blog

GTK/Glade Program Development (Part 3)

#ProgramDev#GTK#Buffer#Attributes#Tree#Insert

Menu Widget

In this section, our design is as follows: Clicking the 'Open' submenu under the 'File' menu in the main window will pop up a new window. Using menu widgets is relatively straightforward. Once designed, simply locate the function corresponding to the respective menu in callbacks.c and add your code there. Our main menu has two items: 'File' and 'Edit'. Under 'File', there are 'Open' and 'Save'. Under 'Edit', there are 'Copy' and 'Paste'.

Creating Menu Widgets: /* Creating menu widgets involves many functions, but fortunately, Glade automatically generates the code. We don't need to worry about it. */

New functions used in this section:

None

I. Designing the Interface with Glade Steps: 1. Create a new Glade project.      2. Place a window (400, 300), a fixed container, and a menu widget in order.      3. Select the menu widget, then click the 'Edit Menu' button in the 'Properties' panel to edit the menu.      4. When editing the menu, note: Menu labels can use Chinese characters, but menu names should use English. Otherwise, in the generated code, you won't be able to tell which is which.      5. In the project, place another window widget, and place a label on the new window. The label's property is 'window2'.      6. Save the project and generate the code.

II. Modifying the Code

callbacks.h /**/

void  on_open1_activate (GtkMenuItem *menuitem,

gpointer user_data);

void  on_save1_activate (GtkMenuItem *menuitem,

gpointer user_data);

void  on_copy1_activate (GtkMenuItem *menuitem,

gpointer user_data);

void  on_pause1_activate (GtkMenuItem *menuitem,

gpointer user_data);

callbacks.c

void on_open1_activate (GtkMenuItem *menuitem,

gpointer user_data)

{

GtkWidget *window2;

window2 = create_window2 ();

gtk_widget_show (window2);

}

void on_save1_activate (GtkMenuItem *menuitem,

gpointer user_data)

{

}

void on_copy1_activate (GtkMenuItem *menuitem,

gpointer user_data)

{

}

void on_pause1_activate (GtkMenuItem *menuitem,

gpointer user_data)

{

}

Making some fixes to the original code for the range widget. interface.c Uncomment /* GtkWidget *all_label1;*/.

callbacks.h Delete GtkWidget *all_label1;.

callbacks.c Add the following line of code to the first line of the on_hscrollbar1_value_changed function: GtkWidget *all_label1 = lookup_widget (GTK_WIDGET(range), "all_label1");

Add the following line of code to the first line of the on_vscrollbar1_value_changed function: GtkWidget *all_label1 = lookup_widget (GTK_WIDGET(range), "all_label1");

This should fix it.

TextView Widget

Our design is as follows: Place a button widget and a TextView widget on the window. Clicking the button widget will display formatted text in the TextView widget.

The TextView widget is used as follows: A TextView widget must be used in conjunction with a TextBuffer widget. 'Formatted text' is defined and stored in the TextBuffer widget, and then displayed in the TextView widget.

Therefore, displaying formatted text using a TextView widget requires three steps:

  1. Define 'formatted text' (in TextBuffer).
  2. Store 'formatted text' (in TextBuffer).
  3. Display 'formatted text' (in TextView).

In this section: A separate function create_tags was written to define 'formatted text', and a separate function insert_text was written to store 'formatted text'.

I. Design the interface with Glade, and add a 'clicked' signal response to the button widget.

II. Adding Code.

callbacks.c

/* Function: Define formatted text */

static void create_tags (GtkTextBuffer buffer) { gtk_text_buffer_create_tag (buffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_create_tag (buffer, "blue_foreground", "foreground", "blue", NULL); gtk_text_buffer_create_tag (buffer, "red_background", "background", "red", NULL); / Parameter meanings: "red_background", name of the formatted text. "background", "red", attributes of the formatted text. */

}

/* Function: Store formatted text */

static void insert_text (GtkTextBuffer *buffer) { GtkTextIter iter; GtkTextIter start, end; gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0); gtk_text_buffer_insert (buffer, &iter, "The text widget can display Richtext./n", -1); gtk_text_buffer_insert (buffer, &iter, "For example, you can have/n ", -1);

gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "a blue foreground /n", -1, "blue_foreground", NULL);

gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "a red background /n /n", -1, "red_background", NULL); /* Parameter meanings: "a red background /n /n", the text to display. "red_background", name of the formatted text. */ }

void on_button1_clicked (GtkButton *button, gpointer user_data) {

GtkWidget *textview1 = lookup_widget (GTK_WIDGET(button), "textview1"); GtkTextBuffer *buffer;

buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(textview1)); create_tags (buffer); insert_text (buffer);

}

TreeView Widget

The TreeView widget requires the support of three other widgets. In other words, the TreeView widget can only be used in conjunction with these three other widgets. These three widgets, along with GtkTreeView itself, are: GtkTreeModel GtkCellRenderer GtkTreeViewColumn GtkTreeView

The TreeView widget is quite flexible. It can display data in a list format, or in a tree-like structure. It also allows for various flexible operations on the displayed data. There are many features to explore later!

In this section, we will discuss its simplest function: displaying data in a list format. The design is as follows: Clicking a button displays data in a list format within the TreeView widget.

I. Designing the Interface with Glade. Place a window widget, a vertical box widget (set to two rows when placed), then place a button widget in the first row of the vertical box. Place a TreeView widget in the second row. Generate the code.

II. Writing Code

callbacks.c

/* Define data structure */

typedef struct { const gchar *id; const gchar *name; const gchar *address; } telman;

enum { COLUMN_ID, COLUMN_NAME, COLUMN_ADDRESS, NUM_COLUMNS };

/* Add data */

static telman data[] = { {"001","cuigf","china"},{"002","home","shanxi"},{"003","",""}, };

/* Set TreeView widget model */

static GtkTreeModel * create_model (void) { gint i = 0; GtkListStore *store; GtkTreeIter iter;

/* create list store */ store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);

/* add data to the list store */ for (i = 0; i < G_N_ELEMENTS (data); i++) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_ID, data[i].id, COLUMN_NAME, data[i].name, COLUMN_ADDRESS, data[i].address, -1); }

return GTK_TREE_MODEL (store); }

/* Add columns to TreeView widget */

static void add_columns (GtkTreeView *treeview) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("ID", renderer, "text", COLUMN_ID, NULL); gtk_tree_view_append_column (treeview, column);

renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("NAME", renderer, "text", COLUMN_NAME, NULL); gtk_tree_view_append_column (treeview, column);

renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("ADDRESS", renderer, "text", COLUMN_ADDRESS, NULL); gtk_tree_view_append_column (treeview, column); }

void on_button1_clicked (GtkButton *button, gpointer user_data) { GtkWidget *treeview1 = lookup_widget (GTK_WIDGET(button), "treeview1"); GtkTreeModel *model; model = create_model (); gtk_tree_view_set_model(GTK_TREE_VIEW(treeview1),model); g_object_unref (model); add_columns (GTK_TREE_VIEW (treeview1)); }