IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

[RESOLU][GTK+3][C] Marges noires et mal centrées


Sujet :

GTK+ avec C & C++

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 38
    Par défaut [RESOLU][GTK+3][C] Marges noires et mal centrées
    Bonjour,


    Je dois développer sur Linux Red Hat 8 une IHM en C avec GTK+3. J'en avais fait il y a 25 ans (peut-être pas avec GTK3, en l'occurrence ) donc je me rappelle de la philosophie par contre je n'ai pas retrouvé mon code de l'époque. De toute façon, il est certainement obsolète.

    Pour commencer, j'ai tenté une IHM assez simple :
    • une zone image en haut qui fait toute la largeur
    • une zone en bas avec un bouton, une scrollbar horizontale et une zone d'édition.



    La largeur de l'image est fournie en paramètre, la marge extérieure aussi. Le reste, ce sont des constantes. Mon code fait des pré-calculs de taille puis créer l'IHM.

    Mon code est le suivant :

    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
    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
     
     
    #include <stdlib.h>
    #include <gtk/gtk.h>
     
     
     
    /* Callback pour le bouton */
    static void on_button_clicked(GtkButton *button, gpointer data) { printf("Button clicked\n"); }
     
    /* Schéma de l'IHM sur la grille */
     
    /*        0        1            2         3     */
    /*       _________________________________      */
    /*   0  |   ___________________________   |  0  */
    /*      |  |                           |  |     */
    /*      |  |           zone            |  |     */
    /*      |  |           image           |  |     */
    /*      |  |___________________________|  |     */
    /*   1  |                                 |  1  */
    /*      |  [Bouton]  <scrollbar>  (Edit)  |     */
    /*   2  |_________________________________|  2  */
    /*                                              */
    /*        0        1            2         3     */
     
    static void IHM_test(int largeur_image, int marge_externe)
    {
        const int hauteur_image     = 480;
        const int hauteur_bouton    =  40;
        const int hauteur_scrollbar =  10;
        const int hauteur_edit_zone =  16;
        const int marge_interne     =  10;
        const int largeur_bouton    =  80;
        const int largeur_edit_zone = 120;
        const int largeur_scrol_min = 200;
        int largeur_fenetre, hauteur_fenetre, hauteur_ligne_2, largeur_scrollbar;
     
        /* hauteur ligne 2 */
        hauteur_ligne_2 = hauteur_bouton;
        if (hauteur_ligne_2 < hauteur_scrollbar)
            hauteur_ligne_2 = hauteur_scrollbar;
        if (hauteur_ligne_2 < hauteur_edit_zone)
            hauteur_ligne_2 = hauteur_edit_zone;
     
        /* Largeur scrollbar : entre bouton et edit zone + marges internes */
        largeur_scrollbar = largeur_image - (marge_interne * 2) - (largeur_bouton + largeur_edit_zone);
        if (largeur_scrollbar < largeur_scrol_min) /* si trop petit : on agrandit tout */
        {
            largeur_scrollbar = largeur_scrol_min;
            largeur_image = largeur_bouton + largeur_edit_zone + largeur_scrol_min + (marge_interne * 2);
        }
     
        /* Dimensions fenêtre */
        largeur_fenetre = largeur_image + (marge_externe * 2);
        hauteur_fenetre = hauteur_image + hauteur_ligne_2 + marge_interne + (marge_externe * 2);
     
        /* Création d’une fenêtre */
        GtkWidget * fenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(fenetre), "Ma fenêtre");
        gtk_window_set_default_size(GTK_WINDOW(fenetre), largeur_fenetre, hauteur_fenetre);
        gtk_widget_set_margin_start(fenetre, marge_externe);
        gtk_widget_set_margin_end(fenetre, marge_externe);
        gtk_widget_set_margin_top(fenetre, marge_externe);
        gtk_widget_set_margin_bottom(fenetre, marge_externe);
        g_signal_connect(fenetre, "destroy", G_CALLBACK(gtk_main_quit), NULL);
     
        // Création de la grille : ligne et colonnes non homogènes, avec des marges
        GtkWidget * grille = gtk_grid_new();
        gtk_grid_set_row_spacing(GTK_GRID(grille), marge_interne);
        gtk_grid_set_column_spacing(GTK_GRID(grille), marge_interne);
        gtk_grid_set_row_homogeneous(GTK_GRID(grille), FALSE);
        gtk_grid_set_column_homogeneous(GTK_GRID(grille), FALSE);
        gtk_container_add(GTK_CONTAINER(fenetre), grille);
     
        // Zone de l'image (avec cadre autour) : débute en (0,0) sur la grille, occupe 3x1
        GtkWidget * cadre = gtk_frame_new("");
        gtk_frame_set_shadow_type(GTK_FRAME(cadre), GTK_SHADOW_ETCHED_IN);
        GtkWidget * zone_image = gtk_drawing_area_new();
        gtk_widget_set_size_request(zone_image, largeur_image, hauteur_image);
        gtk_container_add(GTK_CONTAINER(cadre), zone_image);
        gtk_grid_attach(GTK_GRID(grille), cadre, 0, 0, 3, 1);  // Ligne 0
     
        // Bouton à gauche : débute en (0,1) sur la grille, occupe 1x1
        GtkWidget * bouton = gtk_button_new_with_label("OK");
        gtk_widget_set_size_request(bouton, largeur_bouton, hauteur_bouton);
        gtk_grid_attach(GTK_GRID(grille), bouton, 0, 1, 1, 1);
        g_signal_connect(bouton, "clicked", G_CALLBACK(on_button_clicked), NULL);
     
        // Scrollbar au milieu : débute en (1,1) sur la grille, occupe 1x1
        GtkAdjustment * ajustement = gtk_adjustment_new(50.0, 0.0, 105.0, 1.0, 10.0, 5.0);
        GtkWidget * scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, ajustement);
        g_object_set(scrollbar, "hexpand", TRUE, NULL);
        g_object_set(scrollbar, "vexpand", FALSE, NULL);
        g_object_set(scrollbar, "valign", GTK_ALIGN_CENTER, NULL);
        gtk_widget_set_size_request(scrollbar, largeur_scrollbar, hauteur_scrollbar);
        gtk_grid_attach(GTK_GRID(grille), scrollbar, 1, 1, 1, 1);
     
        // Edit zone à droite : débute en (2,1) sur la grille, occupe 1x1
        GtkWidget * edit_zone = gtk_entry_new_with_buffer((GtkEntryBuffer *) gtk_entry_buffer_new("Valeur", -1));
        gtk_widget_set_size_request(edit_zone, largeur_edit_zone, hauteur_edit_zone);
        gtk_grid_attach(GTK_GRID(grille), edit_zone, 2, 1, 1, 1);  // Ligne 2
     
        // Affichage de tous les widgets
        gtk_widget_show_all(fenetre);
     
    }
     
     
    int main(int argc, char **argv)
    {
        gtk_init(&argc, &argv);
        IHM_test(640, 40);
        IHM_test(640, 20);
        gtk_main();
        return 0;
    }
    Comme c'était bizarre, j'ai fait des essais en mettant deux marges externes différentes. Ça donne les rendus suivants (avec les tailles) :

    Nom : Marge_20.png
Affichages : 96
Taille : 31,7 Ko Nom : Marge_40.png
Affichages : 101
Taille : 30,8 Ko

    On constate que non seulement les marges qui auraient dû être en haut et à gauche se sont cumulées à droite et en bas mais en plus, elles sont complètement noires. A noter que les largeurs de la zone image et de la zone d'édition ont aussi 40 pixels de trop. Et je ne parle pas de la tête de ma scrollbar dont l'apparence est plus que suspecte, mais je verrai ça plus tard.

    Quelqu'un aurait-il une idée de ce qui cloche ? Aurais-je raté quelque chose ?

    Merci d'avance et bonne soirée.

    --
    Olivier

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 330
    Billets dans le blog
    5
    Par défaut
    Bonsoir,

    Sans trop regarder de prés ton code il faut tenir compte du fait qu'un GtkDrawingArea avec une taille fixe gardera cette taille quelque soit la taille de la fenêtre qui l'englobe. Par exemple si tu crées un GtkWindow de 400x400 par exemple dans lequel tu insères un GtkDrawingAera de 400x400, le GtkWindow sera alors un poil plus grand pour pouvoir insérer son enfant. Ceci dit, si tu agrandis le GtkWindow une fois ton application lancée, tu verras alors que le GtkDrawingArea ne changera pas de taille. L'espace "perdu" sera alors soit en noir soit dans une couleur de fond quelconque.

    La bonne philosophie et de ne fixer aucune taille, ou alors une taille minimale pour le GtkDrawingArea. Il faut ensuite connecter le signal “configure-event” du widget parent concerné. Dans le callback associé tu peux alors redimensionner le GtkDrawingArea pour qu'il occupe toute la place libre. Une autre manière est de fixer une taille assez grande et de l'insérer dans un GtkScrolledWindow.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 38
    Par défaut
    Citation Envoyé par gerald3d Voir le message
    Bonsoir,

    Sans trop regarder de prés ton code il faut tenir compte du fait qu'un GtkDrawingArea avec une taille fixe gardera cette taille quelque soit la taille de la fenêtre qui l'englobe. Par exemple si tu crées un GtkWindow de 400x400 par exemple dans lequel tu insères un GtkDrawingAera de 400x400, le GtkWindow sera alors un poil plus grand pour pouvoir insérer son enfant. Ceci dit, si tu agrandis le GtkWindow une fois ton application lancée, tu verras alors que le GtkDrawingArea ne changera pas de taille. L'espace "perdu" sera alors soit en noir soit dans une couleur de fond quelconque.

    La bonne philosophie et de ne fixer aucune taille, ou alors une taille minimale pour le GtkDrawingArea. Il faut ensuite connecter le signal “configure-event” du widget parent concerné. Dans le callback associé tu peux alors redimensionner le GtkDrawingArea pour qu'il occupe toute la place libre. Une autre manière est de fixer une taille assez grande et de l'insérer dans un GtkScrolledWindow.
    Bonsoir,

    Merci de ta réponse même si elle ne concerne pas mon problème actuel. Les conseils sont toujours bons à prendre.
    Pour l'instant, ça n'était qu'une ébauche, je prévoyais de faire évoluer la taille par callback par une rappel de gtk_widget_set_size_request() ou par des g_object_set() via une property de type "size". Ça doit être possible, j'imagine, puisque tu le suggères. L'idée est d'adapter la taille selon l'image chargée, sachant que je risque d'être amené à devoir peut-être l'afficher moins grande que sa taille réelle.

    Néanmoins, j'avoue que j'avais oublié à quel point c'était prise de tête, le GTK. Les dernières IHM, je les ai faites sous matlab à l'époque des uicontrol et uimenu, c'était un bonheur à côté de ce truc

    Bonne soirée.

  4. #4
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 330
    Billets dans le blog
    5
    Par défaut
    Avec Gtk3 tu peux utiliser Glade pour construire ton interface en mode wysiwyg 😉. Il te génère un xml que tu peux utiliser avec le GtkBuilder.

    Regarde dans ma signature j'avais écris un tuto sur l'utilisation de Glade si tu es curieux 😉.

  5. #5
    Invité de passage
    Femme Profil pro
    Ingénieur validation
    Inscrit en
    Mai 2026
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Mai 2026
    Messages : 28
    Par défaut
    Je testerais d'abord un point simple : les marges sont mises sur la GtkWindow, alors que ce n'est pas vraiment elle qui doit servir de conteneur avec marge. Mets plutôt les margins sur la grille, ou sur un GtkBox externe, et laisse la fenêtre contenir ce widget.

    Par exemple : créer la fenêtre, créer la grille, faire gtk_widget_set_margin_start/end/top/bottom(grille, marge_externe), puis gtk_container_add(fenetre, grille). Là tu évites de mélanger taille demandée de la fenêtre et marge d'un widget racine. Les pixels noirs ressemblent à une zone non redessinée autour du contenu, pas à une marge GTK "normale".

    Autre test utile : enlève temporairement tous les set_size_request sauf celui du drawing_area. Si les +40 disparaissent, c'est bien le calcul de taille + marges qui force GTK à agrandir l'allocation.

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 38
    Par défaut
    Citation Envoyé par gerald3d Voir le message
    Avec Gtk3 tu peux utiliser Glade pour construire ton interface en mode wysiwyg 😉. Il te génère un xml que tu peux utiliser avec le GtkBuilder.

    Regarde dans ma signature j'avais écris un tuto sur l'utilisation de Glade si tu es curieux 😉.
    Bonjour,

    Je suis curieux . Et ça a l'air vraiment bien, cet outil, ça ressemble à l'interface QtCreator (et au vieux GUI Matlab).

    Hélas, dans ma boîte, je ne suis pas admin sur ma machine (pas d'accès à sudo apt et compagnie), glade n'est pas installé, meson non plus, donc pas moyen de compiler même en local les sources en téléchargement libre. Pour GTK, ils ont pris une semaine à me l'installer (alors que je n'ai qu'un mois de budget), ils n'aiment pas trop installer des outils en-dehors du master parce que ça nous fait des machines qui ne sont pas "cohérentes" entre elles. Bref, pas envie de me battre pour l'installation d'un nouvel outil dans un si bref délai.

    Donc je m'en passerai pour cette fois. Mais si je dois être amené à faire des IHM plus souvent, je ferai le forcing.

    Bonne journée et merci.

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 38
    Par défaut
    Citation Envoyé par NuageDev81 Voir le message
    Je testerais d'abord un point simple : les marges sont mises sur la GtkWindow, alors que ce n'est pas vraiment elle qui doit servir de conteneur avec marge. Mets plutôt les margins sur la grille, ou sur un GtkBox externe, et laisse la fenêtre contenir ce widget.

    Par exemple : créer la fenêtre, créer la grille, faire gtk_widget_set_margin_start/end/top/bottom(grille, marge_externe), puis gtk_container_add(fenetre, grille). Là tu évites de mélanger taille demandée de la fenêtre et marge d'un widget racine. Les pixels noirs ressemblent à une zone non redessinée autour du contenu, pas à une marge GTK "normale".

    Autre test utile : enlève temporairement tous les set_size_request sauf celui du drawing_area. Si les +40 disparaissent, c'est bien le calcul de taille + marges qui force GTK à agrandir l'allocation.
    Bonjour,

    C'est exactement ça, ça m'a réglé le problème . Bon, les tailles ne sont pas encore celles que j'avais demandées mais ça n'est pas grave.

    Merci merci et bonne journée.

Discussions similaires

  1. [GTK+ 3][C] label centré + bouton qui s'affiche pas
    Par kripteks dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 20/10/2014, 17h03
  2. suprimer les marges noir video
    Par Invité dans le forum Vidéo
    Réponses: 0
    Dernier message: 24/04/2011, 01h29
  3. Objet Figure mal centré
    Par yulken dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 21/06/2007, 12h52
  4. pas de grande marge noire avec adobe premiere 7.0
    Par cuhbe dans le forum Vidéo
    Réponses: 2
    Dernier message: 11/06/2007, 19h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo