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

wxPython Discussion :

Widgets à background transparent sur un Panel


Sujet :

wxPython

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 45
    Points : 36
    Points
    36
    Par défaut Widgets à background transparent sur un Panel
    Salut à tous,

    Voilà un peu plus d'une heure que je cherche sur le net sans résultats, et je n'ai toujours pas trouvé. Je m'en remets donc à vous. En plus, je suis sûr que c'est un truc tout con !

    Je veux poser un wx.Gradient sur le background de mon Panel. L'utilisateur peut choisir le type de Gradient utilisé, sa direction, sa couleur. La direction est définie par la variable self.grad qui prend différentes valeurs en fonction de ce que l'on veut. Pour simplifier, j'ai retiré le choix de la couleur (qui est dans une autre variable) et je l'ai remplacé par un wx.RED (pour faire contraste avec la couleur de l'écriture).

    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
     
    import wx
     
     
    class MyApp(wx.Frame):
        def __init__(self,parent=None,id=-1,title=u"MyAPP",fichier=""):
     
            self.fen1=wx.Frame(None,-1,title=u"Quizz Reader",size=(520,130),style=wx.DEFAULT_FRAME_STYLE)
            self.pan2=wx.Panel(self.fen1,-1,size=self.fen1.GetClientSize())
            self.sizer2=wx.GridBagSizer(20,20)
     
            self.pan2.Bind(wx.EVT_PAINT,self.OnPaint)
     
        def OnPaint(self,evt=None):
     
            size=self.pan2.GetRect() ## <-- La taille est variable
     
            if self.grad==11:
                wx.WindowDC(self.pan2).GradientFillLinear((0,0,size[2]/2,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.WEST)
                wx.WindowDC(self.pan2).GradientFillLinear((size[2]/2,0,size[2]/2+1,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.EAST)
     
            elif ... etc etc etc ...
     
            evt.Skip()
     
    if __name__=='__main__':
        app=wx.App()
        frame=MyApp()
        app.MainLoop()
    Pourquoi un WindowDC ? Je ne sais pas vraiment ... Je les ai essayé un peu tous et j'ai vu que c'était celui-là qui correspondait le mieux à mes attentes. A vrai dire je comprends pas très bien la doc wxPython sur tous les DC alors j'ai mis un peu au pif.

    Mais maintenant, rajoutons un widget quelconque dans la fonction __init__(...):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    self.static1=wx.StaticText(self.pan2,-1,label="Salut 1",style=wx.ALIGN_CENTRE)
    self.static2=wx.StaticText(self.pan2,-1,label="Salut 2",style=wx.ALIGN_CENTRE,wx.TRANSPARENT_WINDOW)
     
    self.sizer2.Add(self.static1,pos=(1,1),flag=wx.ALIGN_CENTRE)
    self.sizer2.Add(self.static2,pos=(1,2),flag=wx.ALIGN_CENTRE)
     
    self.top1.SetSizer(self.sizer2)
    self.top1.Show(True)
    Il y a un solide de la couleur du Panel d'origine qui persiste autour du widget.
    Je voudrais supprimer ce solide autour du widget et que son background s'adapte à la couleur de celui du Panel.

    Peut-être que je n'ai pas utilisé le bon wx.DC ? Comme je le dis, je ne comprends rien à ces trucs.
    Je pense que je suis pas le premier à avoir eu ce genre de problème.
    J'espère que j'ai été assez clair et que vous pourrez m'aider

    Merci beaucoup d'avance
    A bientôt

    Lotendan

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    328
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 328
    Points : 240
    Points
    240
    Par défaut
    Juste une idée sans garantie. Essaie en mettant ça dans ton __init__ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Salut,

    Tout d'abord merci d'avoir essayé de m'aider

    Eh bien non, cela ne marche pas ... J'ai rajouté comme tu m'a dis un self.pan2.Bind dans mon self.__init__() mais cela ne donne rien ...

    J'ai essayé de le placer avant et après mon self.pan2.Bind(wx.EVT_PAINT,self.OnPaint) mais ca ne marche pas dans les deux cas.

    Merci encore d'avoir essayé de m'aider.
    Si quelqu'un propose une autre solution, je prend

    Bye merci
    Lotendan

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Salut à tous,

    Je ne vois toujours pas comment il faut faire ...
    Je cherche, je cherche, mais je ne trouve pas ... J'ai essayé toutes les possibilités (sauf une xD), et rien ne marche.

    Si quelqu'un peut m'aider (au moins essayer), je lui en serai reconnaissant !

    Merci
    Bye et à bientôt

    Lotendan

  5. #5
    Membre averti
    Avatar de Alain_72
    Inscrit en
    Août 2004
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 180
    Points : 342
    Points
    342
    Par défaut
    Je pense que tes problèmes proviennent d'une méconnaissance du modèle objet de wxPython.

    J'ai reconstruit ton appli et comme ça, ça fonctionne.

    A noter que dans un wx.EVT_PAINT, il est préférable d'utiliser un wx.PaintDC plutôt qu'un wx.WindowDC...

    [EDIT]Je viens de tester sous Windows XP et ça ne fonctionne pas (sous linux c'est bon). Je recherche pourquoi[/EDIT]

    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
    import wx
     
     
    class MyFrame(wx.Frame):
        def __init__(self ,title=u"MyAPP",fichier=""):
     
            wx.Frame.__init__(self, None,-1,title=title,size=(520,130),style=wx.DEFAULT_FRAME_STYLE)
            self.pan2=wx.Panel(self,-1,size=self.GetClientSize())
     
            self.pan2.Bind(wx.EVT_PAINT,self.OnPaint)
            self.static1=wx.StaticText(self.pan2,-1,label="Salut 1",style=wx.ALIGN_CENTRE)
            self.static1.CentreOnParent()
            self.Bind(wx.EVT_SIZE, self.OnSize)
     
        def OnSize(self, event):
            self.pan2.SetSize(self.GetClientSize())
            self.static1.CentreOnParent()
            self.pan2.Refresh()
     
        def OnPaint(self,evt=None):
     
            size=self.pan2.GetRect() ## <-- La taille est variable
            dc = wx.PaintDC(self.pan2)
     
            dc.GradientFillLinear((0,0,size[2]/2,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.WEST)
            dc.GradientFillLinear((size[2]/2,0,size[2]/2+1,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.EAST)
     
            evt.Skip()
     
    class MyApp(wx.App):
        def OnInit(self):
            f = MyFrame()
            f.Show(True)
            self.SetTopWindow(f)
            return True
     
    if __name__=='__main__':
        app=MyApp()
        app.MainLoop()
    Je ne traite pas les problèmes techniques par MP...
    Les forums sont là pour ça...

    Les contributions du bipede

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Salut Alain !

    Content que tu viennes m'aider :p
    Je confirme : sous Windows, cela ne fonctionne pas ...

    Pour les objets Python, d'habitude je dérive toujours une wx.App, mais là j'ai du dériver une wx.Frame (car j'utilise deux applications qui peuvent tourner indépendamment, mais l'une peut faire appel à l'autre alors je ne peux pas utiliser deux wx.App)

    je sais aussi que le fait de donner un nom à ma frame (self.fen) n'a pas vraiment de sens puis que je dérive depuis une frame, mais j'ai besoin de plusieurs fenêtres qui se succèdent (j'en détruis une, et j'en crée une autre). Ce n'est surement pas tres "propre" comme méthode, mais ca marche ...

    En tout cas, merci d'essayer de m'aider !!
    A bientôt

    Lotendan

  7. #7
    Membre averti
    Avatar de Alain_72
    Inscrit en
    Août 2004
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 180
    Points : 342
    Points
    342
    Par défaut
    Bon, mauvaise nouvelle...
    La transparence des widgets sous Windows est gérée comme une pseudo transparence. Un wx.StaticText prend la couleur du background de son parent, et comme avec un gradient tu ne modifies pas la propriété background du widget, ça ne modifie pas la couleur du wx.StaticText. Tu peux le vérifier en appliquant un SetBackgroundColour(wx.RED) à ton panel, avant d'appliquer ton gradient... Tu verras alors que le wxStaticText prend bien un fond rouge.

    Maintenant la bonne nouvelle.
    Si tu veux l'équivalant d'un wx.StaticText qui prend bien le bon fond, c'est possible à simuler avec une classe personnalisée à base de wx.Window en recopiant à l'intérieur de la méthode traitant ses wx.EVT_PAINT, à l'aide de la méthode Blit de son wx.PaintDC, la portion du parent couverte, sur le fond de la wx.Windows.

    Je t'ai fait un petit exemple qui vaut mieux que de grands discours.

    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
    import wx
     
    class MyStaticText(wx.Window):
        def __init__(self, parent, label):
            wx.Window.__init__(self, parent, -1)
            self.parent = parent
            self.label = label
            width, height = self.GetTextExtent(label)
            self.SetSize((width, height))
            self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
     
            self.Bind(wx.EVT_PAINT, self.OnPaint)
     
        def OnPaint(self, event):
            x, y = self.GetPositionTuple()
            dc = wx.PaintDC(self)
            l, h = dc.GetTextExtent(self.label)
            self.SetSize((l, h))
            dc = wx.PaintDC(self)
            dc2 = wx.BufferedPaintDC(self.parent)
            dc.Blit(0, 0, l, h, dc2, x, y)
            dc.SetTextBackground(wx.NullColour)
            dc.SetTextForeground(wx.BLACK)
            dc.DrawText(self.label, 0, 0)
     
    class MyFrame(wx.Frame):
        def __init__(self ,title=u"MyAPP",fichier=""):
     
            wx.Frame.__init__(self, None,-1,title=title,size=(520,130),style=wx.DEFAULT_FRAME_STYLE)
            self.pan2=wx.Panel(self,-1,size=self.GetClientSize(),style = wx.TAB_TRAVERSAL|wx.CLIP_CHILDREN)
            self.pan2.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
     
            self.static1=MyStaticText(self.pan2,"Salut 1")
            self.static1.CentreOnParent()
     
            self.Bind(wx.EVT_SIZE, self.OnResize)
            self.pan2.Bind(wx.EVT_PAINT,self.OnPaint)
     
        def OnResize(self, event):
            self.pan2.SetSize(self.GetClientSizeTuple())
            self.pan2.Refresh()
            self.static1.CentreOnParent()
     
        def OnPaint(self,evt=None):
            size=self.pan2.GetRect() ## <-- La taille est variable
            dc = wx.BufferedPaintDC(self.pan2)
            dc.GradientFillLinear((0,0,size[2]/2,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.WEST)
            dc.GradientFillLinear((size[2]/2,0,size[2]/2+1,size[3]),wx.RED,wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),wx.EAST)
     
    class MyApp(wx.App):
        def OnInit(self):
            f = MyFrame()
            f.Show(True)
            self.SetTopWindow(f)
            return True
     
    if __name__=='__main__':
        app=MyApp()
        app.MainLoop()
    Je ne traite pas les problèmes techniques par MP...
    Les forums sont là pour ça...

    Les contributions du bipede

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

Discussions similaires

  1. Possibilité de widgets avec background transparent ?
    Par Bear the french dans le forum Tkinter
    Réponses: 6
    Dernier message: 21/05/2012, 13h24
  2. comment faire un background transparent?
    Par guigui1005 dans le forum Composants
    Réponses: 5
    Dernier message: 17/05/2012, 21h45
  3. Réponses: 7
    Dernier message: 18/12/2008, 10h20
  4. Problem avec les *.AVI sur les panels
    Par NaDiA_SoFt dans le forum C++Builder
    Réponses: 3
    Dernier message: 31/08/2003, 22h50
  5. Réponses: 1
    Dernier message: 23/02/2003, 06h22

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