Hi. I need to have two frames (not necessarily visible together and possibly more than two), and I need to be able to interact between them.

For example - if I have two frames, one visible and one not visible. Clicking a button on frame1 will make frame1 invisible and frame2 visible. On frame2 I might want to edit the contents of a list that is on frame1, so that when frame2 becomes invisible/closes and frame1 becomes visible again, the updates to the list (or other controls) would already have been made.

I have used wxGlade to create code with two frames, but I cant seem to work out how to show, hide or otherwise interact between them. The closest I have come is by doing this in a button event on frame1:

frame_2 = Window2(None, -1, "")
frame_2.label_2.SetLabel("fred")
frame_2.Show()

This seems to work, but only up to a point, because when I try to access anything on frame1 from frame2 I only open another instance of frame1. Clearly I have something fundamentally wrong!

Could someone point me in the right direction please, either by explaining how to access the controls on multiple forms, or perhaps explaining a better way to do this?

Many thanks

Max

I think we had that just a few weeks ago, anyway here is an example how to do this ...

# create two frames with wxFrame, only one is showing

import wx

class Frame1(wx.Frame):
    def __init__(self, parent, mytitle):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle)
        self.SetBackgroundColour("green")
        # pass frame1 to frame2 as instance self
        self.frame2 = Frame2(None, 'Frame1', self)

        # create input widgets
        self.button1 = wx.Button(self, wx.ID_ANY, label='Frame2')
        self.button2 = wx.Button(self, wx.ID_ANY, label='Button2')
        self.button3 = wx.Button(self, wx.ID_ANY, label='Button3')
        # bind mouse event to an action
        self.button1.Bind(wx.EVT_BUTTON, self.button1Click)

        # use a box sizer to lay out widgets
        sizer_v = wx.BoxSizer(wx.VERTICAL)
        # Add(widget, proportion, flag, border)
        sizer_v.Add(self.button1, 0, flag=wx.ALL, border=10)
        sizer_v.Add(self.button2, 0, flag=wx.ALL, border=10)
        sizer_v.Add(self.button3, 0, flag=wx.ALL, border=10)
        self.SetSizer(sizer_v)

        # size the frame so all the widgets fit
        self.Fit()

    def button1Click(self, event):
        """button1 has been left clicked"""
        # self is instance frame1
        self.Hide()
        self.frame2.Show()


class Frame2(wx.Frame):
    def __init__(self, parent, mytitle, frame1):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle)
        self.SetBackgroundColour("brown")
        self.frame1 = frame1

        # create input widgets
        self.button1 = wx.Button(self, wx.ID_ANY, label='Frame1')
        self.button2 = wx.Button(self, wx.ID_ANY, label='Button2')
        self.button3 = wx.Button(self, wx.ID_ANY, label='Button3')
        # bind mouse event to an action
        self.button1.Bind(wx.EVT_BUTTON, self.button1Click)
        # responds to exit symbol x on frame2 title bar
        self.Bind(wx.EVT_CLOSE, self.button1Click)

        # use a box sizer to lay out widgets
        sizer_v = wx.BoxSizer(wx.VERTICAL)
        # Add(widget, proportion, flag, border)
        sizer_v.Add(self.button1, 0, flag=wx.ALL, border=10)
        sizer_v.Add(self.button2, 0, flag=wx.ALL, border=10)
        sizer_v.Add(self.button3, 0, flag=wx.ALL, border=10)
        self.SetSizer(sizer_v)

        # size the frame so all the widgets fit
        self.Fit()

    def button1Click(self, event):
        """button1 has been left clicked"""
        # self is instance frame2
        self.Hide()
        self.frame1.Show()


app = wx.App()
# create a MyFrame instance and show the frame
frame1 = Frame1(None, 'Frame1')
frame1.Show()
app.MainLoop()

I think we had that just a few weeks ago

My apologies - I must confess that I didn't use the search before I posted.

And.. Excellent, many thanks. That code works nicely and I can transfer what I need into my own application.

Regards

Max

One more thing...

So far the Frames have all been created at run time - by this I mean, when I exit Frame1, Frame2 still has to be destroyed itself before the application will close gracefully. This is not a problem, however, is there a way to create and open a frame that has not previously been created?

Let me explain: If I have x frames in the application, can I have Frame1 create and open Frame2 etc, which will destroy itself when it closes. The next time it is needed, it will be re-created for the purpose. This means that only the frames in current use are in memory.

Sorry if I have over complicated something very simple. In other languages the Frames (or Windows) can be loaded and closed explicitly, thus saving memory, and I am assuming that Python can behave in the same way.

Regards

Max

EDIT
Ah! [Slaps Forehead]
I answered it myself, of course the line: "self.frame2 = Frame2(None, 'Frame1', self)" can be called directly from the command button that opens the frame! Doh!

Thanks for all your help.

regards

Max

MaxVK, good thinking!
Having your frame in hiding will be better for execution speed, but if you are worried about memory, you have to switch your approach.

...but if you are worried about memory, you have to switch your approach

Hmm. Care to expand on that? I like to hear about other ways of doing things.

Cheers

Max

Execution speed to me is the first consideration and the I will see how to make use of minimum possible memory!

The beauty of programming is different approaches to same problem. It is like beauty of looking different race of the same human beings! heeh!

Yes, Ill agree with you there - speed of execution is the key since most machines today have plenty of memory to spare, however, I still like to keep things as slim as possible.

regards

Max

This article has been dead for over six months. Start a new discussion instead.