Search code examples
pythonpycharmevent-handlingwxpythonframe

wxpython: pause code as long as second frame is open


I'm pretty much a Python beginner and have only recently started with wxpython and now have the following question:

I'm writing an application where one window is open and by clicking a button, the user opens a second window, where they're supposed to input their name and click another button. My problem is that I don't know how to pause the 'event code' that is executed by clicking Button1 until the user is done with their actions in the second window.

Is there a way to pause the code in OnButton1 (after the line secondframe.Show() until the user has input their name in the SecondFrame and clicked on OnButton2?

Essentially my goal is that first, the name of the user is printed and only afterwards, Done is printed

class MainFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)

        self.panel = wx.Panel(self)
        self.Button1 = wx.Button(self.panel, label='Button 1', pos=(20, 10), size=(90, 25))

        #Set event handlers
        self.Button1.Bind(wx.EVT_BUTTON, self.OnButton1)

    def OnButton1(self, e):
        secondframe = SecondFrame(None)
        secondframe.Show()
        print("Done")



class SecondFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)

        self.panel = wx.Panel(self)
        self.Button2 = wx.Button(self.panel, label='Button 2', pos=(50, 20), size=(90, 25))
        self.NameBox = wx.TextCtrl(self.panel, value="Type Your Name", pos=(50, 60), size=(200, -1))


        #Set event handlers
        self.Button2.Bind(wx.EVT_BUTTON, self.OnButton2)

    def OnButton2(self, e):
        Name = self.NameBox.GetValue()
        print(Name)


app = wx.App(False)
frame = MainFrame(None)
frame.Show()
app.MainLoop()


Solution

  • I don't know of a way to actually block the code there. (Also, blocking is generally speaking never a good idea.)
    But you can get the same behaviour like this:

    • Where you open the second window, in the first Window you call self.Disable()
    • When creating the second window, you also hand a reference to the first window to it (i.e. secondframe = SecondFrame(None, self)), adjust the constructor (def __init__(self, parent, main):) and store this in a variable there (self.mainFrame = main).
    • You add a method to MainFrame, e.g. reenable(self)
    • there you call self.Enable()
    • When you're done with Frame two, you can simply call self.mainFrame.reenable()

    All in all, that would make something like:

    class MainFrame(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent)
    
            self.panel = wx.Panel(self)
            self.Button1 = wx.Button(self.panel, label='Button 1', pos=(20, 10), size=(90, 25))
    
            #Set event handlers
            self.Button1.Bind(wx.EVT_BUTTON, self.OnButton1)
    
        def OnButton1(self, e):
            secondframe = SecondFrame(None, self)
            self.Disable()
            secondframe.Show()
    
        def reenable(self):
            self.Enable()
            print("done")
    
    
    
    class SecondFrame(wx.Frame):
        def __init__(self, parent, main):
            wx.Frame.__init__(self, parent)
            self.mainFrame = main
    
            self.panel = wx.Panel(self)
            self.Button2 = wx.Button(self.panel, label='Button 2', pos=(50, 20), size=(90, 25))
            self.NameBox = wx.TextCtrl(self.panel, value="Type Your Name", pos=(50, 60), size=(200, -1))
    
    
            #Set event handlers
            self.Button2.Bind(wx.EVT_BUTTON, self.OnButton2)
    
        def OnButton2(self, e):
            Name = self.NameBox.GetValue()
            print(Name)
            self.mainFrame.reenable()
    
    
    app = wx.App(False)
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()