Вопрос:

Проблемы с wxPython с переносом staticText

python static wxpython

8298 просмотра

4 ответа

1259 Репутация автора

Упрощенная версия кода размещена ниже (пробелы, комментарии и т. Д. Удалены, чтобы уменьшить размер, но общий формат моей программы остается примерно таким же).

Когда я запускаю сценарий, статический текст корректно переносится, как и должно, но другие элементы на панели не перемещаются вниз (они действуют так, как если бы статический текст представлял собой только одну строку и, следовательно, не все было видно).

Если я вручную изменяю размер окна / рамки, даже небольшую величину, все исправляется и отображается так, как должно.

Почему он не отображается правильно с самого начала? Я пробовал все виды комбинаций GetParent().Refresh()или или Update()и GetTopLevelParent().Update()или Refresh(). Я также перепробовал все, что могу придумать, но не могу заставить его правильно отображаться без изменения размера фрейма / окна вручную. После изменения размера он работает именно так, как я хочу.

Информация:

  • 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()
Автор: Scott B Источник Размещён: 05.01.2011 12:01

Ответы (4)


2 плюса

29626 Репутация автора

Почему вы подклассы? Вам нужен перенос слов? Если это так, в wx.lib.wordwrap есть модуль, который вы можете использовать.

В ответе на комментарий ОП, проверьте это:

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()

Я использовал комментарий ОП для текста. Во всяком случае, это прекрасно работает на Windows XP, Python 2.5 и wxPython 2.8.10.1.

Автор: Mike Driscoll Размещён: 05.01.2011 02:58

4 плюса

1259 Репутация автора

Решение

Используя код Майка Дрисколла как основу, я надеюсь, что это демонстрирует мою проблему. Есть две разные версии использования "TXT". Вот три вещи, которые я хочу, чтобы вы попробовали:

  1. Запустите его как есть. С моим StaticWrapText. Сначала он отображается неправильно, но изменил размер окна, и он работает именно так, как я хочу. Нет пробела / пустого места под текстом перед кнопкой

  2. Измените эти две строки (измените комментарии):
    txt = wx.StaticText (панель, метка = текст)
    #txt = StaticWrapText (панель, метка = текст)
    Теперь вы увидите, что переноса нет, а текст всегда находится только на одной строке , Определенно не то, что мы хотим. Это из-за "sizer.Add (txt, 0, wx.EXPAND, 5)" ... так что переходим к части 3 ...

  3. Сохраните изменения из части 2, а также измените:
    sizer.Add (txt, 0, wx.EXPAND, 5)
    на:
    sizer.Add (txt, 1, wx.EXPAND, 5)
    Так что теперь статический текст будет расширяться. Это близко к работе ... НО я не хочу, чтобы все это впустую пространство между текстом и кнопкой. Если вы сделаете окно большим, будет много потерянного пространства. См. Часть 1 после изменения размера окна, чтобы увидеть разницу.

Код:

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()

РЕДАКТИРОВАТЬ:

AHHH ... наконец-то! Я пытался использовать метод Layout () практически на каждом уровне программы, но мне действительно нужно было использовать Layout () в SIZER, который можно найти с помощью метода GetSizer (), или вы можете отправить SendSizeEvent () на панель (прокомментировано). в коде ниже). Таким образом, следующее теперь делает именно то, что я хочу! Спасибо за помощь. Единственным другим изменением было сохранение панели с self.panel в классе frame. Как примечание, я должен был поместить это утверждение ПОСЛЕ кадра. Show () или он не работал правильно.

Код:

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 ()

Интересно ... с этим оригинальным примером это может быть до или после frame.Show (), но другой пример требует, чтобы это было после frame.Show (). Я не уверен почему, но просто поставь это после, и ты в безопасности.

Автор: Scott B Размещён: 06.01.2011 05:47

5 плюса

301 Репутация автора

я использую

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

Это прекрасно работает, и следующие виджеты расположены правильно. Вы можете легко сделать это txt.Wrap(width)динамически.

Автор: hdrz Размещён: 27.01.2013 03:58

2 плюса

80 Репутация автора

Я нашел гораздо более простой и автоматический способ решения этой проблемы.

После создания элемента управления StaticText свяжите wx.EVT_SIZE элемента управления с обработчиком, который вызывает функцию Wrap () StaticText с параметром GetSize () [0] события в качестве аргумента (а затем пропускает событие).

Пример:

class MyDialog(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent = parent, title = "Test Dialog", style = wx.CAPTION)

        bigstr = "This is a really long string that is intended to test the wrapping functionality of the StaticText control in this dialog.  If it works correctly, it should appear as multiple lines of text with a minimum of fuss."

        self.__label__ = wx.StaticText(parent = self, label = bigstr)
        self.__actionbutton__ = wx.Button(parent = self, label = "Go")

        self.__label__.Bind(wx.EVT_SIZE, self.__WrapText__)
        self.__actionbutton__.Bind(wx.EVT_BUTTON, self.__OnButton__)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.__label__, flag = wx.ALL | wx.EXPAND, border = 5)
        sizer.Add(self.__actionbutton__, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.CENTER, border = 0)
        self.SetSizer(sizer)

        self.Layout()

    def __OnButton__(self, event):
        self.EndModal(wx.ID_OK)

    def __WrapText__(self, event):
        self.__label__.Wrap(event.GetSize()[0])

        event.Skip()

Вот как это выглядит в моей системе (MSW, Python 2.7.5, wx 2.8.12.1): StaticText Wrapping Dialog

Автор: TPDMarchHare Размещён: 16.01.2016 05:53
Вопросы из категории :
32x32