使用 glade 和 GTK+ 进行信号处理
Signal handling with glade and GTK+
出于好奇而尝试学习 Linux 开发,对 C 知之甚少
我正在使用 glade 3.18.3。
我想创建一个应用程序,当按下 button1
时,label1
上的文本将随着 entry1
(输入框)中的输入文本而改变。
我不知道如何将所需的参数传递给回调。
这是sample.glade
:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Nishant</property>
<property name="default_width">440</property>
<property name="default_height">250</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem1">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem2">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem3">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem4">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem5">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem6">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem7">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem8">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem9">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem10">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</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">label1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="name">entry1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button1</property>
<property name="name">button1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<signal name="activate" handler="on_button1_activate" swapped="no"/>
<signal name="clicked" handler="on_button1_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
...这是 main.c
:
//##gcc -o gladewin main.c -Wall pkg-config --cflags --libs gtk+-3.0
-export-dynamic
#include <gtk/gtk.h>
#include <stdio.h>
//gchar *buffer1; //added
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
// ## gchar BUFF[100];
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "sample.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
return 0;
}
// called when window is closed
void on_window_main_destroy()
{
gtk_main_quit();
}
//called when button1 is clicked
void on_button1_clicked()
{
//buffer1 = gtk_entry_get_buffer (entry);
//gtk_entry_buffer_get_text (buffer1);
g_print("Button1 pressed");
//gtk_button_set_label (button1 ,"Hi");
//gtk_label_set_text(GTK_LABEL(entry1),"hi"); // i think this is correct just need tofigure out what to replace insted of entry1
}
你获取GtkEntry文本的方法很奇怪。您根本不需要玩缓冲区;只是做
const char *text = gtk_entry_get_text(myEntry);
text
返回的缓冲区为您提供了完整的文本,但作为 read-only 字符串,在 GtkEntry 需要时释放。
根据您的需要,可以直接传给gtk_button_set_label()
和gtk_label_set_text()
:
gtk_button_set_label(button, text);
gtk_label_set_text(label, text);
通常,该值在整个信号处理程序中保持有效。
如果您想保留文本供以后使用,您需要使用 g_strdup()
复制它(使用 g_free()
免费)。
另外 gtk_label_set_text()
不适用于 GtkEntry;你需要和它一起使用 GtkLabel。
信号回调接收特定参数,具体取决于捕获的信号类型。每个回调的签名都是官方文档documented
在 glade 中,当定义一个信号时,您可以将一个额外的小部件传递给信号回调。真正的挑战是您只能传递 一个 小部件,而您需要访问它们(标签和条目)。
在纯 C 中,您会将两个指针填充到一个结构中并使用它来代替,但如果您仍想使用 glade,则必须找到另一种解决方案。一种方法是使用两个回调,例如:
那么你的回调可能是:
void read_from_entry(GtkButton *button, gpointer user_data)
{
GtkEntry *entry = GTK_ENTRY(user_data);
g_print("read_from_entry\n");
g_object_set_data(G_OBJECT(button), "text", (gpointer) gtk_entry_get_text(entry));
}
void write_to_label(GtkButton *button, gpointer user_data)
{
GtkLabel *label = GTK_LABEL(user_data);
g_print("write_to_label\n");
gtk_label_set_text(label, g_object_get_data(G_OBJECT(button), "text"));
}
g_object_{set,get}_data
对只是为了避免使用全局变量。以上将可靠地工作,前提是:
- 保留回调顺序;
- 不要写入两个回调中或两个回调之间的条目。
出于好奇而尝试学习 Linux 开发,对 C 知之甚少
我正在使用 glade 3.18.3。
我想创建一个应用程序,当按下 button1
时,label1
上的文本将随着 entry1
(输入框)中的输入文本而改变。
我不知道如何将所需的参数传递给回调。
这是sample.glade
:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Nishant</property>
<property name="default_width">440</property>
<property name="default_height">250</property>
<signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem1">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem2">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem3">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem4">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem5">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem6">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem7">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem8">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem9">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem10">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</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">label1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="name">entry1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button1</property>
<property name="name">button1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<signal name="activate" handler="on_button1_activate" swapped="no"/>
<signal name="clicked" handler="on_button1_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
...这是 main.c
:
//##gcc -o gladewin main.c -Wall pkg-config --cflags --libs gtk+-3.0
-export-dynamic
#include <gtk/gtk.h>
#include <stdio.h>
//gchar *buffer1; //added
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
// ## gchar BUFF[100];
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "sample.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
return 0;
}
// called when window is closed
void on_window_main_destroy()
{
gtk_main_quit();
}
//called when button1 is clicked
void on_button1_clicked()
{
//buffer1 = gtk_entry_get_buffer (entry);
//gtk_entry_buffer_get_text (buffer1);
g_print("Button1 pressed");
//gtk_button_set_label (button1 ,"Hi");
//gtk_label_set_text(GTK_LABEL(entry1),"hi"); // i think this is correct just need tofigure out what to replace insted of entry1
}
你获取GtkEntry文本的方法很奇怪。您根本不需要玩缓冲区;只是做
const char *text = gtk_entry_get_text(myEntry);
text
返回的缓冲区为您提供了完整的文本,但作为 read-only 字符串,在 GtkEntry 需要时释放。
根据您的需要,可以直接传给gtk_button_set_label()
和gtk_label_set_text()
:
gtk_button_set_label(button, text);
gtk_label_set_text(label, text);
通常,该值在整个信号处理程序中保持有效。
如果您想保留文本供以后使用,您需要使用 g_strdup()
复制它(使用 g_free()
免费)。
另外 gtk_label_set_text()
不适用于 GtkEntry;你需要和它一起使用 GtkLabel。
信号回调接收特定参数,具体取决于捕获的信号类型。每个回调的签名都是官方文档documented
在 glade 中,当定义一个信号时,您可以将一个额外的小部件传递给信号回调。真正的挑战是您只能传递 一个 小部件,而您需要访问它们(标签和条目)。
在纯 C 中,您会将两个指针填充到一个结构中并使用它来代替,但如果您仍想使用 glade,则必须找到另一种解决方案。一种方法是使用两个回调,例如:
那么你的回调可能是:
void read_from_entry(GtkButton *button, gpointer user_data)
{
GtkEntry *entry = GTK_ENTRY(user_data);
g_print("read_from_entry\n");
g_object_set_data(G_OBJECT(button), "text", (gpointer) gtk_entry_get_text(entry));
}
void write_to_label(GtkButton *button, gpointer user_data)
{
GtkLabel *label = GTK_LABEL(user_data);
g_print("write_to_label\n");
gtk_label_set_text(label, g_object_get_data(G_OBJECT(button), "text"));
}
g_object_{set,get}_data
对只是为了避免使用全局变量。以上将可靠地工作,前提是:
- 保留回调顺序;
- 不要写入两个回调中或两个回调之间的条目。