C 信号连接功能中的指针工作不正常
我想使用C 信号连接功能中的指针工作不正常,c,pointers,gtk3,gtkmm,C,Pointers,Gtk3,Gtkmm,我想使用g\u signal\u connect()函数更改特定struct/class中的数据。因此,在我看来,最好的方法是使用指向struct的指针。问题是指针的信息似乎一直在变化 我花了很多时间想弄明白为什么会这样,但我不知道。 我可以编译和运行代码,没有任何错误,但输出总是不同的 稍后我想使用几个事件框连接到结构数组或类数组(event\u框[0]connect todata[0],…) 我希望有人理解我的意思,我会很高兴得到任何帮助 #include<gtk/gtk.h>
g\u signal\u connect()
函数更改特定struct/class
中的数据。因此,在我看来,最好的方法是使用指向struct
的指针。问题是指针的信息似乎一直在变化
我花了很多时间想弄明白为什么会这样,但我不知道。
我可以编译和运行代码,没有任何错误,但输出总是不同的
稍后我想使用几个事件框连接到结构数组或类数组(event\u框[0]
connect todata[0]
,…)
我希望有人理解我的意思,我会很高兴得到任何帮助
#include<gtk/gtk.h>
struct d
{
bool status;
int ID;
};
void end_program(GtkWidget *wid, gpointer ptr)
{
gtk_main_quit();
}
void box_click(GtkWidget *wid, gpointer user_data)
{
struct d *data = (struct d*)user_data;
printf("status = %i\n", data->status);
printf("ID = %i\n", data->ID);
}
int main (int argc, char *argv[])
{
struct d data;
data.status = 0;
data.ID = 1;
gtk_init(&argc, &argv);
GtkWidget *win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *event_box = gtk_event_box_new();
g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(box_click), &data);
gtk_container_add(GTK_CONTAINER(win), event_box);
gtk_widget_show_all(win);
g_signal_connect(win, "delete_event", G_CALLBACK(end_program),NULL);
gtk_main();
return 0;
}
我希望有人能理解我的意思,我也会很高兴
救命啊
嗯,是的。。您对按钮按下事件使用了错误的函数原型。按钮按下事件的原型是:
The “button-press-event” signal
gboolean
user_function (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
(注意:信号正确地显示为“按钮按下事件”,而不是“按钮按下事件”,尽管有一个\define
允许第二个表单工作)
看。因此,您的函数应该是:
gboolean box_click(GtkWidget *wid, GdkEvent *event, gpointer user_data)
{
struct d *data = user_data; /* no need for cast, gpointer is void* */
g_print("status = %d\n", data->status);
g_print("ID = %d\n", data->ID);
return TRUE; /* to prevent further handling, FALSE otherwise */
(void)wid; /* cast to void to avoid unused var warning */
(void)event;
}
附加NIT
使用
g_print
代替printf
,使用gboolean
代替bool
。传递的地址对于小型结构很好,但是对于大型结构,您应该使用g_slice\u new
进行分配。我将对这一部分进行一点扩展,其中@David C.Rankin说:
(void)wid; /* cast to void to avoid unused var warning */
(void)event;
因为有些重要的事情很多人都不知道
cast的需求一直都是错误的,这是因为有另一个函数被调用:
g_signal_connect_swapped()
通过将fist参数与最后一个参数交换,可以避免进行如此多的强制转换
让我们以下面的例子为例:
#include <gtk/gtk.h>
GtkWidget *createWindow ( const gint width, const gint height );
void user_function ( GtkWidget *object, gpointer user_data );
int main ( void )
{
GtkWidget *window;
gtk_init ( NULL, NULL );
/// ***
window = createWindow( 300, 300 );
/// ***
g_signal_connect ( window, "destroy", G_CALLBACK( user_function ), NULL );
/// ***
gtk_widget_show_all ( window );
gtk_main();
}
GtkWidget *createWindow ( const gint width, const gint height )
{
GtkWidget *window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gtk_widget_set_size_request ( window, width, height );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 50 );
return window;
}
void user_function ( GtkWidget *object, gpointer user_data )
{
(void)object;
(void)user_data;
g_print( "Goodbye\n" );
gtk_main_quit();
}
或者更好:
g_signal_connect_swapped ( window, "destroy", G_CALLBACK( user_function ), (gpointer)"Goodbye" );
现在我们的程序如下所示:
g_signal_connect_swapped ( window, "destroy", G_CALLBACK( user_function ), NULL
#include <gtk/gtk.h>
GtkWidget *createWindow ( const gint width, const gint height );
void user_function ( gpointer data );
int main ( void )
{
GtkWidget *window;
gtk_init ( NULL, NULL );
/// ***
window = createWindow( 300, 300 );
/// ***
g_signal_connect_swapped ( window, "destroy", G_CALLBACK( user_function ), (gpointer)"Goodbye" );
/// ***
gtk_widget_show_all ( window );
gtk_main();
}
GtkWidget *createWindow ( const gint width, const gint height )
{
GtkWidget *window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gtk_widget_set_size_request ( window, width, height );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 50 );
return window;
}
void user_function ( gpointer data )
{
g_print( "%s\n", (char*)data );
gtk_main_quit();
}
#包括
GtkWidget*createWindow(常量基特宽度、常量基特高度);
无效用户_函数(gpointer数据);
内部主(空)
{
GtkWidget*窗口;
gtk_init(NULL,NULL);
/// ***
window=createWindow(300300);
/// ***
g_信号连接交换(窗口,“销毁”,g_回调(用户函数),(gpointer)“再见”);
/// ***
gtk_小部件_全部显示(窗口);
gtk_main();
}
GtkWidget*createWindow(常量基特宽度、常量基特高度)
{
GtkWidget*window=gtk_window_new(gtk_window_TOPLEVEL);
gtk_小部件_设置_大小_请求(窗口、宽度、高度);
gtk_容器设置_边框宽度(gtk_容器(窗口),50);
返回窗口;
}
无效用户_函数(gpointer数据)
{
g_print(“%s\n”,(char*)数据);
gtk_main_quit();
}
再也没有石膏了
下面是一个更好的例子:
#include <gtk/gtk.h>
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event );
gboolean show_mouse_pressed ( GtkWidget *widget, GdkEventButton *event );
int main ( void )
{
GtkWidget *window;
GtkWidget *button;
gtk_init( NULL, NULL );
/// ***
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_default_size( GTK_WINDOW( window ), 300, 250 );
g_signal_connect( window, "destroy", gtk_main_quit, NULL );
gtk_container_set_border_width( GTK_CONTAINER( window ), 50 );
/// ***
button = gtk_button_new_with_mnemonic( "_Click me" );
gtk_widget_add_events( button, GDK_BUTTON_PRESS );
gtk_widget_add_events( button, GDK_SCROLL_MASK );
///g_signal_connect( button, "clicked", gtk_main_quit, NULL );
gtk_container_add( GTK_CONTAINER( window ), button );
/// ***
g_signal_connect_swapped( button, "button_press_event", G_CALLBACK( show_mouse_pressed ), window );
g_signal_connect_swapped( button, "scroll_event", G_CALLBACK( scroll_callback ), window );
/// ***
gtk_widget_show_all( window );
gtk_main();
}
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event )
{
if ( event->type == GDK_SCROLL ) /// Scroll was Catched ?
{
if ( event->scroll.direction == GDK_SCROLL_DOWN ) /// It is down?
{
g_print( "Scroll-Down Detected\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "Scroll-Down Detected" );
}
if ( event->scroll.direction == GDK_SCROLL_UP ) /// It is up?
{
g_print( "Scroll-UP Detected\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "Scroll-UP Detected" );
}
return FALSE;
}
return TRUE;
}
gboolean show_mouse_pressed ( GtkWidget *widget, GdkEventButton *event )
{
assert ( widget != NULL );
if ( gtk_widget_get_has_window ( widget ) )
{
if ( event->type == GDK_BUTTON_PRESS )
{
g_print( "The mouse clicked the button\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "The mouse was Clicked" );
}
return TRUE;
}
return FALSE;
}
#包括
gboolean scroll_回调(GtkWidget*小部件,GdkEvent*事件);
gboolean show_mouse_pressed(GtkWidget*小部件,GdkEventButton*事件);
内部主(空)
{
GtkWidget*窗口;
GtkWidget*按钮;
gtk_init(NULL,NULL);
/// ***
窗口=gtk_窗口_新建(gtk_窗口_顶层);
gtk_窗口设置默认大小(gtk_窗口(窗口),300250);
g_信号连接(窗口,“销毁”,gtk_主退出,空);
gtk_容器设置_边框宽度(gtk_容器(窗口),50);
/// ***
button=gtk_button_new_,带助记符(“_ClickMe”);
gtk_小部件_添加_事件(按钮、GDK_按钮_按下);
gtk_小部件_添加_事件(按钮、GDK_滚动_掩码);
///g_信号连接(按钮“点击”,gtk_主退出,空);
gtk_容器添加(gtk_容器(窗口),按钮);
/// ***
g_信号连接交换(按钮,“按钮按下事件”,g_回调(显示鼠标按下),窗口);
g_信号连接交换(按钮,“滚动事件”,g_回调(滚动回调),窗口);
/// ***
gtk_小部件_全部显示(窗口);
gtk_main();
}
gboolean scroll_回调(GtkWidget*小部件,GdkEvent*事件)
{
如果(事件->类型==GDK\u滚动)///滚动被捕获?
{
如果(event->scroll.direction==GDK\u scroll\u DOWN)///它是向下的吗?
{
g_打印(“检测到向下滚动\n”);
gtk_窗口_设置_标题(gtk_窗口(小部件),“检测到向下滚动”);
}
如果(event->scroll.direction==GDK\u scroll\u UP)///它是向上的吗?
{
g_打印(“检测到向上滚动\n”);
gtk_窗口设置标题(gtk_窗口(小部件),“检测到向上滚动”);
}
返回FALSE;
}
返回TRUE;
}
gboolean显示鼠标按下(GtkWidget*小部件,GdkEventButton*事件)
{
断言(小部件!=NULL);
如果(gtk_小部件_获取_有_窗口(小部件))
{
如果(事件->类型==GDK\u按钮\u按下)
{
g_print(“鼠标点击按钮”);
gtk_窗口_设置_标题(gtk_窗口(小部件),“点击鼠标”);
}
返回TRUE;
}
返回FALSE;
}
谢谢!到目前为止,这对我很有效。我只是不明白为什么我必须使用struct d*data=(struct d*)user\u data
而不是struct d*data=user\u data
。如果我尝试在没有(struct d*)
的情况下使用它,我会得到以下错误:main.cpp:在函数“gboolean box”中单击(GtkWidget*,GdkEvent*,gpointer)∶main.cpp:16:22:错误:从“gpointer{aka void*}”到“d*”[-fppermissive]struct d*data=user\u数据的转换无效代码>哦,如果你正在用C++编译,那么你需要的是<代码>(StuttD*) Case.GTK通常用C编译,GTKMM是C++。(这也解释了为什么你用bool
而不是gboolean
)。谁让你在Gtk中使用.cpp
的?好的,我明白了。没有人告诉我使用.CPP我只是使用它,因为在我开始GTK之前,我总是用C++编写我的程序。我开始学习lea
#include <gtk/gtk.h>
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event );
gboolean show_mouse_pressed ( GtkWidget *widget, GdkEventButton *event );
int main ( void )
{
GtkWidget *window;
GtkWidget *button;
gtk_init( NULL, NULL );
/// ***
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_default_size( GTK_WINDOW( window ), 300, 250 );
g_signal_connect( window, "destroy", gtk_main_quit, NULL );
gtk_container_set_border_width( GTK_CONTAINER( window ), 50 );
/// ***
button = gtk_button_new_with_mnemonic( "_Click me" );
gtk_widget_add_events( button, GDK_BUTTON_PRESS );
gtk_widget_add_events( button, GDK_SCROLL_MASK );
///g_signal_connect( button, "clicked", gtk_main_quit, NULL );
gtk_container_add( GTK_CONTAINER( window ), button );
/// ***
g_signal_connect_swapped( button, "button_press_event", G_CALLBACK( show_mouse_pressed ), window );
g_signal_connect_swapped( button, "scroll_event", G_CALLBACK( scroll_callback ), window );
/// ***
gtk_widget_show_all( window );
gtk_main();
}
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event )
{
if ( event->type == GDK_SCROLL ) /// Scroll was Catched ?
{
if ( event->scroll.direction == GDK_SCROLL_DOWN ) /// It is down?
{
g_print( "Scroll-Down Detected\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "Scroll-Down Detected" );
}
if ( event->scroll.direction == GDK_SCROLL_UP ) /// It is up?
{
g_print( "Scroll-UP Detected\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "Scroll-UP Detected" );
}
return FALSE;
}
return TRUE;
}
gboolean show_mouse_pressed ( GtkWidget *widget, GdkEventButton *event )
{
assert ( widget != NULL );
if ( gtk_widget_get_has_window ( widget ) )
{
if ( event->type == GDK_BUTTON_PRESS )
{
g_print( "The mouse clicked the button\n" );
gtk_window_set_title( GTK_WINDOW( widget ), "The mouse was Clicked" );
}
return TRUE;
}
return FALSE;
}