包装 staticText 的 wxPython 问题 [英] wxPython problems with wrapping staticText

查看:25
本文介绍了包装 staticText 的 wxPython 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面发布了代码的简化版本(删除了空格、注释等以减小大小 - 但我的程序的一般格式大致保持不变).

A simplified version of the code is posted below (white space, comments, etc. removed to reduce size - but the general format to my program is kept roughly the same).

当我运行脚本时,静态文本按原样正确换行,但面板中的其他项目不会向下移动(它们就好像静态文本只有一行,因此并非所有内容都可见).

When I run the script, the static text correctly wraps as it should, but the other items in the panel do not move down (they act as if the statictext is only one line and thus not everything is visible).

如果我手动调整窗口/框架的大小,即使只是很小的一部分,一切都会得到纠正,并按原样显示.

If I manually resize the window/frame, even just a tiny amount, everything gets corrected, and displays as it is should.

为什么一开始就不能正确显示?我已经尝试了 GetParent().Refresh()Update()GetTopLevelParent().Update()Refresh().我也尝试了我能想到的所有方法,但如果不手动调整框架/窗口的大小就无法正确显示.重新调整大小后,它的工作方式完全符合我的要求.

Why doesn't it display correctly to begin with? I've tried all sorts of combination's of GetParent().Refresh() or Update() and GetTopLevelParent().Update() or Refresh(). I've also tried everything I can think of but cannot get it to display correctly without manually resizing the frame/window. Once re-sized, it works exactly as I want it to.

信息:

  • Windows XP
  • Python 2.5.2
  • wxPython 2.8.11.0 (msw-unicode)

我的代码:

#! /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()

推荐答案

使用 Mike Driscoll 的代码作为基准,我希望这能说明我的问题.使用txt"有两种不同的版本.以下是我希望您尝试的三件事:

Using Mike Driscoll's code as a baseline, I hope this demonstrates my issue. There are two different versions of using "txt". Here are three things I want you to try:

  1. 按原样运行.使用我的 StaticWrapText.它起初显示错误,但重新调整窗口大小,它完全按照我的意愿工作.按钮"之前的文本下方没有空白/浪费空间

  1. Run it as-is. With my StaticWrapText. It displays wrong at first, but re-size the window and it works EXACTLY as I want. There is no blank/wasted space below the text before the "button"

更改这两行(更改注释):
txt = wx.StaticText(面板,标签=文本)
#txt = StaticWrapText(panel, label=text)
现在你会看到没有换行,文本总是只有一行.绝对不是我们想要的.这是因为 "sizer.Add(txt, 0, wx.EXPAND, 5) "...所以继续第 3 部分...

Change these two lines (change the comments):
txt = wx.StaticText(panel, label=text)
#txt = StaticWrapText(panel, label=text)
Now you will see there is no wrapping and the text is always on only one line. Definitely not what we want. This is because of "sizer.Add(txt, 0, wx.EXPAND, 5) "...so going on to Part 3...

保留第 2 部分的更改并更改:
sizer.Add(txt, 0, wx.EXPAND, 5)
至:
sizer.Add(txt, 1, wx.EXPAND, 5)
所以现在静态文本将扩展.这是接近工作...但我不希望文本和按钮之间的所有浪费空间.如果你把窗户做得大,就会浪费很多空间.重新调整窗口大小后,请参阅第 1 部分以查看差异.

Keep the change from Part 2 and also change:
sizer.Add(txt, 0, wx.EXPAND, 5)
to:
sizer.Add(txt, 1, wx.EXPAND, 5)
So now the statictext will expand. This is CLOSE to working...BUT I don't want all that wasted space between the text and the button. If you make the window large, there is a lot of wasted space. See Part 1 after the window is re-sized to see the difference.

代码:

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 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)
        txt = StaticWrapText(panel, label=text)
        wxbutton = wx.Button(panel, label='Button', size=wx.Size(120,50))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(txt,      0, wx.EXPAND, 5)
        sizer.Add(wxbutton, 1, wx.EXPAND, 5)
        panel.SetSizer(sizer)

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

啊哈……终于!我尝试在程序的几乎每个级别上使用 Layout() 方法,但实际上我需要在 SIZER 上使用 Layout() 方法,该方法可以通过 GetSizer() 方法找到 - 或者您可以将 SendSizeEvent() 发送到面板(评论在下面的代码中).因此,以下内容正是我想要的!谢谢您的帮助.唯一的其他更改是将带有 self.panel 的面板存储在框架类中.请注意,我必须将此语句放在 frame.Show() 之后,否则它无法正常工作.

AHHH...finally! I tried using the Layout() method on virtually every level of the program, but I actually needed to use Layout() on the SIZER which is found with the method GetSizer() - or you can send SendSizeEvent() to the panel (commented in code below). Thus, the following now does EXACTLY what I want! Thanks for the help. The only other change was to store the panel with self.panel in the frame class. As a note, I had to put this statement AFTER the frame.Show() or it didn't work correctly.

代码:

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 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
        self.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 = StaticWrapText(self.panel, label=text)
        wxbutton = wx.Button(self.panel, label='Button', size=wx.Size(120,50))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(txt,      0, wx.EXPAND, 5)
        sizer.Add(wxbutton, 1, wx.EXPAND, 5)
        self.panel.SetSizer(sizer)

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

最后一点,在我发布的原始程序中,需要在 frame.Show() 之前或之后添加以下行:
frame.panel.Panel2.GetSizer().Layout()

As a final note, in my original program posted, the following line needs to be added just before or after frame.Show():
frame.panel.Panel2.GetSizer().Layout()

有趣的是...对于原始示例,这可以在 frame.Show() 之前或之后,但另一个示例要求它在 frame.Show() 之后.我不知道为什么,但只要把它放在后面,你就安全了.

Interestingly...with that original example this can be before or after frame.Show() but the other example requires that it be after frame.Show(). I'm not sure why, but just put it after and you're safe.

这篇关于包装 staticText 的 wxPython 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆