Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[GTK+] Problem z funkcjami

Ostatnio zmodyfikowano 2012-08-07 07:13
Autor Wiadomość
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 //<<<<
C/C++
#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;
}
P-61616
Badman
» 2012-08-03 08:08:31
Spójrz Nowe opisy wokół Gtk+, jest tam punkt typy danych. Zobacz czym jest gpointer ?
Dlatego zmień:
C/C++
void niszczenie( GtkWidget * widget, gpointer * dane )
 
na
C/C++
void niszczenie( GtkWidget * widget, gpointer dane )


P-61621
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".
P-61662
Badman
» 2012-08-04 13:29:08
Wizualnie jest ok :)
Wieczorem jak będę maił dostęp do kompilatora zabaczę w czym problem...
P-61716
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.

C/C++
#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 ); // Na potrzeby testowania :0
   
    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;
   
    /* wyswietlenie na konsole adresow w celu werefikacji czy wskazuja na to samo */
    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;
   
    //rysujmenu( NULL, & 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;
}
P-61778
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:
C/C++
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:
C/C++
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ć?
P-61865
Badman
» 2012-08-07 07:13:41
No i nie może działać ! Nadal nie rozumiesz wskaźników !
C/C++
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.
P-61907
« 1 »
  Strona 1 z 1