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 :

Widget maison : problème de rendu


Sujet :

GTK+ avec C & C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 32
    Par défaut Widget maison : problème de rendu
    Bonjour à tous,

    J'écris un widget à partir d'un GtkWidget, et dessine avec Cairo dans sa GdkWindow, ça fonctionne
    Cependant, j'ai un problème majeur : je ne vois les dessins effectués par Cairo dans gtk_***_expose() que pendant le redimentionnement de mon widget.
    Je subodore que "quelqu'un" (le GtkWidget parent !?) redessine sur ma fenêtre juste après moi ou quelque chose dans le genre...

    Voici ma gtk_***_expose() (avec en cadeau bonus ma gtk_***_realize au cas-où) :
    Code C : 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
     
    static gboolean
    gtk_lonly_expose (GtkWidget* widget,
                      GdkEventExpose* event)
    {
       g_return_val_if_fail (GTK_IS_LONLY (widget), FALSE);
       g_return_val_if_fail (event != NULL, FALSE);
     
       if (GTK_WIDGET_DRAWABLE (widget))
       {
          gtk_lonly_paint (GTK_LONLY (widget)); /* => fonction dessinant avec Cairo sur widget->window */
       }
     
       return FALSE;
    }
     
     
    static void
    gtk_lonly_realize (GtkWidget* widget)
    {
       GdkWindowAttr attributes;
       guint attributes_mask;
     
     
       g_return_if_fail (GTK_IS_LONLY (widget));
     
     
       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
     
       attributes.window_type  = GDK_WINDOW_CHILD;
       attributes.x            = widget->allocation.x;
       attributes.y            = widget->allocation.y;
       attributes.width        = widget->allocation.width;
       attributes.height       = widget->allocation.height;
       attributes.wclass       = GDK_INPUT_OUTPUT;
       attributes.event_mask   = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
     
       attributes_mask = GDK_WA_X | GDK_WA_Y;
     
       widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                        &attributes, attributes_mask);
     
       /* create CairoRenderer now because of need of the GdkWindow */
       GTK_LONLY (widget)->cr = cairo_reference (gdk_cairo_create (widget->window));
     
       gdk_window_set_user_data (widget->window, widget);
     
       widget->style = gtk_style_attach (widget->style, widget->window);
       gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
    }

    Qu'ais-je fais de mal ?


    Merci d'avance !

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 32
    Par défaut
    Bonjour,

    Alors, j'ai un peu avancé dans la recherche de mon problème, même si ça ne fonctionne toujours pas vraiment.

    Apparemment une fonction appelle gdk_window_end_paint() après ma fonction expose(), et redéssine donc la partie de la GdkWindow indiquée par event->region ; ce qui fatalement écrase mes rendus.
    Je me demande maintenant quelle est cette fonction, et comment l'empêcher d'être appelée ou du moins comment l'empêcher de redéssiner ?

    Ça "fonctionne" si je rends event->window NULL : j'obtiens un erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (solitaire:11462): Gdk-CRITICAL **: gdk_window_end_paint: assertion `window != NULL' failed
    mais mon widget n'est pas écrasé. Bon, c'est moche mais ça m'a aidé a cerner le problème ^^

    Plus étrange par contre, si je fais un appelle manuel à gdk_window_begin_paint_region() et à gdk_window_end_paint() avant d'effectuer mes rendus, la fonction bizarre est toujours appelée, mais elle n'écrase pas mes dessins.
    Quelle est là raison, et comment faire pareil de façon moins "bricolage" ?


    En pratique mon code est le suivant :
    Code c : 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
    static gboolean
    gtk_lonly_expose (GtkWidget* widget,
                      GdkEventExpose* event)
    {
      g_return_val_if_fail (GTK_IS_LONLY (widget), FALSE);
      g_return_val_if_fail (event != NULL, FALSE);
     
      if (GTK_WIDGET_DRAWABLE (widget))
      {
         /*** FAKE ***/
        gdk_window_begin_paint_region (widget->window, event->region);
        gdk_window_end_paint (widget->window);
        /*** ENDFAKE ***/
     
        gtk_lonly_paint (GTK_LONLY (widget)); /* => fonction dessinant avec Cairo sur widget->window */
      }
     
      return FALSE;
    }


    Merci d'avance !

    PS :
    Si vous avez besoin du code complet ou plus de détails, pas de problèmes, il suffit de demander.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    32
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 32
    Par défaut
    J'avance ^^

    GTK+ entoure par défaut les appels au expose_event d'appels à gdk_window_begin_paint_region() et gdk_window_end_paint(). Le but est de dessiner dans un backingstore et d'afficher tout en même temps pour éviter les artefacts visibles durant le rendu.
    Il est possible de désactiver la chose pour un widget en mettant à faux l'utilisation des doubles buffers (via gtk_widget_set_double_buffered()).

    Maintenant je n'ai plus de problème de rendu, ça s'affiche sans hacks. Mais je vois les artefacts pendant le rendu ^^
    Cependant, je me demande ce qui fait que je ne dessine pas dans le backing store mais apparemment directement à l'écran (ou dans la GdkWindow)... Cairo !??
    Apparemment il y a de ça car je viens de voir dans un exemple de dessin dans un environnement GTK+ sur le site de Cairo qu'il faisaient ça... bon, y'avait des threads dans l'air.


    J'hésite à mettre à résolu pour le moment, car j'aimerais bien comprendre le pourquoi du problème, et s'il y a une autre solution, mais le problème lui-même est résolu.

    Merci d'avance à mes éclaireurs !
    moiban

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. stockage page web dans mysql : problème de rendu
    Par circajet7 dans le forum SQL Procédural
    Réponses: 5
    Dernier message: 29/03/2007, 10h25
  2. Problèmes de rendu incongru
    Par jacquesprogram dans le forum Flash
    Réponses: 14
    Dernier message: 01/10/2006, 11h50
  3. Problème de rendu 16 bits float + MSAA
    Par gybe dans le forum DirectX
    Réponses: 10
    Dernier message: 10/08/2006, 16h24
  4. [wxPython] problème de rendu
    Par tool69 dans le forum wxPython
    Réponses: 5
    Dernier message: 25/09/2005, 19h43
  5. Problème de rendu 2D
    Par Freakazoid dans le forum DirectX
    Réponses: 6
    Dernier message: 04/08/2004, 21h47

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