如何避免在我的 GTK3 应用程序中使用全局指针变量
How to avoid using a global pointer variable in my GTK3 Application
我正在 C
创建一个 GTK3
CHAT 应用程序 Linux(Linux mint 19 现在),我不知道如何避免在我设计整个程序的方式中使用全局(标签)指针。
有一个 window,它有一个按钮、一个条目和一个标签。
当用户键入内容并按下 Enter 键或按下按钮时,消息应打印在标签部分。
一切正常,除了我在此处使用全局指针更新标签,我想避免它,并在信号函数中使用它。
这是一个可以正常编译并可以测试的工作示例:
#include <gtk/gtk.h>
GtkWidget *label;
static void display ( GtkWidget *widget, GtkWidget *data )
{
(void)widget;
const gchar *const buffer = gtk_entry_get_text ( GTK_ENTRY ( data ) );
if ( strlen ( buffer ) > 0 )
{
g_print ( "%s\n", buffer );
gtk_label_set_text ( GTK_LABEL ( label ), buffer );
}
gtk_entry_set_text ( GTK_ENTRY ( data ), "" );
gtk_editable_select_region ( GTK_EDITABLE ( data ), 0, -1 );
gtk_editable_copy_clipboard ( GTK_EDITABLE ( data ) );
}
GtkWidget *createWind ( void );
GtkWidget *createGrid ( GtkWidget *window );
GtkWidget *createButton ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
GtkWidget *createEntry ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
GtkWidget *createLabel ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
int main ( void )
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *entry;
GtkWidget *button;
gtk_init ( NULL, NULL );
window = createWind ();
gtk_widget_show ( window );
grid = createGrid ( window );
gtk_widget_show ( grid );
entry = createEntry ( grid, 0, 1, 1, 1 );
gtk_widget_show ( entry );
button = createButton ( grid, 1, 1, 1, 1 );
gtk_widget_show ( button );
label = createLabel ( grid, 0, 0, 1, 1 );
gtk_widget_show ( label );
g_signal_connect ( button, "clicked", G_CALLBACK ( display ), entry );
g_signal_connect ( entry, "activate", G_CALLBACK ( display ), entry );
//gtk_widget_show_all ( window );
gtk_main();
}
GtkWidget *createWind ( void )
{
GdkRectangle display = { 0 };
GtkWidget *window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gdk_monitor_get_workarea ( gdk_display_get_primary_monitor ( gdk_display_get_default() ), &display );
gtk_window_move ( GTK_WINDOW ( window ), display.width, display.height );
gtk_window_set_title ( GTK_WINDOW ( window ), "MyApp" );
gtk_window_set_default_size ( GTK_WINDOW ( window ), 850, 100 );
gtk_window_set_resizable ( GTK_WINDOW ( window ), FALSE );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 5 );
g_signal_connect ( window, "destroy", G_CALLBACK ( gtk_main_quit ), NULL );
return window;
}
GtkWidget *createGrid ( GtkWidget *window )
{
GtkWidget *grid = gtk_grid_new();
gtk_widget_set_name ( grid, "Grid" );
gtk_container_add ( GTK_CONTAINER ( window ), grid );
return grid;
}
GtkWidget *createEntry ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *entry = gtk_entry_new();
gtk_widget_set_name ( grid, "Entry" );
gtk_widget_set_size_request ( entry, 800, 50 );
g_object_set ( entry, "margin", 22, NULL );
gtk_grid_attach ( GTK_GRID ( grid ), entry, left, top, width, height );
return entry;
}
GtkWidget *createLabel ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *ret = gtk_label_new ( "Type a Message" );
gtk_widget_set_name ( ret, "Label" );
gtk_widget_set_size_request ( ret, 850, 250 );
gtk_label_set_justify ( GTK_LABEL ( ret ), GTK_JUSTIFY_CENTER );
gtk_grid_attach ( GTK_GRID ( grid ), ret, left, top, width, height );
return ret;
}
GtkWidget *createButton ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *button = gtk_button_new_with_mnemonic ( "Send" );
gtk_widget_set_name ( button, "Button" );
gtk_widget_set_size_request ( button, 50, 50 );
g_object_set ( button, "margin", 22, NULL );
gtk_grid_attach ( GTK_GRID ( grid ), button, left, top, width, height );
return button;
}
免责声明:我从未使用过 GTK,也无法实际测试我的代码。以下内容基于粗略阅读文档。
信号回调的最后一个参数可以是任何你想要的(只要它是一个指针)。
因此您应该能够通过此参数传递条目和标签,例如通过将所有数据捆绑在自定义结构中。
结构本身可以是main
中的局部变量,其地址传递给回调,然后回调可以根据需要恢复内容。
例如:
struct EntryLabelPair {
GtkWidget *entry;
GtkWidget *label;
};
static void display ( GtkWidget *widget, gpointer *data )
{
(void)widget;
struct EntryLabelPair *pair = data;
const gchar *const buffer = gtk_entry_get_text ( GTK_ENTRY ( pair->entry ) );
if ( strlen ( buffer ) > 0 )
{
g_print ( "%s\n", buffer );
gtk_label_set_text ( GTK_LABEL ( pair->label ), buffer );
}
gtk_entry_set_text ( GTK_ENTRY ( pair->entry ), "" );
gtk_editable_select_region ( GTK_EDITABLE ( pair->entry ), 0, -1 );
gtk_editable_copy_clipboard ( GTK_EDITABLE ( pair->entry ) );
}
...
int main ( void )
{
GtkWidget *window;
GtkWidget *grid;
struct EntryLabelPair pair;
...
pair.entry = createEntry ( grid, 0, 1, 1, 1 );
gtk_widget_show ( pair.entry );
pair.label = createLabel ( grid, 0, 0, 1, 1 );
gtk_widget_show ( pair.label );
g_signal_connect ( button, "clicked", G_CALLBACK ( display ), &pair );
g_signal_connect ( entry, "activate", G_CALLBACK ( display ), &pair );
...
}
我正在 C
创建一个 GTK3
CHAT 应用程序 Linux(Linux mint 19 现在),我不知道如何避免在我设计整个程序的方式中使用全局(标签)指针。
有一个 window,它有一个按钮、一个条目和一个标签。 当用户键入内容并按下 Enter 键或按下按钮时,消息应打印在标签部分。
一切正常,除了我在此处使用全局指针更新标签,我想避免它,并在信号函数中使用它。
这是一个可以正常编译并可以测试的工作示例:
#include <gtk/gtk.h>
GtkWidget *label;
static void display ( GtkWidget *widget, GtkWidget *data )
{
(void)widget;
const gchar *const buffer = gtk_entry_get_text ( GTK_ENTRY ( data ) );
if ( strlen ( buffer ) > 0 )
{
g_print ( "%s\n", buffer );
gtk_label_set_text ( GTK_LABEL ( label ), buffer );
}
gtk_entry_set_text ( GTK_ENTRY ( data ), "" );
gtk_editable_select_region ( GTK_EDITABLE ( data ), 0, -1 );
gtk_editable_copy_clipboard ( GTK_EDITABLE ( data ) );
}
GtkWidget *createWind ( void );
GtkWidget *createGrid ( GtkWidget *window );
GtkWidget *createButton ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
GtkWidget *createEntry ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
GtkWidget *createLabel ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height );
int main ( void )
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *entry;
GtkWidget *button;
gtk_init ( NULL, NULL );
window = createWind ();
gtk_widget_show ( window );
grid = createGrid ( window );
gtk_widget_show ( grid );
entry = createEntry ( grid, 0, 1, 1, 1 );
gtk_widget_show ( entry );
button = createButton ( grid, 1, 1, 1, 1 );
gtk_widget_show ( button );
label = createLabel ( grid, 0, 0, 1, 1 );
gtk_widget_show ( label );
g_signal_connect ( button, "clicked", G_CALLBACK ( display ), entry );
g_signal_connect ( entry, "activate", G_CALLBACK ( display ), entry );
//gtk_widget_show_all ( window );
gtk_main();
}
GtkWidget *createWind ( void )
{
GdkRectangle display = { 0 };
GtkWidget *window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gdk_monitor_get_workarea ( gdk_display_get_primary_monitor ( gdk_display_get_default() ), &display );
gtk_window_move ( GTK_WINDOW ( window ), display.width, display.height );
gtk_window_set_title ( GTK_WINDOW ( window ), "MyApp" );
gtk_window_set_default_size ( GTK_WINDOW ( window ), 850, 100 );
gtk_window_set_resizable ( GTK_WINDOW ( window ), FALSE );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 5 );
g_signal_connect ( window, "destroy", G_CALLBACK ( gtk_main_quit ), NULL );
return window;
}
GtkWidget *createGrid ( GtkWidget *window )
{
GtkWidget *grid = gtk_grid_new();
gtk_widget_set_name ( grid, "Grid" );
gtk_container_add ( GTK_CONTAINER ( window ), grid );
return grid;
}
GtkWidget *createEntry ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *entry = gtk_entry_new();
gtk_widget_set_name ( grid, "Entry" );
gtk_widget_set_size_request ( entry, 800, 50 );
g_object_set ( entry, "margin", 22, NULL );
gtk_grid_attach ( GTK_GRID ( grid ), entry, left, top, width, height );
return entry;
}
GtkWidget *createLabel ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *ret = gtk_label_new ( "Type a Message" );
gtk_widget_set_name ( ret, "Label" );
gtk_widget_set_size_request ( ret, 850, 250 );
gtk_label_set_justify ( GTK_LABEL ( ret ), GTK_JUSTIFY_CENTER );
gtk_grid_attach ( GTK_GRID ( grid ), ret, left, top, width, height );
return ret;
}
GtkWidget *createButton ( GtkWidget *grid, const gint left, const gint top, const gint width, const gint height )
{
GtkWidget *button = gtk_button_new_with_mnemonic ( "Send" );
gtk_widget_set_name ( button, "Button" );
gtk_widget_set_size_request ( button, 50, 50 );
g_object_set ( button, "margin", 22, NULL );
gtk_grid_attach ( GTK_GRID ( grid ), button, left, top, width, height );
return button;
}
免责声明:我从未使用过 GTK,也无法实际测试我的代码。以下内容基于粗略阅读文档。
信号回调的最后一个参数可以是任何你想要的(只要它是一个指针)。
因此您应该能够通过此参数传递条目和标签,例如通过将所有数据捆绑在自定义结构中。
结构本身可以是main
中的局部变量,其地址传递给回调,然后回调可以根据需要恢复内容。
例如:
struct EntryLabelPair {
GtkWidget *entry;
GtkWidget *label;
};
static void display ( GtkWidget *widget, gpointer *data )
{
(void)widget;
struct EntryLabelPair *pair = data;
const gchar *const buffer = gtk_entry_get_text ( GTK_ENTRY ( pair->entry ) );
if ( strlen ( buffer ) > 0 )
{
g_print ( "%s\n", buffer );
gtk_label_set_text ( GTK_LABEL ( pair->label ), buffer );
}
gtk_entry_set_text ( GTK_ENTRY ( pair->entry ), "" );
gtk_editable_select_region ( GTK_EDITABLE ( pair->entry ), 0, -1 );
gtk_editable_copy_clipboard ( GTK_EDITABLE ( pair->entry ) );
}
...
int main ( void )
{
GtkWidget *window;
GtkWidget *grid;
struct EntryLabelPair pair;
...
pair.entry = createEntry ( grid, 0, 1, 1, 1 );
gtk_widget_show ( pair.entry );
pair.label = createLabel ( grid, 0, 0, 1, 1 );
gtk_widget_show ( pair.label );
g_signal_connect ( button, "clicked", G_CALLBACK ( display ), &pair );
g_signal_connect ( entry, "activate", G_CALLBACK ( display ), &pair );
...
}