Can't go back to wxpython main frame after creating and destroying Dialogue using ShowModal via Pubsub

665 views Asked by At

I am programming an application using wxpython and wx.lib.pubsub. in python 2.7.3

1- There is a Frame with a menu item. When this menu is clicked, a message is published by pubsub.

2- This message destroys (if possible) and creates a "first level" dialogue.

3- "First Level" dialogue has an list of valules and an "add value" button. (NOTE: Such list of variables can be modified so I am trying to update this list)

4- When the "add value" button is clicked, another message is published by pubsub.

5- This message creates a "Second Level" dialogue, so a new name for the new variable can be written.

6- There is a "continue" button in this "second level" dialogue which has two consequences:

First one: Self.Destroy();

Second one: goes to step 2, i.e. destroys the "first level" dialogue and creates it again.

To that point the program seems to work fine, however, when I finish "adding" variables to the "first level" dialogue I Destroy it and then I cannot go back to the main Frame stated in step 1.

Why is this happening?

All the Dialogues are shown via ShowModal(). However if I use only Show() it seems to work fine but, since the program has many menus and items, ShowModal() is preferred. Any idea why it works with Show() but not with ShowModal()?

If there is a simpler way to perform the task I want to do, it would be appreciated.

import wx
from wx.lib.pubsub import Publisher as pub

class itemReceiver(object):
    def __init__(self):
        pub.subscribe(self.__OnShowDialog, 'show.dialog')

    def __OnShowDialog(self, message):
        self.dlgParent = message.data[0]
        print str(self.dlgParent)
        self.valuesToShow = message.data[1]
        print self.valuesToShow
        #try to destroy dialog before creating a new one
        try:
            self.manageParametersDialog.Destroy()
        except:
            pass   
        self.manageParametersDialog = manageParamsDialog(self.dlgParent,  self.valuesToShow)
        print "ready to show first level dialogue"
        self.manageParametersDialog.ShowModal() #if .Show() instead, there is no problem

class secondaryReceiver(object):
    def __init__(self):
        pub.subscribe(self.__OnShowDialog, 'add.item')

    def __OnShowDialog(self, message):
        dlgParent = message.data[0]
        dlgGrandParent = message.data[1]
        self.variableList = message.data[2]
        editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
        editParameterDialog.ShowModal()

class manageParamsDialog (wx.Dialog):
    def __init__(self, parent, valueList):
        self.valueList = valueList
        self.parent = parent
        wx.Dialog.__init__(self, parent, -1, "first level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 
        sizer=wx.BoxSizer(wx.VERTICAL)
        self.optionList = wx.ListBox(self, -1, size=(200, 70), choices = valueList)
        sizer.Add(self.optionList)
        addButton = wx.Button(self, -1, 'Add New')
        self.Bind(wx.EVT_BUTTON, self.OnButton, addButton)
        sizer.Add(addButton)
        cancelButton = wx.Button(self, -1, 'Cancel')
        self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
        sizer.Add(cancelButton)
        self.SetSizer(sizer)
        self.Fit()
    def OnButton (self, e):
        pub.sendMessage('add.item', [self, self.parent, self.valueList])
    def OnCancel(self,e):
        self.Destroy()

class editParamDlg(wx.Dialog):
    def __init__(self, parent, grandParent, variableList):
        self.variableList = variableList
        self.grandParent = grandParent
        wx.Dialog.__init__(self, parent, -1, "second level dialogue", style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 
        hboxSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.textInput = wx.TextCtrl(self, -1)
        hboxSizer.Add(self.textInput)
        addButton = wx.Button(self, -1, 'Continue')
        self.Bind(wx.EVT_BUTTON, self.OnAdd, addButton)
        hboxSizer.Add(addButton)
        cancelButton = wx.Button(self, -1, 'Cancel')
        self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)
        hboxSizer.Add(cancelButton)
        self.SetSizer(hboxSizer)
        self.Fit()

    def OnAdd(self, e):
        self.variableList.append(self.textInput.GetValue())
        self.Destroy()
        pub.sendMessage('show.dialog',[self.grandParent, self.variableList])
    def OnCancel(self,e):
        self.Destroy()

class ToolbarFrame(wx.Frame):
#this ToolbarFrame is the main window, with a Toolbar and a white panel below.
    def __init__(self, parent, id):    
        wx.Frame.__init__(self, parent, id, "this is a frame", size=(480, 320))
        myPanel = wx.Panel(self)
        myPanel.SetBackgroundColour("White")
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        menuItem = wx.MenuItem(fileMenu, -1, "menu item", "opens dialog via pubsub") 
        self.Bind(wx.EVT_MENU, self.OnMenuItem, menuItem)
        fileMenu.AppendItem(menuItem)
        menuBar.Append(fileMenu, "File")
        self.SetMenuBar(menuBar)


    def OnMenuItem(self, e):
        pub.sendMessage('show.dialog', [self, ["one", "two", "three"]])


app = wx.PySimpleApp()
frame = ToolbarFrame(parent=None, id=-1)
frame.Show()
newItemListener = itemReceiver()
editParameterListener = secondaryReceiver()
app.MainLoop()
1

There are 1 answers

1
Joran Beasley On BEST ANSWER

try changing secondaryReciever as follows

class secondaryReceiver(object):
    def __init__(self):
        pub.subscribe(self.__OnShowDialog, 'add.item')

    def __OnShowDialog(self, message):
        dlgParent = message.data[0]
        dlgGrandParent = message.data[1]
        self.variableList = message.data[2]
        editParameterDialog = editParamDlg(dlgParent, dlgGrandParent, self.variableList)
        editParameterDialog.ShowModal()
        #this line will not execute till the dialog closes
        self.dlgParent.optionList.SetItems(editParameterDialog.variableList)
        editParameterDialog.Destroy()

and also change editParamDlg

def OnAdd(self, e):
    self.variableList.append(self.textInput.GetValue())
    self.Close()

the problem was that you would call the show.modal from that OnAdd ... which would try to destroy the existing window and then open a new one... but the old one wasnt destroyed ... this left weird remnants that caused you errors ... and really all you want to do is update the item list ...