Bonjour à tous,
Je voudrais savoir si il est possible en GTK+ de cacher certaines lettres d'un label par un caractère comme "*".
Merci
Version imprimable
Bonjour à tous,
Je voudrais savoir si il est possible en GTK+ de cacher certaines lettres d'un label par un caractère comme "*".
Merci
Bah dans un label, il suffit d'utiliser gtk_set_label() ;)
Tu gardes le mot de passe réel en mémoire, mais tu affiches que des * :)
Merci de ta réponse, mais comment savoir le bon nombre de "*" à afficher, c'est à dire le nombre de lettres que contient le mot que je veux cacher ? 8O
Tu récupères le contenu du label dans un string, et tu utilises strlen ;)
=>
Code:
1
2
3
4
5
6
7
8
9
10 int length, i; char* text; text = gtk_label_get_text(label); length= strlen(text); for(i=0 ; i<length; i++)text[i]='*'; gtk_label_set_text(label, text);
Merci bien, je ne connaissais pas la fonction pour récupérer le texte du label. Peux tu me dire où tu l'as trouvé, sur la doc (pas trouvé) ou ailleurs ?
Serais tu aussi par hazard, comment faire apparaitre une boite de dialogue durant quelques secondes, puis la fermer automatiquement ?
Pas dans la doc ?
Tu rigoles ? ^^
http://man.chinaunix.net/develop/GTK.../GtkLabel.html
Et puis de toute facon le gros avantage de GTK, à mon gout, c'est que les fonctions sont tout de même super intuitive.
Tu veux récupérer du texte dans un label, bah tu fait gtk_label pour acceder aux fonctions du label, puis get_text pour le prendre, et set_text pour le changer.
Pas bien compliqué tout de même ;)
Pour la pop up, je te conseille de passer par les tutos GTK disponibles ici même, qui sont trés largement suffisant pour maitriser les bases.
Afficher une pop up ne devrait pas te poser trop de probleme, aprés pour la fermer aprés un certain temps, bah tu utilises un sleep, ca se trouve également super facilement sur la toile !
Essayes de trouver tout de même avant de demander, y'a quand même vachement de solutions proposées sur le net ;)
Enfin, si tu es vraiment en galère, je me ferais un plaisir de t'aider :)
Ciao !
Non, strlen ne marchera pas si ton label contient des lettres accentuées (entre autres). Utilise g_utf8_strlen qui te renverra le nombre de caractères dans ta chaîne de caractères. Si tu manipules un GtkEntry, il y a une fonction gtk_entry_set_visibility qui te permet d'avoir un mode "saisie de mot de passe". Enfin, pour faire disparaître ta fenêtre au bout de qques secondes, utilise g_timeout_add et appelle gtk_widget_destroy dans le callback qui est appelé lors le timeout s'est écoulé.
Merci à vous deux.
Je comprend pas trop ce que tu entends skip78 par "pop up" (pop en GTK+, on est d'accord ?), excuse moi si je t'agace, mais tu es sûr qu'il y'a un tuto là-dessus sur Developpez.com ?
Sinon effectivement j'utilise un GtkEntry mais je ne veux pas cacher la saisie, juste cacher les lettres d'un label.
La solution le plus simple est peut être d'utiliser la fonction indiquée par toeuf13 ?
Si c'est le nom que cela porte, alors non. Je sais par contre afficher une boite de dialogue :)
Peux tu me dire comment stp ? Je suppose que c'est quelque chose comme : void gtk_popup_new ?
Bah c'est la même chose :mouarf:
Bref je pense qu'au final tu peux te retrouver avec quelque chose du type :
(ca me fait réviser c'est trés bien ^^)
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 // Déclaration des variables : int time = 2500, num_page = 1; (...) // On crée la pop up : pAbout = gtk_message_dialog_new (GTK_WINDOW(app->MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Page %d affichee %d secondes", num_page, time); // On configure la pop up : gtk_window_set_modal(GTK_WINDOW(pAbout), TRUE); gtk_window_set_title(GTK_WINDOW(pAbout), "Affichage page"); gtk_window_set_position(GTK_WINDOW(pAbout), GTK_WIN_POS_CENTER); // On indique à la pop up qu'on veut qu'elle ferme aprés 'time' ms g_timeout_add(time, (GSourceFunc)gtk_widget_destroy, pAbout); // On affiche la pop up gtk_dialog_run(GTK_DIALOG(pAbout));
C'est bien ce que je pensais, c'est pour ça que j'ai précisé :lol:
Merci pour tout, j'ai plus de questions.
De rien :)
A noter que vu que t'as plus besoin des bouttons, tu peux les enlever :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 // Déclaration des variables : GtkWidget *pAbout; int time = 3000, num_page = 1; (...) // On crée la pop up : pAbout = gtk_message_dialog_new (GTK_WINDOW(app->MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, 0, "Page %d affichee %d secondes", num_page, time/1000); // On configure la pop up : gtk_window_set_modal(GTK_WINDOW(pAbout), TRUE); gtk_window_set_title(GTK_WINDOW(pAbout), "Affichage page"); gtk_window_set_position(GTK_WINDOW(pAbout), GTK_WIN_POS_CENTER); // On indique à la pop up qu'on veut qu'elle ferme aprés 'time' ms g_timeout_add(time, (GSourceFunc)gtk_widget_destroy, pAbout); // On affiche la pop up gtk_dialog_run(GTK_DIALOG(pAbout));
J'ai un petit problème. Mon compilateur ne m'indique rien, mais la console à coté de l'interface de mon programme en GTK+ affiche :Voici le code de la boite de dialogue :Code:gtk_widget_destroy : assertion ' GTK_IS_WIDGET (widget)' failed
Voyez-vous quelque chose d'anormal ?Code:
1
2
3
4
5
6
7
8
9
10
11 dialog = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, 0, "Bonne Lettre\n"); g_timeout_add(lenth, (GSourceFunc)gtk_widget_destroy, dialog); gtk_dialog_run(GTK_DIALOG(dialog));
Merci
Je dirais a priori que ton "data" n'est pas un GtkWindow :)
Je regarde.
Alors, je pense que si je te donne tout le code ça va être plus simple, attention je débute en GTK+, il y'a surement des fautes. J'essaye de faire le jeu du Pendu en GTK+ ;) , histoire de m'entrainer.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 #include <stdlib.h> #include <gtk/gtk.h> void search(GtkWidget *entry, gpointer data); gchar text[] = "salut"; int main (int argc, char *argv[]) { GtkWidget *main_window; GtkWidget *main_box; GtkWidget *entry; /* GtkWidget *label; */ gtk_init(&argc, &argv); /* Main Window */ { main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(main_window), 400, 600); gtk_window_set_title(GTK_WINDOW(main_window), "Pendu"); g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(gtk_main_quit), NULL); } /* Main Box */ { main_box = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(main_window), main_box); } /* Entry */ { entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(main_box), entry, FALSE, FALSE, 0); gtk_entry_set_max_length(GTK_ENTRY(entry), 1); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(search), (gpointer*)main_window); } gtk_widget_show_all(main_window); gtk_main(); return 0; } void search(GtkWidget *entry, gpointer data) { const gchar *text_enter; int i = 0; int time= 3000; GtkWidget *dialog; text_enter = gtk_entry_get_text(GTK_ENTRY(entry)); for (i = 0; text[i] != '\0'; i++) { if (text_enter[0] == text[i]) { dialog = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, 0, "Bonne Lettre\n"); g_timeout_add(time, (GSourceFunc)gtk_widget_destroy, dialog); gtk_dialog_run(GTK_DIALOG(dialog)); } } } /* Afficher le mot secret dans un label, mais utiliser une boite de dialogue pour bonne lettre ou pas */
Je suis pas sûr que le gtk_widget_destroy pendant un gtk_dialog_run soit une bonne idée. Faut peut être utiliser gtk_dialog_response pour "fermer" le dialogue.
Bon, j'ai fait pas mal de recherches dans la doc et modifié mon code, mais sans résultat concret.
Cependant d'après ce que j'ai compris comme mon dialog ne comporte aucun bouton (GTK_BUTTONS_NONE), la fonction citée au-dessus ne renverrait rien, en second paramètre il lui faut un reponse_id, qui n'existe pas pour mon type de dialog :( .
Je sais pas trop quoi faire, je pense que je vais mettre un bouton valider, ça serait plus simple et ça fonctionne bien.
SI vous avez une idée je suis preneur :)
Merci, pour vos réponses précédentes.
Re-bonjour,
Excusez moi d'encore vous déranger :? , mais j'ai un nouveau problème, et je voudrais aussi avoir vos avis.
Je viens donc de commencer à apprendre le GTK+, c'est ma première lib graphique.
J'essaye donc de coder le jeu du pendu en GTK+. Voici mon code en entier :
Mais j'ai un problème, que la lettre soit bonne ou mauvaise, le dialog_non ne cesse de s'afficher 8O , ça provient surement de la deuxième condition mais je vois pas ce qui cloche. Voyez-vous d'autres problèmes dans mon code ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 #include <stdlib.h> #include <gtk/gtk.h> void search(GtkWidget *entry, gpointer data); gchar text[] = "salut"; int main (int argc, char *argv[]) { GtkWidget *main_window; GtkWidget *main_box; GtkWidget *entry; /* GtkWidget *label; */ gtk_init(&argc, &argv); /* Main Window */ { main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(main_window), 400, 600); gtk_window_set_title(GTK_WINDOW(main_window), "Pendu"); g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(gtk_main_quit), NULL); } /* Main Box */ { main_box = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(main_window), main_box); } /* Entry */ { entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(main_box), entry, FALSE, FALSE, 0); gtk_entry_set_max_length(GTK_ENTRY(entry), 1); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(search), (GtkWidget*)main_window); } gtk_widget_show_all(main_window); gtk_main(); return 0; } void search(GtkWidget *entry, gpointer data) { const gchar *text_enter; int i = 0; GtkWidget *dialog_ok; GtkWidget *dialog_non; text_enter = gtk_entry_get_text(GTK_ENTRY(entry)); while (i < 5) { if (text_enter[0] == text[i]) { dialog_ok = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Bien joue !\n Bonne lettre !\n"); gtk_dialog_run(GTK_DIALOG(dialog_ok)); gtk_widget_destroy(dialog_ok); } else { dialog_non = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Desole...\n Ce n'est pas une bonne lettre !\n"); gtk_dialog_run(GTK_DIALOG(dialog_non)); gtk_widget_destroy(dialog_non); } i++; } }
J'aimerais avoir une précision sur :le quatrième paramètre, j'ai bien le droit de faire ce cast, sinon il va bien avoir une erreur ?Code:g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(search), (GtkWidget*)main_window);
On va commencer par le commencement, tu as d'autres problemes plus profonds :)
Deja les accolades pour séparer les différentes parties dans le main, c'est trés moyen je pense.
Aprés, un truc plus spécifique à GTK, je vois que tu as voulu déclarer text en global.
Ton raisonnement à normalement été le suivant :
Je veux initialiser text dans une fonction (surement le main), et le tester dans une callback par exemple. Or je passe deja ma fenetre en argument dans la callback, qui n'en prend qu'un, donc je dois créer text en global.
=> L'astuce utilisée en GTK est de créer une structure, contenant la fenêtre elle même, et tous ses éléments, afin d'avoir accès à l'ensemble des ressources lors de chaque appel de fonction.
Ca parait pas trés important de procéder ainsi pour l'instant, mais trés vite ca devient indispensable, et si tu n'y penses pas avant, ca te promet de belles prises de tête un peu plus tard :)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 // Dans le .h : typedef struct APP { GtkWindow* window; GtkWidget* entry; gchar* text; }APP; // Dans le main : APP *app; app = (APP*)malloc(sizeof(APP)); app->window = gtk_window_new(); app->text = "salut"; app->entry = gtk_entry_new(); (...) g_signal_connect(G_OBJECT(app->entry), "activate", G_CALLBACK(search), app); // Dans le callback : void search(GtkWidget *entry, gpointer data) { APP* app = (APP*)data; // Tu fait tes opérations en utilisant app de la facon suivante : printf("text = %s\n", app->text); (...) // Par ailleurs, je préfères ne pas utiliser du tout le premier paramètre de la callback : text_enter = gtk_entry_get_text(GTK_ENTRY(app->entry)); (...) }
Par ailleurs j'ai répondu indirectement à ton interrogation sur le cast de window.
Je poursuivrais en te conseillant d'utiliser for(i=0 ; i<5 ; i++) à la place de ton while, et pour savoir ce qui va pas, de faire des tests basiques tels que l'affichage console de text et de text_entre[0].
Pour le problème que tu rencontres en tant que tel, il devrait te sauter aux yeux (je viens de tester ton code, si tu met s, il te dis une fois "ok" puis 4 fois "pas ok")
C'est donc qu'il voit bien que c'est bon, mais ta boucle est mal pensée puisqu'il y reste et affiche ensuite que c'est pas bon pour les autres lettres.
Met plutot un booleen genre :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 gboolean lettre_ok = FALSE; for(i=0 ; i<strlen(app->text) ; i++) { if (text_enter[0] == app->text[i]) lettre_ok = TRUE; } if (lettre_ok) { dialog_ok = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Bien joue !\n Bonne lettre !\n"); gtk_dialog_run(GTK_DIALOG(dialog_ok)); gtk_widget_destroy(dialog_ok); } else { dialog_non = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Desole...\n Ce n'est pas une bonne lettre !\n"); gtk_dialog_run(GTK_DIALOG(dialog_non)); gtk_widget_destroy(dialog_non); }
Ta boucle ne marchera pas si tu as des caractères accentués ;)
Merci pour toutes ces précisions :) :)
Je vais essayer de tout remettre au propre. Je vous tiens au courant.
skip78 : concernant le cast de window, j'en déduis pas tes explications qu'il est inutile puisque tu le fais dans le code de la fonction. Pourtant j'ai vu beaucoup de code avec des casts dans l'appel de la fonction callback 8O
En fait te dire que j'avais répondu à ta question était faux :)
Le cast est trés important si tu te sers directement de la variable passée en argument.
Mais je préfère faire une copie du pointeur, donc pas besoin de cast dans l'appel puisque je le fais durant la copie (app = (APP*)user_data; )
@teuf : LoL :mrgreen: => en effet, ne pas oublier de gérer l'utf8 => g_utf8_strlen à la place de strlen ;)
Ah, vu comme ca effectivement c'est ch***t (je vous entraine au pendu ;))
Comment qu'on fait pour contourner le problème ? on passe en guchar ? :aie:
Y a g_utf8_next_char qui peut être utilisé par exemple.