Почему вложенные сайзеры не расширяются в wxPython, если они скрыты при инициализации?

Я пытаюсь создать трехпанельный графический интерфейс, и все шло отлично, пока я не попытался вложить панели / окна внутри других панелей и скрыть их при запуске графического интерфейса.

См. Это изображение ... Желтые / зеленые / синие поля были автоматически расширены, чтобы заполнить свои панели во время инициализации, но маленький фиолетовый прямоугольник создается, НО затем скрывается во время инициализации wx.Panel, пока не истечет 2-секундный таймер, а затем в это время вызывается метод Show () этого объекта. В это время он не заполняет содержащуюся панель. Кажется, что скрытие панели во время инициализации заставляет измеритель панели выбирать размер по умолчанию, 20x20.

тест калибровки

Вот код:

import wx
import  wx.lib.scrolledpanel as scrolled

class NavPanel(wx.Panel):
    """"""
    def __init__(self, parent, actionPanel):
        """Constructor"""
        wx.Panel.__init__(self, parent) #, size=(200,600))
        self.actionPanel = actionPanel
        self.SetBackgroundColour("Yellow")

class ActionPanel(wx.Panel):
    """"""
    def __init__(self, parent, target_item=None):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.SetBackgroundColour("Green")

        self.sc = NestedScrolledActionPanel(self)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.sc, 1, wx.EXPAND)
        self.SetSizer(sizer)

    def show_child(self):
        # Putting a sizer here doesn't work either...
        self.sc.Show()


class NestedScrolledActionPanel(wx.ScrolledWindow):
    """"""
    def __init__(self, parent, target_item=None):
        """Constructor"""
        wx.ScrolledWindow.__init__(self, parent)
        self.SetBackgroundColour("Purple")

        # I don't want to show this at starutp, but hiding it causes the sizer to startup at 20x20!
        # Comment out this line and the sizer set in ActionPanel works, but you see it at startup
        self.Hide()       

class ConsolePanel(scrolled.ScrolledPanel): 
    """"""
    def __init__(self, parent):
        """Constructor"""

        scrolled.ScrolledPanel.__init__(self, parent, -1)
        self.SetBackgroundColour("Blue")

class MainPanel(wx.Panel):
    """"""
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        mainSplitter = wx.SplitterWindow(self)
        topSplitter = wx.SplitterWindow(mainSplitter)

        self.rightPanel = ActionPanel(topSplitter)
        self.rightPanel.SetBackgroundColour("Green")

        leftPanel = NavPanel(topSplitter, self.rightPanel)
        leftPanel.SetBackgroundColour("Yellow")

        topSplitter.SplitVertically(leftPanel, self.rightPanel, sashPosition=0)
        topSplitter.SetMinimumPaneSize(200)

        bottomPanel = ConsolePanel(mainSplitter)

        mainSplitter.SplitHorizontally(topSplitter, bottomPanel, sashPosition=400)
        mainSplitter.SetSashGravity(1)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(mainSplitter, 1, wx.EXPAND)
        self.SetSizer(sizer)

        return


########################################################################
class MainFrame(wx.Frame):
    """"""
    def __init__(self):
        """Constructor"""

        wx.Frame.__init__(self, None, title="Sizer Test",
                          size=(800,600))

        self.panel = MainPanel(self)

        self.Centre()
        self.Show()

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.timer.Start(2000)

    def OnTimer(self, e):
        self.panel.rightPanel.show_child()

if __name__ == '__main__':
    app = wx.App(redirect=False)
    print "Launching frame"
    frame = MainFrame()
    print "starting mainloop"
    app.MainLoop()

Причина, по которой я хочу, чтобы эта панель была скрыта при запуске графического интерфейса пользователя, заключается в том, что у меня будет много разных панелей, находящихся в этом пространстве ActionPanel (зеленое поле), и когда пользователь щелкает узел дерева в желтом поле, панель, которая отображается в зеленая рамка будет скрыта, и будет показана другая панель. Если я не скрою все панели при запуске, они будут «сложены» друг на друга, и мне придется установить таймер, чтобы пройти и скрыть их все в какой-то момент после запуска графического интерфейса ??? Это кажется странным. Как еще я могу это сделать?


person David Lynch    schedule 04.02.2013    source источник


Ответы (2)


Добавьте self.Layout() в свой метод show_child. Простое отображение дочернего элемента не запускает макет, как событие размера. В тех случаях, когда макет нужно изменить без события размера, вам нужно вызвать Layout самостоятельно.

person RobinDunn    schedule 04.02.2013
comment
Что ж, это сработало для моего небольшого примера здесь, но не для моего более крупного приложения. Мне пришлось вызвать self.Layout () после self.sc.Show (), а не до него. Почему бы вам не вызвать self.sc.Layout ()? Я все еще в замешательстве. Что делают эти методы под капотом? - person David Lynch; 05.02.2013
comment
Да, более сложные макеты могут усложнить понимание подобных вещей. Использование WIT (wiki.wxpython.org/Widget_Inspection_Tool) действительно может помочь диагностировать проблемы с макетом и способы работы вокруг них. В общем, я обнаружил, что обычно работает для вызова метода Layout окна, которое владеет сайзером, который необходимо отрегулировать, хотя иногда нужно вызывать родительский Layout. - person RobinDunn; 06.02.2013
comment
Очень круто .. добавление этого в закладки. Еще раз спасибо за вашу помощь. Я наконец-то пробил стену в большом приложении. Я отвечу на свой вопрос, чтобы подробно рассказать об этом, но вы получите чек. - person David Lynch; 06.02.2013

У меня было много проблем, чтобы создать простой случай для Stack Overflow, но это выявило только вторую проблему, на которую ответил РобинДанн. Другая моя, более раздражающая проблема заключалась в том, что я пытался добавить к объекту два измерителя. Только последний получил калибратор, остальные были 20х20, и я не мог понять.

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

some_object= wx.Panel(self)  # Could be anything
sizer = BoxSizer(wx.VERTICAL)
sizer.Add(some_object, 1, wx.EXPAND)
sizer.SetSizer(sizer)

something_else = wx.Panel(self)  # Could be anything
something_else.Hide()
sizer = BoxSizer(wx.VERTICAL)
sizer.Add(something_else, 1, wx.EXPAND)
sizer.SetSizer(sizer)

Но я должен был сделать вот что:

some_object= wx.Panel(self)  # Could be anything
something_else = wx.Panel(self)  # Could be anything
something_else.Hide()
sizer = BoxSizer(wx.VERTICAL)
sizer.Add(some_object, 1, wx.EXPAND)
sizer.Add(something_else, 1, wx.EXPAND)
sizer.SetSizer(sizer)

Затем, конечно же, выполняйте функцию Layout () после каждого показа / скрытия различных панелей, и спустя 36 часов после этого я вылечился!

person David Lynch    schedule 06.02.2013