0

I want to buid my applications under the idea of an MVC, with sepparate GUI and controller. In addition, I have a workmate much better than me in graphical tasks, and we want to distribute the work: he build the graphical part with wxFormBuilder and I build the "machinery" of the application.

When I have the GUI generated, I want substitute some elements that wxFormbuilder cannot manage: by example, the wxObjectListView. My idea is create a GUI with a normal wxListBox, import it with the main program, and substitute it with an wxObjectListView. I don't want to modify directly the generated code by wxFormBuilder, because I want to maintain the backwards compatibility with the GUI editor.

The problem and the question are: from the main program that imports the GUI, how can I access the sizer that contains the list, delete and substitute by a ObjectListView? Something like sizer.Delete(list) and then sizer.Add(olv)...

Here you are an example:

The GUI code generated by wxFormBuilder: a Frame with a list and a button.

# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Sep  8 2010)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################

import wx

###########################################################################
## Class MyFrame1
###########################################################################

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 330,288 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        fgSizer = wx.FlexGridSizer( 2, 1, 0, 0 )
        fgSizer.AddGrowableCol( 0 )
        fgSizer.AddGrowableRow( 0 )
        fgSizer.SetFlexibleDirection( wx.BOTH )
        fgSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

        m_listBox1Choices = [ u"Row1", u"Row2" ]
        self.m_listBox1 = wx.ListBox( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_listBox1Choices, 0 )
        fgSizer.Add( self.m_listBox1, 1, wx.ALL|wx.EXPAND, 5 )

        self.m_button1 = wx.Button( self, wx.ID_ANY, u"MyButton", wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer.Add( self.m_button1, 1, wx.ALL|wx.EXPAND, 5 )

        self.SetSizer( fgSizer )
        self.Layout()

        self.Centre( wx.BOTH )

    def __del__( self ):
        pass

And here is the main code, that imports the graphical class.

from __future__ import print_function
# -*- coding: utf-8 -*-
import wx
from olvGUI import MyFrame1

class Ventana(MyFrame1):

    def inicia(self):
        hijos = self.GetChildren()
        for h in hijos:
            print(h)


if __name__ == "__main__":
    app = wx.App(False)
    v = Ventana(None)
    v.inicia()
    v.Show()
    app.MainLoop()

When I attempt to access the Frame children, I only see the "final" objects, not the Sizer.

<wx._controls.ListBox; proxy of <Swig Object of type 'wxListBox *' at 0x1e0cea8> >
<wx._controls.Button; proxy of <Swig Object of type 'wxButton *' at 0x19a5f90> >

Maybe the GUI must have another structure if I want make it his elements accesibles, but I have no idea how to make it. I have tried make two levels of sizers, and the final result is the same: I can access the final elements, not the sizers.

4

1 回答 1

1

You will need to change fgSizer to self.fgSizer so you can access it later. Then you can use the sizer's Remove method to remove the widget. There is an Insert method that you can use to insert another widget in it's place.

See the documentation on sizers for full details:

Because you are removing and inserting a widget, you will most likely need to call Layout at the end of that method. This article has an example:

Finally, here's an example of getting the sizer:

import wx

########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title='Test')
        self.panel = wx.Panel(self)

        sizer = wx.BoxSizer(wx.VERTICAL)

        btn = wx.Button(self.panel, label="Get sizer")
        btn.Bind(wx.EVT_BUTTON, self.onGetSizer)
        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
        self.panel.SetSizer(sizer)

        self.Show()

    #----------------------------------------------------------------------
    def onGetSizer(self, event):
        """"""
        sizer = self.panel.GetSizer()

if __name__ == '__main__':
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Here is an example of saving your widget's index:

self.widget_dict = {}
some_boxsizer.Add(some_widget)  # this is the first widget, so its ID is zero
self.widget_dict[some_widget] = 0

Now in your event handler, you can use this dictionary to determine what widget is in which index:

index = self.widget_dict[some_widget]
于 2015-05-15T13:51:49.933 回答