user237076
user237076

Reputation:

wxPython: call a wxApp from another wxApp

Is it possible to run a wxApp from another wxApp? I am trying to simply call a program I wrote (called DataDeck) from a method of another wxApp, like it was a plugin.

something like:

def on_datadeck_btn_click(self, event):
        import datadeck.main
        datadeck.main.run()
        event.Skip()

where datadeck.main.run() is a classic start of a wxApp:

def run():
    app = DataDeck(0)
    app.SetAppName("DataDeck")
    app.MainLoop()

Right now, it correctly opens DataDeck the first time and it works, but it won't reopen DataDeck a second time after I close it. This would freeze everything.

Update: based on @Mike Driscoll answer, I documented myself more and came to the following solution:

I added an "entry point" in datadeck

def run_as_plugin():
    #[do some stuff related to XRC layouts and sysout redirection]
    MainGUI = datadeck.gui.maingui.MainGUI()

Where the constructor of MainGUI() automatically shows the wxFrame. Now my application behaves like it was a component of the caller wxApp. Therefore, I modify the application method as follows:

def on_datadeck_btn_click(self, event):
    import datadeck.main
    datadeck.main.run_as_plugin()
    event.Skip()

It was very simple, indeed! I just had to modify my objects that deal with stdout redirection (not part of this question, I omit the details), and everything worked fine.

Upvotes: 2

Views: 1509

Answers (2)

Mike Driscoll
Mike Driscoll

Reputation: 33101

There should only be on wx.App. From what I've read online, you can't have two wx.App objects running in one script. You could probably do it using the subprocess module to open a new process though. Take a look at Editra to see some examples for how to do plugins. It is included with wxPython or you can download it separately.

Upvotes: 1

joaquin
joaquin

Reputation: 85683

It is perfectly feasible. Not sure why it doesnt work for you.
This example works perfectly:

--main.py--

import wx

class MainFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title='Main', size=(353,270))
        button= wx.Button(self, -1, 'call app', pos=(10,10), size=(-1,30))
        self.Bind(wx.EVT_BUTTON, self.capp, button)

    def capp(self, event):
        import datadeck
        datadeck.run()

if __name__ == '__main__':
    app = wx.App(0)
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()

--datadeck.py--

import wx

class DDFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title='DDFrame', size=(353,270))
        button = wx.Button(self, -1, 'print something', pos=(100,100), size=(-1,30))
        self.Bind(wx.EVT_BUTTON, self.say_hello, button)

    def say_hello(self, event):
        print 'something'

class DataDeck(wx.App):
    def OnInit(self):
        frame = DDFrame(None)
        frame.Show()
        return True

def run():
    app = DataDeck(1)
    app.SetAppName("DataDeck")
    app.MainLoop()

if you press the 'call app' button you get the new frame open. And you can open as many as you want.
Created aplications/frames are independent of each other. You can close any of them without affecting the others. And the system doesnt freeze.

Upvotes: 0

Related Questions