[英]GTK pass user data to callback using Glade
我注意到Glade只允許你設置一個在GTK回調的用戶數據部分內傳遞的對象。
有沒有辦法可以傳遞一個整數值?
我有一組菜單項,我想指向相同的回調函數,但是對於代碼的一小部分我需要確定哪個菜單項是調用回調的菜單項。
注意:我的所有信號都是使用glade_xml_signal_autoconnect自動設置的,我會按照這種方式保留它。
在我看來,對於林間空地和回調,人們不得不告別將一個單一元素傳遞給回調的概念。 因此,停止使用glade
以配置傳遞給特定回調的用戶數據。
我習慣將名為App
的結構傳遞給所有回調,這些回調包含指向從ui定義文件加載並已由GtkBuilder
實例化的每個ui元素的指針。 這也停止了繁瑣的任務, glade
點擊之間來回部件只設置了回調的用戶數據。 除了ui元素之外,大多數情況下,此結構還包含在應用程序級別上運行時很重要的其他元素。
這種方法的一個好處是你不會想到如何實現一個單獨的回調,這個回調應該作用於多個元素,而這通常就是這種情況。 有些人通過將感興趣的小部件分組到容器中來解決這個問題。 為了將所有小部件傳遞給回調,它們只是傳遞容器。 然后在回調中,他們通過調用gtk_container_get_children
或類似的函數來獲取小部件。 這種方法使得回調難以辨認,並在編輯代碼時減少了樂趣。
如果每個回調都具有應該在運行時操作的所有可用元素,則不必關心實現單個回調,因為每個回調共享相同的結構。
此外,我創建了一個輔助宏,它定義了一個指向已經實例化的元素的指針,該元素具有其glade id的名稱。 這樣,代碼中的元素定義始終與glade中顯示的元素定義同步。 這使得小部件的重命名非常容易(替換所有源中的名稱+ glade文件)。
為了說明這種方法,我附加了一個示例程序的文件。 不要害怕文件的數量。 將程序划分為邏輯單元/模塊使編程更加簡單。 為了快速查看整個項目,我在github上創建了一個git存儲庫:
只需將我的callbacks.c
與您的回調文件進行比較即可。 我很想知道他們如何在易讀性和結構方面進行比較,並考慮到你可能仍然記得來自林間glade
的元素ID。
callbacks.c
:
#include "app.h"
void
button1_clicked_cb (GtkButton * button, App * app)
{
GET_UI_ELEMENT (GtkEntry, entry1);
if (gtk_entry_get_text_length (entry1) == 0)
gtk_entry_set_text (entry1, "test");
else
gtk_entry_set_text (entry1, "");
}
void
button2_clicked_cb (GtkButton * button, App * app)
{
gboolean active;
GET_UI_ELEMENT (GtkSpinner, spinner1);
GET_UI_ELEMENT (GtkWidget, eventbox1);
g_object_get (G_OBJECT (spinner1), "active", &active,
NULL);
if (active) {
gtk_spinner_stop (spinner1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
app->
active_color);
}
else {
gtk_spinner_start (spinner1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
app->
inactive_color);
}
}
void
button3_clicked_cb (GtkButton * button, App * app)
{
GdkRGBA bg = { 0, 0, 1, 1 };
GET_UI_ELEMENT (GtkWidget, eventbox1);
gtk_widget_override_background_color (eventbox1,
GTK_STATE_FLAG_NORMAL,
&bg);
}
void
button4_clicked_cb (GtkButton * button, App * app)
{
const gchar *str;
GET_UI_ELEMENT (GtkLabel, label1);
str = gtk_label_get_text (label1);
if (strcmp (str, "label") == 0) {
gtk_label_set_text (label1, "NewText");
}
else {
gtk_label_set_text (label1, "label");
}
}
void
button5_clicked_cb (GtkButton * button, App * app)
{
GET_UI_ELEMENT (GtkWidget, button1);
GET_UI_ELEMENT (GtkWidget, button2);
GET_UI_ELEMENT (GtkWidget, button4);
g_signal_emit_by_name (button1, "clicked", app);
g_signal_emit_by_name (button2, "clicked", app);
g_signal_emit_by_name (button4, "clicked", app);
}
main.c
:
#include "app.h"
int
main (int argc, char *argv[])
{
App *app;
app = (App *) g_new (App, 1);
gtk_init (&argc, &argv);
app_init (app);
GET_UI_ELEMENT (GtkWidget, window1);
gtk_widget_show_all (window1);
gtk_main ();
return 0;
}
app.c
:
#include "app.h"
GObject *
app_get_ui_element (App * app, const gchar * name)
{
const gchar *s;
GSList *list;
list = app->objects;
do {
s = gtk_buildable_get_name (list->data);
if (strcmp (s, name) == 0) {
return list->data;
}
} while (list = g_slist_next (list));
return NULL;
}
void
app_init_colors (App * app)
{
GdkRGBA active_color = { 1, 0, 0, 1 };
GdkRGBA inactive_color = { 0, 1, 0, 1 };
app->active_color = g_new0 (GdkRGBA, 1);
app->inactive_color = g_new0 (GdkRGBA, 1);
app->active_color = gdk_rgba_copy (&active_color);
app->inactive_color = gdk_rgba_copy (&inactive_color);
}
void
app_init (App * app)
{
GError *err = NULL;
app->definitions = gtk_builder_new ();
gtk_builder_add_from_file (app->definitions,
UI_DEFINITIONS_FILE, &err);
if (err != NULL) {
g_printerr
("Error while loading app definitions file: %s\n",
err->message);
g_error_free (err);
gtk_main_quit ();
}
gtk_builder_connect_signals (app->definitions, app);
app->objects = gtk_builder_get_objects (app->definitions);
app_init_colors (app);
}
app.h
:
#ifndef __APP__
#define __APP__
#include <gtk/gtk.h>
#define UI_DEFINITIONS_FILE "ui.glade"
#define GET_UI_ELEMENT(TYPE, ELEMENT) TYPE *ELEMENT = (TYPE *) \
app_get_ui_element(app, #ELEMENT);
typedef struct app_
{
GtkBuilder *definitions;
GSList *objects;
GdkRGBA *active_color;
GdkRGBA *inactive_color;
} App;
void app_init (App * );
GObject * app_get_ui_element (App * , const gchar * );
#endif
ui.glade
:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="border_width">20</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
<property name="column_spacing">20</property>
<child>
<object class="GtkSpinner" id="spinner1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEventBox" id="eventbox1">
<property name="height_request">50</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">10</property>
<property name="layout_style">center</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">toggle entry</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button1_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">toggle spinner + bg</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button2_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="label" translatable="yes">set bg</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button3_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label" translatable="yes">toggle label</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button4_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button5">
<property name="label" translatable="yes">toggle everything</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button5_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">4</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">4</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.