Results 1 to 1 of 1
Hello everyone, I tried to create a simple widget derived from the one that already existed. I follow the instruction from Foundation of GTK+ Development book and also this link ...
- 07-01-2009 #1Just Joined!
- Join Date
- Nov 2008
- Posts
- 3
GTK+ errors invalid conversion from ‘GType’ to ‘GtkSignalRunType
Hello everyone, I tried to create a simple widget derived from the one that already existed. I follow the instruction from Foundation of GTK+ Development book and also this link :
mathematik.uni-ulm.de/help/gtk+-1.1.3/gtk_tut-24.html#ss24.3]GTK]GTK]GTK Tutorial: Writing Your Own Widgets
I've been studying GTK+ for a month. I recognized that there are so many different styles between different GTK+ programmer. I just want to ask which one is more toward to the standard of GTK+. The one from that website or the one from Andrew's book( Foundation of GTK+ Development ).
Here is my code after edited follow the book instruction :
And I got this error :Code:#include <glib.h> #include <glib-object.h> #include <gtk/gtkentry.h> #include <gtk/gtkvbox.h> #include <gtk/gtktable.h> #include <gtk/gtktogglebutton.h> #include <gtk/gtk.h> G_BEGIN_DECLS #define TICTACTOE_TYPE ( tictactoe_get_type() ) #define TICTACTOE( obj ) ( G_TYPE_CHECK_INSTANCE_CAST( ( obj ), tictactoe_get_type(), Tictactoe ) ) #define TICTACTOE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( ( klass ), TICTACTOE_TYPE, TictactoeClass ) ) #define IS_TICTACTOE( obj ) ( G_TYPE_CHECK_INSTANCE_TYPE( ( obj ), TICTACTOE_TYPE ) ) #define IS_TICTACTOE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE( ( klass ), TICTACTOE_TYPE ) ) struct Tictactoe { GtkVBox vbox; GtkWidget *buttons[ 3 ][ 3 ]; }; struct TictactoeClass { GtkVBoxClass parent_class; void ( *tictactoe )( Tictactoe *ttt ); }; GType tictactoe_get_type( void )G_GNUC_CONST; GtkWidget* tictactoe_new( void ); G_END_DECLS #define TICTACTOE_GET_PRIVATE( obj ) ( G_TYPE_INSTANCE_GET_PRIVATE( ( obj ), TICTACTOE_TYPE, TictactoePrivate ) ) static void tictactoe_class_init( TictactoeClass *klass ); static void tictactoe_init( Tictactoe *ttt ); static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt ); static void tictactoe_clear( Tictactoe *ttt ); enum { TICTACTOE_SIGNAL, LAST_SIGNAL }; static unsigned tictactoe_signals[ LAST_SIGNAL ] = { 0 }; GType tictactoe_get_type( void ) { static GType vbox_type = 0; if( !vbox_type ) { static const GTypeInfo vbox_info = { sizeof( TictactoeClass ), NULL, NULL, ( GClassInitFunc )tictactoe_class_init, NULL, NULL, sizeof( Tictactoe ), 0, ( GInstanceInitFunc )tictactoe_init, }; vbox_type = g_type_register_static( GTK_TYPE_VBOX, "Tictactoe", &vbox_info, static_cast< GTypeFlags >( 0 ) ); } return vbox_type; } static void tictactoe_class_init( TictactoeClass *klass ) { GObjectClass *gobject_class = G_OBJECT_CLASS( klass ); tictactoe_signals[ TICTACTOE_SIGNAL ] = gtk_signal_new( "game-played", G_TYPE_FROM_CLASS( klass ), static_cast< GSignalFlags >( G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION ), G_STRUCT_OFFSET( TictactoeClass, tictactoe ), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); } static void tictactoe_init( Tictactoe *ttt ) { GtkWidget *table = gtk_table_new( 3, 3, true ); gtk_container_add( GTK_CONTAINER( ttt ), table ); gtk_widget_show( table ); for( int i = 0; i < 3; ++i ) { for( int j = 0; j < 3; ++j ) { ttt->buttons[ i ][ j ] = gtk_toggle_button_new(); gtk_table_attach_defaults( GTK_TABLE( table ), ttt->buttons[ i ][ j ], i, i + 1, j, j + 1 ); gtk_signal_connect( GTK_OBJECT( ttt->buttons[ i ][ j ] ), "toggled", G_CALLBACK( tictactoe_toggle ), static_cast< gpointer >( ttt ) ); gtk_widget_set_size_request( ttt->buttons[ i ][ j ], 20, 20 ); gtk_widget_show( ttt->buttons[ i ][ j ] ); } } } GtkWidget* tictactoe_new () { return GTK_WIDGET( g_object_new( tictactoe_get_type(), NULL ) ); } static void tictactoe_clear( Tictactoe *ttt ) { for( int i = 0; i < 3; ++i ) { for( int j = 0; j < 3; ++j ) { gtk_signal_handler_block_by_data( GTK_OBJECT( ttt->buttons[ i ][ j ] ), ttt ); gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( ttt->buttons[ i ][ j ]), false ); gtk_signal_handler_unblock_by_data( GTK_OBJECT( ttt->buttons[ i ][ j ]), ttt ); } } } static void tictactoe_toggle( GtkWidget *widget, Tictactoe *ttt ) { static int rwins[ 8][ 3 ] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 }, { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 } }; static int cwins[ 8 ][ 3 ] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 }, { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 }, { 0, 1, 2 }, { 2, 1, 0 } }; int success, found; for( int k = 0; k < 8; ++k ) { success = TRUE; found = FALSE; for( int i=0; i < 3; ++i ) { success = success && GTK_TOGGLE_BUTTON( ttt->buttons[ rwins[ k ][ i ] ][ cwins[ k ][ i ]] )->active; found = found || ttt->buttons[ rwins[ k ][ i ] ][ cwins[ k ][ i ] ] == widget; } if( success && found ) { gtk_signal_emit( GTK_OBJECT( ttt ), tictactoe_signals[ TICTACTOE_SIGNAL ] ); break; } } } /* Invoked when a row, column or diagonal is completed */ void win( GtkWidget *widget, gpointer data ) { g_print( "Yay!\n" ); tictactoe_clear( TICTACTOE( widget ) ); } int main( int argc, char *argv[] ) { gtk_init( &argc, &argv ); GtkWidget *window; GtkWidget *ttt; window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_title( GTK_WINDOW( window ), "Aspect Frame" ); gtk_signal_connect( GTK_OBJECT (window), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); gtk_container_border_width( GTK_CONTAINER( window ), 10 ); /* Create a new Tictactoe widget */ ttt = tictactoe_new(); gtk_container_add( GTK_CONTAINER( window ), ttt ); gtk_widget_show( ttt ); /* And attach to its "tictactoe" signal */ gtk_signal_connect( GTK_OBJECT (ttt), "game-played", G_CALLBACK( win ), NULL ); gtk_widget_show( window ); gtk_main (); return 0; }
Comparing with the one from the book which worked fine :Code:||=== Fun With File ^_^, Debug ===| /main.cpp||In function ‘void tictactoe_class_init(TictactoeClass*)’:| /main.cpp|96|error: invalid conversion from ‘GType’ to ‘GtkSignalRunType’| /main.cpp|96|error: invalid conversion from ‘void (*)(GClosure*, GValue*, guint, const GValue*, void*, void*)’ to ‘guint’| /main.cpp|85|warning: unused variable ‘gobject_class’| ||=== Build finished: 2 errors, 1 warnings ===|
The error implied that something wrong with gtk_signal_new(...) parameters. But when I compared those two( one from the text-book vs the one that I editted ), they're not different in logicCode:#include <glib.h> #include <glib-object.h> #include <gtk/gtkentry.h> #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <stdlib.h> #include <math.h> G_BEGIN_DECLS #define MY_IP_ADDRESS_TYPE ( my_ip_address_get_type() ) #define MY_IP_ADDRESS( obj ) ( G_TYPE_CHECK_INSTANCE_CAST( ( obj ), MY_IP_ADDRESS_TYPE, MyIPAddress ) ) #define MY_IP_ADDRESS_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( ( klass ), MY_IP_ADDRESS_TYPE, MyIPAddressClass ) ) #define IS_MY_IP_ADDRESS(obj) ( G_TYPE_CHECK_INSTANCE_TYPE( ( obj ), MY_IP_ADDRESS_TYPE ) ) #define IS_MY_IP_ADDRESS_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE( ( klass ), MY_IP_ADDRESS_TYPE ) ) struct MyIPAddress { GtkEntry entry; }; struct MyIPAddressClass { GtkEntryClass parent_class; void ( *ip_changed )( MyIPAddress *ipaddress ); }; GType my_ip_address_get_type ( void )G_GNUC_CONST; GtkWidget* my_ip_address_new ( void ); gchar* my_ip_address_get_address( MyIPAddress *ipaddress ); void my_ip_address_set_address( MyIPAddress *ipaddress, int address[ 4 ] ); G_END_DECLS #define MY_IP_ADDRESS_GET_PRIVATE( obj ) ( G_TYPE_INSTANCE_GET_PRIVATE( ( obj ), MY_IP_ADDRESS_TYPE, MyIPAddressPrivate ) ) typedef struct _MyIPAddressPrivate MyIPAddressPrivate; struct _MyIPAddressPrivate { unsigned address[ 4 ]; }; enum { CHANGED_SIGNAL, LAST_SIGNAL }; enum { PROP_0, PROP_IP1, PROP_IP2, PROP_IP3, PROP_IP4 }; static void my_ip_address_class_init( MyIPAddressClass* ); static void my_ip_address_init( MyIPAddress* ); static void my_ip_address_get_property( GObject*, unsigned int, GValue*, GParamSpec* ); static void my_ip_address_set_property( GObject*, unsigned int, const GValue*, GParamSpec* ); static void my_ip_address_render( MyIPAddress* ); static void my_ip_address_move_cursor( GObject*, GParamSpec* ); static bool my_ip_address_key_pressed( GtkEntry*, GdkEventKey* ); static int my_ip_address_signals[ LAST_SIGNAL ] = { 0 }; /* Get a GType that corresponds to MyIPAddress. The first time this function is * called (on object instantiation), the type is registered. */ GType my_ip_address_get_type( void ) { static GType entry_type = 0; if( !entry_type ) { static const GTypeInfo entry_info = { sizeof( MyIPAddressClass ), NULL, NULL, ( GClassInitFunc )my_ip_address_class_init, NULL, NULL, sizeof( MyIPAddress ), 0, ( GInstanceInitFunc )my_ip_address_init, }; entry_type = g_type_register_static( GTK_TYPE_ENTRY, "MyIPAddress", &entry_info, static_cast< GTypeFlags >( 0 ) ); } return entry_type; } /* Initialize the MyIPAddressClass class by overriding standard functions, * registering a private class and setting up signals and properties. */ static void my_ip_address_class_init( MyIPAddressClass *klass ) { GObjectClass *gobject_class = G_OBJECT_CLASS( klass ); /* Override the standard functions for setting and retrieving properties. */ gobject_class->set_property = my_ip_address_set_property; gobject_class->get_property = my_ip_address_get_property; /* Add MyIPAddressPrivate as a private data class of MyIPAddressClass. */ g_type_class_add_private( klass, sizeof( MyIPAddressPrivate ) ); /* Register the ip-changed signal, which will be emitted when the ip changes. */ my_ip_address_signals[ CHANGED_SIGNAL ] = g_signal_new( "ip-changed", G_TYPE_FROM_CLASS( klass ), static_cast< GSignalFlags >( G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION ), G_STRUCT_OFFSET( MyIPAddressClass, ip_changed ), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); /* Register four GObject properties, one for each ip address number. */ g_object_class_install_property( gobject_class, PROP_IP1, g_param_spec_int( "ip-number-1", "IP Address Number 1", "The first IP address number", 0, 255, 0, static_cast< GParamFlags >( G_PARAM_READWRITE ) ) ); g_object_class_install_property( gobject_class, PROP_IP2, g_param_spec_int( "ip-number-2", "IP Address Number 2", "The second IP address number", 0, 255, 0, static_cast< GParamFlags >( G_PARAM_READWRITE ) ) ); g_object_class_install_property( gobject_class, PROP_IP3, g_param_spec_int( "ip-number-3", "IP Address Number 3", "The third IP address number", 0, 255, 0, static_cast< GParamFlags >( G_PARAM_READWRITE ) ) ); g_object_class_install_property( gobject_class, PROP_IP4, g_param_spec_int( "ip-number-4", "IP Address Number 1", "The fourth IP address number", 0, 255, 0, static_cast< GParamFlags >( G_PARAM_READWRITE ) ) ); } /* This function is called when the programmer gives a new value for a widget * property with g_object_set(). */ static void my_ip_address_set_property( GObject *object, unsigned prop_id, const GValue *value, GParamSpec *pspec ) { MyIPAddress *ipaddress = MY_IP_ADDRESS( object ); int address[ 4 ] = { -1, -1, -1, -1 }; switch( prop_id ) { case PROP_IP1: address[ 0 ] = g_value_get_int( value ); my_ip_address_set_address( ipaddress, address ); break; case PROP_IP2: address[ 1 ] = g_value_get_int( value ); my_ip_address_set_address( ipaddress, address ); break; case PROP_IP3: address[ 2 ] = g_value_get_int( value ); my_ip_address_set_address( ipaddress, address ); break; case PROP_IP4: address[ 3 ] = g_value_get_int( value ); my_ip_address_set_address( ipaddress, address ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); break; } } /* This function is called when the programmer requests the value of a widget * property with g_object_get(). */ static void my_ip_address_get_property( GObject *object, unsigned prop_id, GValue *value, GParamSpec *pspec ) { MyIPAddress *ipaddress = MY_IP_ADDRESS( object ); MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE( ipaddress ); switch( prop_id ) { case PROP_IP1 : g_value_set_int( value, priv->address[ 0 ] ); break; case PROP_IP2 : g_value_set_int( value, priv->address[ 1 ] ); break; case PROP_IP3 : g_value_set_int( value, priv->address[ 2 ] ); break; case PROP_IP4 : g_value_set_int( value, priv->address[ 3 ] ); break; default : G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec ); break; } } /* Initialize the actual MyIPAddress widget. This function is used to setup * the initial view of the widget and set necessary properties. */ static void my_ip_address_init (MyIPAddress *ipaddress) { MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE( ipaddress ); PangoFontDescription *fd; for( unsigned i = 0; i < 4; ++i ) priv->address[ i ] = 0; fd = pango_font_description_from_string( "Monospace" ); gtk_widget_modify_font( GTK_WIDGET( ipaddress ), fd ); my_ip_address_render( ipaddress ); pango_font_description_free( fd ); /* The key-press-event signal will be used to filter out certain keys. We will * also monitory the cursor-position property so it can be moved correctly. */ g_signal_connect( G_OBJECT( ipaddress ), "key-press-event", G_CALLBACK( my_ip_address_key_pressed ), NULL ); g_signal_connect( G_OBJECT( ipaddress ), "notify::cursor-position", G_CALLBACK( my_ip_address_move_cursor ), NULL ); } /* Create and return a new instance of the MyIPAddress widget. */ GtkWidget* my_ip_address_new() { return GTK_WIDGET( g_object_new( my_ip_address_get_type(), NULL ) ); } /* Return a string that represents the currently displayed IP address. */ char* my_ip_address_get_address( MyIPAddress *ipaddress ) { MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE( ipaddress ); return g_strdup_printf( "%d.%d.%d.%d", priv->address[ 0 ], priv->address[ 1 ], priv->address[ 2 ], priv->address[ 3 ] ); } /* Set the content of the IP address. Ignore any values that are out of bounds * so the programmer can provide a negative value for fields not to change. */ void my_ip_address_set_address( MyIPAddress *ipaddress, int address[ 4 ] ) { MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE( ipaddress ); for( unsigned i = 0; i < 4; ++i ) { if( address[ i ] >= 0 && address[ i ] <= 255 ) { priv->address[ i ] = address[ i ]; } } my_ip_address_render( ipaddress ); g_signal_emit_by_name( ( gpointer ) ipaddress, "ip-changed" ); } /* Render the current content of the IP address in the GtkEntry widget. */ static void my_ip_address_render( MyIPAddress *ipaddress ) { MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE( ipaddress ); GString *text; /* Create a string that displays the IP address content, adding spaces if a * number cannot fill three characters. */ text = g_string_new( NULL ); for( unsigned i = 0; i < 4; i++ ) { gchar *temp = g_strdup_printf( "%3i.", priv->address[ i ] ); text = g_string_append( text, temp ); g_free( temp ); } /* Remove the trailing decimal place and add the string to the GtkEntry. */ text = g_string_truncate( text, 15 ); gtk_entry_set_text( GTK_ENTRY( ipaddress ), text->str ); g_string_free( text, true ); } /* Force the cursor to always be at the end of one of the four numbers. */ static void my_ip_address_move_cursor( GObject *entry, GParamSpec *spec ) { int cursor = gtk_editable_get_position( GTK_EDITABLE( entry ) ); if( cursor <= 3 ) gtk_editable_set_position( GTK_EDITABLE( entry ), 3 ); else if( cursor <= 7 ) gtk_editable_set_position( GTK_EDITABLE( entry ), 7 ); else if( cursor <= 11 ) gtk_editable_set_position( GTK_EDITABLE( entry ), 11 ); else gtk_editable_set_position( GTK_EDITABLE( entry ), 15 ); } /* Handle key presses of numbers, tabs, backspaces and returns. */ static bool my_ip_address_key_pressed( GtkEntry *entry, GdkEventKey *event ) { MyIPAddressPrivate *priv = MY_IP_ADDRESS_GET_PRIVATE (entry); guint k = event->keyval; int cursor, value; /* If the key is an integer, append the new number to the address. This is only * done if the resulting number will be less than 255. */ if( ( k >= GDK_0 && k <= GDK_9 ) || ( k >= GDK_KP_0 && k <= GDK_KP_9 ) ) { cursor = floor (gtk_editable_get_position( GTK_EDITABLE( entry ) ) / 4 ); value = g_ascii_digit_value( event->string[ 0 ] ); if( ( priv->address[ cursor ] == 25 ) && ( value > 5 ) ) return TRUE; if( priv->address[ cursor ] < 26 ) { priv->address[ cursor ] *= 10; priv->address[ cursor ] += value; my_ip_address_render( MY_IP_ADDRESS( entry ) ); gtk_editable_set_position( GTK_EDITABLE( entry ), ( 4 * cursor ) + 3 ); g_signal_emit_by_name( static_cast< gpointer >( entry ), "ip-changed" ); } } /* Move to the next number or wrap around to the first. */ else if( k == GDK_Tab ) { cursor = ( floor( gtk_editable_get_position( GTK_EDITABLE( entry ) ) / 4 ) + 1 ); gtk_editable_set_position( GTK_EDITABLE( entry ), ( 4 * ( cursor % 4 ) ) + 3 ); } /* Delete the last digit of the current number. This just divides the number by * 10, relying on the fact that any remainder will be ignored. */ else if( k == GDK_BackSpace ) { cursor = floor( gtk_editable_get_position( GTK_EDITABLE( entry ) ) / 4 ); priv->address[ cursor ] /= 10; my_ip_address_render( MY_IP_ADDRESS( entry ) ); gtk_editable_set_position( GTK_EDITABLE( entry ), ( 4 * cursor ) + 3 ); g_signal_emit_by_name( static_cast< gpointer >( entry ), "ip-changed" ); } /* Activate the GtkEntry widget, which corresponds to the activate signal. */ else if( ( k == GDK_Return ) || ( k == GDK_KP_Enter ) ) gtk_widget_activate( GTK_WIDGET( entry ) ); return TRUE; } static void init_main_window( GtkWidget *&window ); static void ip_address_changed( MyIPAddress* ); int main( int argc, char *argv[] ) { gtk_init( &argc, &argv ); GtkWidget *window, *ipaddress; int address[ 4 ] = { 1, 20, 35, 255 }; init_main_window( window ); ipaddress = my_ip_address_new(); my_ip_address_set_address( MY_IP_ADDRESS( ipaddress ), address ); g_signal_connect( G_OBJECT( ipaddress ), "ip-changed", G_CALLBACK( ip_address_changed ), NULL ); gtk_container_add( GTK_CONTAINER( window ), ipaddress ); gtk_widget_show_all( window ); gtk_main(); return 0; } /* When the IP address is changed, print the new value to the screen. */ static void ip_address_changed( MyIPAddress *ipaddress ) { char *address = my_ip_address_get_address( ipaddress ); g_print( "%s\n", address ); g_free( address ); } static void init_main_window( GtkWidget *&window ) { window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_title( GTK_WINDOW( window ), "GtkIPAddress" ); gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); g_signal_connect( G_OBJECT( window ), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); }
! All I meaned is this function :
Could anyone give me a hint what did I do wrong ? Thanks in advance !Code:static void tictactoe_class_init( TictactoeClass *klass ) { GObjectClass *gobject_class = G_OBJECT_CLASS( klass ); tictactoe_signals[ TICTACTOE_SIGNAL ] = gtk_signal_new( "game-played", G_TYPE_FROM_CLASS( klass ), static_cast< GSignalFlags >( G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION ), G_STRUCT_OFFSET( TictactoeClass, tictactoe ), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); }


Reply With Quote