czosnek17 Temat założony przez niniejszego użytkownika |
[GTK+] Problem z funkcjami » 2012-08-02 21:30:46 Witam. Zacząłem pisać gui do gry konsolowej. Jedna z funkcji ma rysować menu. Nie rysuję na początku programu, bo będzie potrzebne w różnych momentach. Gdy próbuję wywołać funkcję w ten sposób(bez zdarzeń, przekazuję strukturę): rysujmenu( & sss ); mam błąd: cannot convert 'struktura*' to 'void**' for argument '1' to 'void rysujmenu(void**)' W gtk nie da się tak? Więc spróbowałem inaczej. Utworzyłem przycisk, a po jego kliknięciu wywołana jest funkcja rysujmenu. Otrzymałem "Wystąpił problem z aplikacją szablon gtk.exe i zostanie ona zamknięta. Przepraszamy za kłopoty." Zaznaczam te funkcje komentarzami //<<<< #include <gtk/gtk.h>
struct struktura { GtkWidget * sokno; GtkWidget * svbox; GtkWidget * start; GtkWidget * zasady; GtkWidget * statystyki; GtkWidget * ogrze; GtkWidget * wwyjdz; };
void niszczenie( GtkWidget * widget, gpointer * dane ) { struct struktura * sss; sss =( struct struktura * ) dane; gtk_widget_destroy( sss->statystyki ); gtk_widget_destroy( sss->zasady ); gtk_widget_destroy( sss->ogrze ); gtk_widget_destroy( sss->wwyjdz ); gtk_widget_destroy( sss->start ); }
void rysujmenu( gpointer * dane ) { struct struktura * sss; sss =( struct struktura * ) dane; gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->start, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->zasady, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->statystyki, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->ogrze, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->wwyjdz, TRUE, TRUE, 2 ); }
int main( int argc, char * argv[] ) { struct struktura sss; GtkWidget * okno; GtkWidget * vbox; GtkWidget * pstart; GtkWidget * pzasady; GtkWidget * pstatystyki; GtkWidget * pogrze; GtkWidget * wyjdz; GtkWidget * pokaz; gtk_init( & argc, & argv ); okno = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_position( GTK_WINDOW( okno ), GTK_WIN_POS_CENTER ); gtk_window_set_default_size( GTK_WINDOW( okno ), 250, 250 ); gtk_window_set_title( GTK_WINDOW( okno ), "Gra 1.0" ); gtk_container_set_border_width( GTK_CONTAINER( okno ), 5 ); vbox = gtk_vbox_new( FALSE, 1 ); gtk_container_add( GTK_CONTAINER( okno ), vbox ); pstart = gtk_button_new_with_label( "Start" ); pzasady = gtk_button_new_with_label( "Zasady" ); pstatystyki = gtk_button_new_with_label( "Statystyki" ); pogrze = gtk_button_new_with_label( "O grze" ); wyjdz = gtk_button_new_with_label( "Wyjdź" ); pokaz = gtk_button_new_with_label( "pokaz" ); gtk_box_pack_start( GTK_BOX( vbox ), pokaz, TRUE, TRUE, 2 ); sss.sokno = okno; sss.svbox = vbox; sss.start = pstart; sss.zasady = pzasady; sss.statystyki = pstatystyki; sss.ogrze = pogrze; sss.wwyjdz = wyjdz; rysujmenu( & sss ); g_signal_connect( G_OBJECT( pokaz ), "clicked", G_CALLBACK( rysujmenu ), & sss ); g_signal_connect( G_OBJECT( pstart ), "clicked", G_CALLBACK( niszczenie ), & sss ); g_signal_connect( G_OBJECT( wyjdz ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); g_signal_connect( G_OBJECT( okno ), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); gtk_widget_show_all( okno ); gtk_main(); return 0; }
|
|
Badman |
» 2012-08-03 08:08:31 Spójrz Nowe opisy wokół Gtk+, jest tam punkt typy danych. Zobacz czym jest gpointer ?
Dlatego zmień:
void niszczenie( GtkWidget * widget, gpointer * dane )
na
void niszczenie( GtkWidget * widget, gpointer dane )
|
|
czosnek17 Temat założony przez niniejszego użytkownika |
» 2012-08-03 17:50:08 Miałem problem z funkcją rysujmenu, ale w niej też usunąłem gwiazdkę i działa. Tylko jak wywołuję ją po kliknięciu na przycisk, to dalej jest "Wystąpił problem z aplikacją szablon gtk.exe i zostanie ona zamknięta". |
|
Badman |
» 2012-08-04 13:29:08 Wizualnie jest ok :)
Wieczorem jak będę maił dostęp do kompilatora zabaczę w czym problem...
|
|
Badman |
» 2012-08-05 10:59:01 Miałem problem z funkcją rysujmenu, ale w niej też usunąłem gwiazdkę i działa. |
To jak wiesz co to dało, dlaczego wcześniej był błąd ? Program się wykrzacza bo odwołuje się nie pod ten adres co należy. Początkowo również nie wiedziałem co jest grane. Pomogło wypisanie adresów, proponuję Ci w takich przypadkach używać, któreś z funkcji *print* z argumentem %p. Wyszło, że adres sss->svbox w funkcji rysuj jest zupełnie inny niż ten w main, i od razu mnie oświeciło: skojarzenie sygnału z kontrolką wywołuje określoną funkcje przekazując argumenty i ich ilość zależną od rodzaju sygnału, oraz na końcu argument podany przez użytkownika (userdata). Zatem po kliknięciu na przycisk Pokaż, funkcja rysuj otrzymuje w parametrze dane wskaźnik na kontrolkę pokaz. Aby mogła otrzymać dane użytkownika należy ją zdefiniować: void niszczenie( GtkWidget * widget, gpointer dane ) Moim zdaniem funkcja niszczenie nie powinna niszczyć kontrolek, wiąże się to ze zwalnianiem pamięci zajmowanej przez kontrolki, więc już nie można ich wyświetlić, lepiej inaczej nazwać tą funkcję i użyć funkcji ukrywania kontrolki gtk_widget_hide. #include <gtk/gtk.h>
struct struktura { GtkWidget * sokno; GtkWidget * svbox; GtkWidget * start; GtkWidget * zasady; GtkWidget * statystyki; GtkWidget * ogrze; GtkWidget * wwyjdz; };
void niszczenie( GtkWidget * widget, gpointer dane ) { struct struktura * sss; sss =( struct struktura * ) dane; gtk_widget_hide( sss->statystyki ); gtk_widget_hide( sss->zasady ); gtk_widget_hide( sss->ogrze ); gtk_widget_hide( sss->wwyjdz ); gtk_widget_hide( sss->start ); }
void rysujmenu( GtkButton * przycisk, gpointer dane ) { struct struktura * sss; sss =( struct struktura * ) dane; g_print( "sss->svbox %p\n", sss->svbox ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->start, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->zasady, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->statystyki, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->ogrze, TRUE, TRUE, 2 ); gtk_box_pack_start( GTK_BOX( sss->svbox ), sss->wwyjdz, TRUE, TRUE, 2 ); gtk_widget_show_all( sss->svbox ); }
int main( int argc, char * argv[] ) { struct struktura sss; GtkWidget * okno; GtkWidget * vbox; GtkWidget * pstart; GtkWidget * pzasady; GtkWidget * pstatystyki; GtkWidget * pogrze; GtkWidget * wyjdz; GtkWidget * pokaz; gtk_init( & argc, & argv ); okno = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_position( GTK_WINDOW( okno ), GTK_WIN_POS_CENTER ); gtk_window_set_default_size( GTK_WINDOW( okno ), 250, 250 ); gtk_window_set_title( GTK_WINDOW( okno ), "Gra 1.0" ); gtk_container_set_border_width( GTK_CONTAINER( okno ), 5 ); vbox = gtk_vbox_new( FALSE, 1 ); gtk_container_add( GTK_CONTAINER( okno ), vbox ); pstart = gtk_button_new_with_label( "Start" ); pzasady = gtk_button_new_with_label( "Zasady" ); pstatystyki = gtk_button_new_with_label( "Statystyki" ); pogrze = gtk_button_new_with_label( "O grze" ); wyjdz = gtk_button_new_with_label( "Wyjdź" ); pokaz = gtk_button_new_with_label( "pokaz" ); gtk_box_pack_start( GTK_BOX( vbox ), pokaz, TRUE, TRUE, 2 ); sss.sokno = okno; sss.svbox = vbox; g_print( "vbox %p\n", vbox ); g_print( "sss.svbox %p\n", sss.svbox ); sss.start = pstart; sss.zasady = pzasady; sss.statystyki = pstatystyki; sss.ogrze = pogrze; sss.wwyjdz = wyjdz; g_signal_connect( G_OBJECT( pokaz ), "clicked", G_CALLBACK( rysujmenu ), & sss ); g_signal_connect( G_OBJECT( pstart ), "clicked", G_CALLBACK( niszczenie ), & sss ); g_signal_connect( G_OBJECT( wyjdz ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); g_signal_connect( G_OBJECT( okno ), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); gtk_widget_show_all( okno ); gtk_main(); return 0; }
|
|
czosnek17 Temat założony przez niniejszego użytkownika |
» 2012-08-06 19:33:49 Działa, dzięki! Teraz próbuję z funkcji po kliknięciu przejść do funkcji, przekazując strukturę, ale jakoś nie wychodzi, po kliknięciu na przycisk start "wystąpił problem z aplikacją..." Z tej funkcji: void rysujmenu( GtkWidget * przycisk, gpointer dane ) { struct struktura * sss; sss =( struct struktura * ) dane; g_signal_connect( G_OBJECT( sss->start ), "clicked", G_CALLBACK( test ), & sss ); gtk_widget_show_all( kontener ); }
Chcę przejść do: void test( GtkWidget * przycisk, gpointer dane ) { struct struktura * sss; sss =( struct struktura * ) dane; }
Ten sposób nie działa, więc jak powiniennem to zrobić? |
|
Badman |
» 2012-08-07 07:13:41 No i nie może działać ! Nadal nie rozumiesz wskaźników !
void rysujmenu( GtkWidget * przycisk, gpointer dane ) { struct struktura * sss; sss =( struct struktura * ) dane; g_signal_connect( G_OBJECT( sss->start ), "clicked", G_CALLBACK( test ), & sss ); gtk_widget_show_all( kontener ); }
Zmienna sss w funkcji rysujmenu jest zmienną wskaźnikową, więc twój zapis w funkcji g_signal_connect: &sss zamiast adresu przekazuje zawartość na co wskazuje zmienna wsakaźnikowa sss.
Poprawny zapis to:
g_signal_connect( G_OBJECT( sss->start ), "clicked", G_CALLBACK( test ), sss );
W sumie równie dobrze może być:
g_signal_connect( G_OBJECT( sss->start ), "clicked", G_CALLBACK( test ), dane );
ponieważ sss i dane wskazują na ten sam adres.
|
|
« 1 » |