Forum Programmation.python Faire disparaitre une fenêtre GTK quand on clique en dehors

Posté par (page perso) .
Tags : aucun
1
10
nov.
2008
Hello,

Je suis en train d'essayer de faire apparaitre une fenetre GTK comme un "popup". Cela signifie que je souhaite que cette fenêtre disparaisse si on clique en dehors.

Un bon exemple sont les menus de n'importe quelle appli : si on ouvre un menu, il se ferme dès qu'on clique en dehors mais, également, le clic n'est pas transmis à l'application en dessous.

Pour cela, je tente de jouer avec gtk.widget.grab_add() mais il ne fait rien de perceptible et avec gtk.gdk.pointer_grab dont je ne comprend pas les paramètres.

J'arrive à faire en sorte que les clics en dehors de mon menu ne soit pas transmis au reste avec gdk.pointer_grab(self.menu.window, True,gdk.BUTTON1_MASK|gdk.BUTTON3_MASK)

Sauf que je comprends pas les paramètres (si le True devient False alors plus aucun clic n'est transmis nul part)

Et puis surtout, la fenêtre ne disparait pas si je clique en dehors.

Est-ce que quelqu'un a une idée ou a déjà fait qqch de semblable ?

Merci d'avance !
  • # une idée peut être

    Posté par . Évalué à 3.

    Bonjour,
    je n'utilise pas GTK mais wxWidgets et pour faire ce genre de chose, j'ai 2 techniques :
    1/ je garde le contrôle de la souris et j'intercepte les événements même si celle-ci est en dehors de la fenêtre et donc lors du clique si je suis en dehors ben je ferme la fenêtre,
    (on peut aussi récupérer l'événement souris qui sort de la fenêtre)
    2/ lors du clique en dehors de la fenêtre ben je perds le "focus" donc je peux alors fermer la fenêtre lors de la réception de l'événement "perte de focus"

    Pour GTK je ne peux pas t'aider, j'avais essayé dans le passé pour faire avancer le projet wxWidgets de regarder un peu GTK mais c'est vrai que la documentation est très très loin au niveau qualité de celle de wxWidgets 'ou Qt).
    Mais à priori fouille sur ces événements pour faire ce que tu cherches.
    Mais peut être que tu peux sur GTK faire un "pop up" d'une fenêtre ?
    Cordialement
  • # J'y connais rien...

    Posté par . Évalué à 3.

    Bonjour,

    Ca fait longtemps que j'ai pas fait de Gtk, et je ne fait pas de python, mais de ce que j'en sait:

    - il faut appeller la fonction X XGrabPointer;
    - dans Gtk/Gdk, celle-ci est appelée par gdk_grab_pointer;
    - la fonction gtk_widget_grab sert seulement à définir quel widget à le focus dans sa fenêtre.

    Quand je regarde les paramètres de la fonction gdk_grab_pointer, je me rend compte que ceux-ci ressemblent beaucoup à son équivalent X :)

    En gros, les paramètres sont, dans l'ordre:
    - window, le fenêtre qui monopolise le pointer, pas de soucis là-dessus;
    - owner_events, contrôle comment sont reportés les évenements pour les autres fenêtres de la même application. En gros, si tu le met à False, alors les clicks sur les autres fenêtres seront considérés comme ne s'adressant pas à ta fenêtre, et seront donc jetés, alors que si tu le met à True ceux-ci seront considérés comme destinés à ta fenêtre... donc pas jetés;
    - event_mask les évènements que tu ne veux pas jeter (Remarque: uniquement pour la souris);
    - confine_to l'id d'une fenêtre dans laquelle la souris sera bloquée (cela servait sur certaines versions de xlock), le pointeur ne pourra pas en sortir;
    - cursor le curseur de souris à afficher tant que le grab est actif;
    - time_ le timestamp de l'évènement qui est la cause du grab. Cela sert à X pour savoir a partir de quand rediriger les évenements. Tu peux récupérer ce paramètre depuis l'évenement: event->time, ou dans le pire des cas utiliser GDK_CURRENT_TIME.

    Voila, j'espère que cela t'aidera...
    Christophe.
    • [^] # Re: J'y connais rien...

      Posté par (page perso) . Évalué à 1.

      problème : si je met owner_events à False, y'a plus rien qui fonctionne. Je dois aller en console et killer mon appli. Je comprends pas car à priori les évênements sont bel et bien interceptés. (j'ai connecté le button-press de ma souris à un print)
      • [^] # Re: J'y connais rien...

        Posté par (page perso) . Évalué à 1.

        Ma solution :

        Dans le code du widget lui meme (appelé calendar) :

        self.calendar.grab_add()
        #We grab the pointer in the calendar
        gdk.pointer_grab(self.calendar.window, True,gdk.BUTTON1_MASK|gdk.MOD2_MASK)
        #we will close the calendar if the user clic outside
        self.calendar.connect('button-press-event', self.__focus_out)


        def __focus_out(self,w=None,e=None) :
        #We should only close if the pointer clic is out of the calendar !
        p = self.calendar.window.get_pointer()
        s = self.calendar.get_size()
        if not(0 <= p[0] <= s[0] and 0 <= p[1] <= s[1]) :
        self.__close_calendar()
        • [^] # Re: J'y connais rien...

          Posté par . Évalué à 1.

          Si le code dans ton commentaire (dans la gestion de l'évènement) est "correct", alors ton message précédent est normal:

          Lorsque tu fait le grab avec owner_events = false:
          - si tu clique dans ta fenêtre, tu recois un évènement -> tu le jette toi-même;
          - si tu clique en dehors -> X voit un évènement. il voit qu'il n'est pas pour ta fenêtre. il voit que tu as demandé un grab. il le jette.
          Typiquement ce que tu ne veux pas...

          Ai-je loupé quelque-chose?

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.