8
votes

WXPYTHON Problèmes d'emballage Statictext

Une version simplifiée du code est affichée ci-dessous (espace blanc, commentaires, etc. supprimés pour réduire la taille - mais le format général à mon programme est maintenu à peu près le même).

Quand je gère le script, la statique Le texte s'enveloppe correctement tel qu'il le devrait, mais les autres éléments du panneau ne descendent pas (ils agissent comme si le statisteext n'est qu'une ligne et que tout n'est donc pas visible). p>

Si je redimensionniste manuellement la fenêtre / Cadre, même juste une petite quantité, tout est corrigé, et s'affiche comme il faut. P>

Pourquoi ne s'affiche pas correctement pour commencer? J'ai essayé toutes sortes de combinaisons de getparent (). Rafraîchissez () code> ou update () code> et gettoplevelparent (). Mise à jour () code> ou Actualiser () Code>. J'ai également essayé tout ce que je peux penser mais je ne peux pas l'obtenir correctement sans redimensionner manuellement le cadre / la fenêtre. Une fois ré-dimensionné, cela fonctionne exactement comme je le veux. P>

Information: P>

  • Windows XP LI>
  • Python 2.5.2 Li>
  • WXPYTHON 2.8.11.0 (MSW-UNICODE) LI> ul>

    Mon code: P>

    #! /usr/bin/python
    
    import wx
    
    class StaticWrapText(wx.PyControl):
       def __init__(self, parent, id=wx.ID_ANY, label='', pos=wx.DefaultPosition,
                    size=wx.DefaultSize, style=wx.NO_BORDER,
                    validator=wx.DefaultValidator, name='StaticWrapText'):
          wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
          self.statictext = wx.StaticText(self, wx.ID_ANY, label, style=style)
          self.wraplabel = label
          #self.wrap()
       def wrap(self):
          self.Freeze()
          self.statictext.SetLabel(self.wraplabel)
          self.statictext.Wrap(self.GetSize().width)
          self.Thaw()
       def DoGetBestSize(self):
          self.wrap()
          #print self.statictext.GetSize()
          self.SetSize(self.statictext.GetSize())
          return self.GetSize()
    
    class TestPanel(wx.Panel):
       def __init__(self, *args, **kwargs):
          # Init the base class
          wx.Panel.__init__(self, *args, **kwargs)
          self.createControls()
       def createControls(self):
          # --- Panel2 -------------------------------------------------------------
          self.Panel2 = wx.Panel(self, -1)
          msg1 =  'Below is a List of Files to be Processed'
          staticBox      = wx.StaticBox(self.Panel2, label=msg1)
          Panel2_box1_v1 = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
          Panel2_box2_h1 = wx.BoxSizer(wx.HORIZONTAL)
          Panel2_box3_v1 = wx.BoxSizer(wx.VERTICAL)
    
          self.wxL_Inputs = wx.ListBox(self.Panel2, wx.ID_ANY, style=wx.LB_EXTENDED)
    
          sz = dict(size=(120,-1))
          wxB_AddFile    = wx.Button(self.Panel2, label='Add File',        **sz)
          wxB_DeleteFile = wx.Button(self.Panel2, label='Delete Selected', **sz)
          wxB_ClearFiles = wx.Button(self.Panel2, label='Clear All',       **sz)
          Panel2_box3_v1.Add(wxB_AddFile,    0, wx.TOP, 0)
          Panel2_box3_v1.Add(wxB_DeleteFile, 0, wx.TOP, 0)
          Panel2_box3_v1.Add(wxB_ClearFiles, 0, wx.TOP, 0)
    
          Panel2_box2_h1.Add(self.wxL_Inputs, 1, wx.ALL|wx.EXPAND, 2)
          Panel2_box2_h1.Add(Panel2_box3_v1,  0, wx.ALL|wx.EXPAND, 2)
    
          msg =  'This is a long line of text used to test the autowrapping '
          msg += 'static text message.  '
          msg += 'This is a long line of text used to test the autowrapping '
          msg += 'static text message.  '
          msg += 'This is a long line of text used to test the autowrapping '
          msg += 'static text message.  '
          msg += 'This is a long line of text used to test the autowrapping '
          msg += 'static text message.  '
          staticMsg = StaticWrapText(self.Panel2, label=msg)
    
          Panel2_box1_v1.Add(staticMsg,      0, wx.ALL|wx.EXPAND, 2)
          Panel2_box1_v1.Add(Panel2_box2_h1, 1, wx.ALL|wx.EXPAND, 0)
          self.Panel2.SetSizer(Panel2_box1_v1)
    
          # --- Combine Everything -------------------------------------------------
          final_vbox = wx.BoxSizer(wx.VERTICAL)
          final_vbox.Add(self.Panel2, 1, wx.ALL|wx.EXPAND, 2)
          self.SetSizerAndFit(final_vbox)
    
    class TestFrame(wx.Frame):
       def __init__(self, *args, **kwargs):
          # Init the base class
          wx.Frame.__init__(self, *args, **kwargs)
          panel = TestPanel(self)
          self.SetClientSize(wx.Size(500,500))
          self.Center()
    
    class wxFileCleanupApp(wx.App):
       def __init__(self, *args, **kwargs):
          # Init the base class
          wx.App.__init__(self, *args, **kwargs)
       def OnInit(self):
          # Create the frame, center it, and show it
          frame = TestFrame(None, title='Test Frame')
          frame.Show()
          return True
    
    if __name__ == '__main__':
       app = wxFileCleanupApp()
       app.MainLoop()
    


0 commentaires

4 Réponses :


2
votes

Pourquoi vous sous-classez-vous? Avez-vous besoin de wordwrap? Si tel est le cas, il y a un module pour cela dans wx.lib.wordwrap que vous pouvez utiliser.

En répondez au commentaire de l'OP, vérifiez ceci: P>

import wx

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)

        text = "I'm subclasses the statictext because I want it to act exactly like a static text, but correctly wordwrap as needed. I've found several examples of it on the web, but none that worked how I wanted. The wordwrap makes it look much nicer when the user may decide to re-size the window, so I would definitely like to have it be wordwrapped. I know about the wx.lib.wordwrap, but chose to use the built in Wrap function of the statictext control instead. It basically does the same thing from what I understand."
        txt = wx.StaticText(panel, label=text)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(txt, 1, wx.EXPAND, 5)
        panel.SetSizer(sizer)

# Run the program
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm().Show()
    app.MainLoop()


3 commentaires

Je suis sous-classes le statutext parce que je veux qu'il agisse exactement comme un texte statique, mais correctement wordwraf au besoin. J'en ai trouvé plusieurs exemples sur le Web, mais aucun qui a fonctionné comme je voulais. Le WordWrap indique qu'il a l'air beaucoup plus agréable lorsque l'utilisateur peut décider de redimensionner la fenêtre, donc je voudrais certainement le faire être wordwrapped. Je sais sur le wx.lib.wordwrap, mais j'ai choisi d'utiliser la fonction d'enveloppe intégrée de la commande StatItext à la place. Cela fait essentiellement la même chose de ce que je comprends.


Vous voudrez peut-être utiliser SetSizeDhints pour empêcher le cadre d'être redimensionné trop petit.


OK, votre exemple est plus petit, il sera donc plus facile de travailler avec. Consultez ma réponse pour une modification à votre code qui démontre mon problème (plus clairement, j'espère).



5
votes

Utilisation du code de Mike Driscoll comme base, j'espère que cela démontre mon problème. Il existe deux versions différentes d'utiliser "txt". Voici trois choses que je veux que vous essayiez:

  1. exécutez-le comme. Avec mon staticwraptext. Il affiche le problème au début, mais réapparaîtra la fenêtre et cela fonctionne exactement comme je le souhaite. Il n'y a pas d'espace vide / gaspillé sous le texte avant le "bouton"

  2. Changer ces deux lignes (changez les commentaires):
    txt = wx.staticext (panneau, étiquette = texte)
    #txt = staticwraptext (panneau, étiquette = texte)
    Vous verrez maintenant qu'il n'y a pas d'emballage et le texte n'est toujours pas sur une seule ligne. Certainement pas ce que nous voulons. C'est à cause de "SIZER.ADD (TXT, 0, WX.EXPAND, 5)" ... donc la partie 3 ...

  3. Gardez le changement de la partie 2 et changez également:
    sifer.add (txt, 0, wx.expand, 5)
    à:
    SIZER.ADD (TXT, 1, WX.EXPAND, 5)
    Alors maintenant, le statutext va se développer. Ceci est proche de travailler ... mais je ne veux pas tout ce qui gaspille de l'espace entre le texte et le bouton. Si vous faites la fenêtre grande, il y a beaucoup d'espace perdu. Voir la partie 1 après la ré-dimension de la fenêtre pour voir la différence.

    code: xxx

    edit:

    ahhh ... enfin! J'ai essayé d'utiliser la méthode de la mise en page () sur pratiquement tous les niveaux du programme, mais j'avais réellement nécessaire d'utiliser la mise en page () sur le sizer qui se trouve avec la méthode Getsizer () - ou vous pouvez envoyer SendSizeevent () au panneau (commenté dans le code ci-dessous). Ainsi, ce qui suit fait maintenant exactement ce que je veux! Merci pour l'aide. Le seul autre changement était de stocker le panneau avec Self.panel dans la classe de trame. En tant que note, je devais mettre cette déclaration après le cadre.Show () ou cela n'a pas fonctionné correctement.

    code: xxx

    comme Une note finale, dans mon programme d'origine affiché, la ligne suivante doit être ajoutée juste avant ou après la trame.Show ():
    cadre.panel.panel2.Getsizer (). Disposition ()

    Intéressant ... Avec cet exemple original, cela peut être avant ou après la trame.Show () mais l'autre exemple nécessite que cela soit après la trame. Spectacle(). Je ne suis pas sûr de savoir pourquoi, mais je viens de le mettre après et vous êtes en sécurité.


3 commentaires

J'aurais dû penser à cela. Vous souhaitez généralement appeler la mise en page sur le parent des widgets ou le sizer contenant les widgets. Tant pis. Désolé je n'ai pas tapé ça.


Merci pour l'aide! Cela ne fonctionne toujours pas comme si je devrais maximiser / minimiser la fenêtre. Mais pour le moment, c'est assez bon.


Ah, cela permet de fonctionner même lorsque le bouton Maximizize est utilisé ... dans la fonction d'enveloppe, utilisez self.staticExt.wrap (auto.getparent (). Getsize (). Largeur) au lieu de auto.StaticExt.wrap (auto. Obtenir (). Largeur)



5
votes

J'utilise

width = 200  # panel width
txt = wx.StaticText(panel, label=text)
txt.Wrap(width)


0 commentaires

2
votes

J'ai trouvé ce que je pense est un moyen beaucoup plus facile et automatique de gérer ce problème.

Après avoir créé le contrôle StatItext, liez le contrôleur WX.EVT_SIZE à un gestionnaire qui appelle la fonction Wrap () du StatCeText avec l'obtention de l'événement () [0] comme un argument (puis saute l'événement).

Un exemple: xxx

C'est à quoi il ressemble à mon système (MSW, Python 2.7.5, WX 2.8.12.1):


1 commentaires

Appeler Enveloppement à l'intérieur d'un gestionnaire EvT_Size semble à nouveau appeler le même gestionnaire, cette fois avec une taille différente.