Lire les valeurs de deux widgets GtkScale en cliquant sur un bouton

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

Le but de mon programme est de récupérer les valeurs de deux widgets GtkScale pour les enregistrer dans un fichier, le tout en cliquant sur un bouton. Le problème est que la fonction g_signal_connect reliant le bouton et ma fonction config_setInfo pour traiter les GtkScale ne peut prendre qu'un seul argument. Les deux GtkScale sont donc déclarés dans une structure config_set, dont l'adresse est envoyée à ma fonction. Tout compile, mais j'obtiens une erreur de segmentation. Elle a lieu lors de la conversion avec la macro GTK_RANGE (start.c ligne 124). Apparemment, gtk n'apprécie pas trop le fait de travailler sur un pointeur de structure : l'erreur de segmentation n'a pas lieu si la conversion est faite sur la structure en elle même (start.c ligne 73). Mais du coup le traitement est effectué avant de cliquer sur le bouton, ce qui perd tout son intérêt…

Je ne comprends pourquoi GTK_RANGE ne peut pas effectuer la conversion dans un cas et pas dans l'autre. Si vous avez des éclaircissements à me proposer, je suis preneuse :)

Voici le code :

main.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "start.h"


int main(void) {
  GtkWidget *pWindow;
  gtk_init(NULL, NULL);

  pWindow = gui_createWindow();

  GtkWidget *pTable = gtk_table_new(12, 12, TRUE);
  gtk_container_add(GTK_CONTAINER(pWindow), GTK_WIDGET(pTable));

  g_signal_connect(G_OBJECT(pWindow), "destroy",
                   G_CALLBACK(gtk_main_quit), NULL);

  gui_displayConfig(pWindow, pTable);
  gtk_widget_show_all(pWindow);

  gtk_main();
}

start.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef __START_H__
#define __START_H__


typedef struct {
  int questions;
  int chrono;
} Config;

typedef struct {
  GtkWidget *pScale1;
  GtkWidget *pScale2;
} Config_set;


GtkWidget* gui_createWindow();
void gui_displayConfig(GtkWidget *widget, GtkWidget* pTable);

void config_setDefault(GtkWidget* widget, Config* config);
void config_getInfo(GtkWidget* widget, Config* config);
void config_setInfo(GtkWidget* widget, Config_set* config_set);

#endif //__START_H__

start.c

  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
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "start.h"


/*    FONCTION :    GtkWidget* gui_createWindow()
 *      Creation de la fenetre
 */

GtkWidget* gui_createWindow() {
  GtkWidget *pWindow;

  pWindow = gtk_window_new        (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size     (GTK_WINDOW(pWindow), 900, 900);
  gtk_window_set_title            (GTK_WINDOW(pWindow), "Quizz");

  g_signal_connect(G_OBJECT(pWindow), "destroy",
                   G_CALLBACK(gtk_main_quit), NULL);
  return pWindow;
}


/*    FONCTION :   void gui_displayConfig(GtkWidget *widget, GtkWidget* pTable)
 *      Affichage du contenu de la fenetre
 */

void gui_displayConfig(GtkWidget *widget, GtkWidget* pTable) {
  GtkWidget *pFrame;
  Config_set config_set;
  GtkWidget *pButton[3];
  Config config;

  config_getInfo(widget, &config);

  pButton[0] = gtk_button_new_with_label("Parametres par defaut");
  pButton[1] = gtk_button_new_with_label("Annuler");
  pButton[2] = gtk_button_new_with_label("Enregistrer");

  g_signal_connect(G_OBJECT(pButton[0]), "clicked",
                   G_CALLBACK(config_setDefault), &config);

  g_signal_connect(G_OBJECT(pButton[1]), "clicked",
                   G_CALLBACK(gtk_main_quit), NULL);

  g_signal_connect(G_OBJECT(pButton[2]), "clicked",
                   G_CALLBACK(config_setInfo), &config_set);

  pFrame = gtk_frame_new("Questions");
  config_set.pScale1 = gtk_hscale_new_with_range(0, 255, 1);
  gtk_range_set_value(GTK_RANGE(config_set.pScale1), config.questions);
  gtk_container_add(GTK_CONTAINER(pFrame), config_set.pScale1);

  gtk_table_attach(GTK_TABLE(pTable), pFrame, 4, 8, 3, 4,
                   GTK_FILL, GTK_FILL, 0, 0);

  pFrame = gtk_frame_new("Chrono (en secondes)");
  config_set.pScale2 = gtk_hscale_new_with_range(0, 255, 1);
  gtk_range_set_value(GTK_RANGE(config_set.pScale2), config.chrono);
  gtk_container_add(GTK_CONTAINER(pFrame), config_set.pScale2);

  gtk_table_attach(GTK_TABLE(pTable), pFrame, 4, 8, 4, 5,
                   GTK_FILL, GTK_FILL, 0, 0);
  gtk_table_attach(GTK_TABLE(pTable), pButton[0], 4, 8, 5, 7,
                   GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_table_attach(GTK_TABLE(pTable), pButton[1], 4, 8, 7, 9,
                   GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_table_attach(GTK_TABLE(pTable), pButton[2], 4, 8, 9, 11,
                   GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);

  gtk_widget_show_all(pTable);

  printf("Ca fonctionne sans pointeur : \n");
  config.questions = gtk_range_get_value(GTK_RANGE(config_set.pScale1));
  printf("%d\n", config.questions);
}


/*    FONCTION :    void config_setDefault(GtkWidget* widget, Config* config)
 *      Reinitialisation des parametres par defaut
 */

void config_setDefault(GtkWidget* widget, Config* config) {
  FILE* config_file;
  config->questions = 20;
  config->chrono = 60;

  if((config_file = fopen("config", "w+b")) == NULL) {
    perror("Impossible de creer le fichier ");
  }
  else {
    fwrite(config, sizeof(config), 1, config_file);
    fclose(config_file);
  }
}


/*    FONCTION :    void config_getInfo(GtkWidget* widget, Config* config)
 *      Initialisation des parametres
 */

void config_getInfo(GtkWidget* widget, Config* config) {
  FILE* config_file;
  if((config_file = fopen("config", "rb")) == NULL) {
    perror("Erreur, les parametres seront remis a zeros ");
    config_setDefault(widget, config);
  }
  else {
    fread(config, sizeof(config), 1, config_file);
    fclose(config_file);
  }
}


/*    FONCTION :    void config_setInfo(GtkWidget* widget, Config* config)
 *      Enregistrement des parametres
 */

void config_setInfo(GtkWidget* widget, Config_set* config_set) {
  FILE* config_file;
  Config config;

  // CA PLANTE A LA LIGNE SUIVANTE
  config.questions = gtk_range_get_value(GTK_RANGE(config_set->pScale1));
  config.chrono = gtk_range_get_value(GTK_RANGE(config_set->pScale2));

  // FAISONS AUTREMENT
  // printf("CA PLANTE A LA LIGNE SUIVANTE !\n");
  // GtkRange* v = GTK_RANGE(config_set->pScale1);
  // printf("CA A PLANTE !\n");
  // int nb = gtk_range_get_value(v);

  if((config_file = fopen("config", "w+b")) == NULL) {
    perror("Erreur");
  }
  else {
    fwrite(&config, sizeof(config), 1, config_file);
    fclose(config_file);
  }
}

Merci de votre attention o/

+0 -0
Staff

Salut,

C'est un problème de durée de vie : ta variable config_set n'existe plus après l'exécution de la fonction gui_displayConfig (puisqu'elle lui est locale), or tu y accèdes malgré tout lors de la survenance d'un évènement. Je t'invite à lire cette section du cours sur le C pour approfondir la question. ;)

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte