Bonjour,
Je suis en train de coder un mini-chat. Il y a un serveur et un ou plusieurs clients. J'utilise les sockets et les threads.
Je voudrais que l'espace, où l'utilisateur écrit, se vide une fois que le message est envoyé.
Aucun soucis quand il clique sur Envoyer, mais si il appuie sur la touche Entrée, il restera un saut de ligne après que l'espace soit vidé.
Les différentes variables :
- text_view : le fameux espace (variable globale)
- view_chat : l'espace d'affichage des messages (variable globale)
- label2 : les personnes connectées (variable globale)
Le code pour les signaux :
Le code pour l'envoi de message :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 g_signal_connect(G_OBJECT(window2), "key_press_event", G_CALLBACK(on_key_press_chat), NULL); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(envoi), NULL);
Quand l'utilisateur se connecte avec son pseudo au serveur, il y a un thread d'activé. Le code pour la réception de message :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 /* Envoi des messages */ void envoi (GtkWidget* widget) { GtkTextBuffer* text_buffer = 0; GtkTextIter start; GtkTextIter end; gchar* buf = 0; gdouble upper; printf("Envoi d'un message au serveur. \n"); // On récupère le buffer text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); // On récupère l'origine du buffer gtk_text_buffer_get_start_iter(text_buffer, &start); // On récupère la fin du buffer gtk_text_buffer_get_end_iter(text_buffer, &end); // On copie le contenu du buffer dans une variable buf = gtk_text_buffer_get_text(text_buffer, &start, &end, TRUE); printf("Message envoye : %s \n", buf); if (buf[0] != ' ' && buf[0] != '\n') { // Envoi du message vers le serveur (strnlen) if ((write(socket_descriptor, buf, strlen(buf))) < 0) { perror("Erreur : impossible d'ecrire le message destine au serveur"); exit(1); } } g_free(buf); printf("Fin envoi\n"); } /* Envoie un message en appuyant sur la touche Enter */ gboolean on_key_press_chat (GtkWidget* widget, GdkEventKey* event) { if (event->keyval == GDK_Return) { envoi(widget); } return 0; }
Avec tout ces codes, le text_view n'est pas vidé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 /* Réception des messages */ void* reception (void* donnee) { GtkTextBuffer* text_buffer = 0; GtkTextIter start; GtkTextIter end; int longueur; int connecte = 1; int i = 0; while (1) { char buffer[1024] = ""; char pseudo[50] = ""; if ((longueur = read(socket_descriptor, buffer, sizeof(buffer))) > 0) { printf("Message destinataire : \n"); write(1, buffer, longueur); if (buffer[0] == '/' && buffer[1] == 'z') { gtk_label_set_text(GTK_LABEL(label2), str_sub(buffer, 3, longueur)); } else { text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view_chat)); gtk_text_buffer_get_end_iter(text_buffer, &end); int j = 0; // Récupération du pseudo pour le mettre en gras while (buffer[j] != ':') { sprintf(pseudo, "%s%c", pseudo, buffer[j]); j++; } // A faire : Si il existe déjà, ne pas le recrée gtk_text_buffer_create_tag(text_buffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_buffer_insert_with_tags_by_name(text_buffer, &end, pseudo, -1, "bold", NULL); text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view_chat)); gtk_text_buffer_get_end_iter(text_buffer, &end); gtk_text_buffer_insert(text_buffer, &end, g_locale_to_utf8(str_sub(buffer, j, longueur), -1, NULL, NULL, NULL), -1); // Ajustement scrollbar GtkTextMark* text_mark = gtk_text_buffer_create_mark(text_buffer, NULL, &end, FALSE); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(view_chat), text_mark, 0, FALSE, 0, 0); printf("\nFin de la reception via Reception \n"); } } } }
Donc j'ai ajouté la fonction suivante :
Et j'ai placé l'appel de cette fonction à différents endroits.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 /* Vider le text_view */ void clearTextView() { GtkTextBuffer* text_buffer = 0; GtkTextIter start; GtkTextIter end; // On récupère le buffer text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); // On récupère l'origine du buffer gtk_text_buffer_get_start_iter(text_buffer, &start); // On récupère la fin du buffer gtk_text_buffer_get_end_iter(text_buffer, &end); // Supprimer message dans le view_text gtk_text_buffer_get_bounds(text_buffer, &start, &end); gtk_text_buffer_delete(text_buffer, &start, &end); }
Quand je le place à la fin de la fonction "envoi", ça fait la même chose que ce que j'ai décrit au début de ce message.
Quand je le place à la fin de la fonction "reception", mais avant : printf("\nFin de la reception via Reception \n"), j'ai des erreurs aléatoires quand j'appuie sur la touche Entrée. Mais le saut de ligne est bien supprimé. Il ne se passe rien d'anormal quand je clique sur Envoyer.
Voici les erreurs, elles ne surviennent pas toutes en même temps :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 (client:1934): Gtk-ERROR **: Byte index 0 is off the end of the line Trappe pour point d'arrêt et de trace (core dumped)
Code : Sélectionner tout - Visualiser dans une fenêtre à part Erreur de segmentation (core dumped)En espérant que quelqu'un a une idée. Merci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 (client:1945): Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created. You must use marks, character numbers, or line numbers to preserve a position across buffer modifications. You can apply tags and insert marks without invalidating your iterators, but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset) will invalidate all outstanding iterators Erreur de segmentation (core dumped)
Partager