Reputation:
I have a problem with my menu in WxPython! In the file header I have 'File' and in that I have 2 options, 'Save' and 'Close'...When I click save, I want it to print "Saved" and when I clock quit, the application should print "Closed" and close...But if I click even save it's closing! So can you please help me. Here is a part of my code:
menubar = wx.MenuBar()
fileMenu = wx.Menu()
menubar.Append ( fileMenu, '&File' )
m1 = fileMenu.Append ( wx.ID_EXIT, 'Save' )
self.Bind ( wx.EVT_MENU, self.OnSave, m1 )
m2 = fileMenu.Append ( wx.ID_EXIT, 'Quit' )
self.Bind ( wx.EVT_MENU, self.OnQuit, m2 )
self.SetMenuBar ( menubar )
And the functions:
def OnSave ( self, event ):
text = self.text_ctrl.GetValue()
fil.write ( text )
print ( "Saved file")
def OnQuit ( self, event ):
print ( "Closed" )
self.Close()
Upvotes: 0
Views: 632
Reputation: 22443
You are using the same Id
i.e. wx.ID_EXIT
for both menu items, which as @Petr Blahos has pointed out, is causing your problem.
There is however an issue with Petr's answer, whilst technically correct,
wx.NewId
is now Deprecated
and although it still works, it has been replaced by wx.NewIdRef
.
wx.NewId()
Generates an integer identifier unique to this run of the program.
Return type
int
Deprecated IDs generated by this function can possibly conflict with IDs used elsewhere in the application code. It is recommended to instead use the wx.ID_ANY ID to assign generated IDs for the controls, menu items and etc. that you create in the application. These IDs are guaranteed to not conflict with the other IDs that are in use in the application. For those cases where you need to create an ID that can be used more than once then please see wx.NewIdRef.
wx.NewIdRef(count=1)
Reserves a new Window ID (or range of WindowIDs) and returns a wx.WindowIDRef object (or list of them) that will help manage the reservation of that ID.
This function is intended to be a drop-in replacement of the old and deprecated wx.NewId function, with the added benefit that the ID should never conflict with an in-use ID or other IDs generated by this function.
wx.NewIdRef
also has a count
function, so it can be used to grab
a group of id's that you use as required. i.e.
>>> myIds = wx.NewIdRef(count=6)
>>> myIds
[WindowIDRef: -31973, WindowIDRef: -31972, WindowIDRef: -31971, WindowIDRef: -31970, WindowIDRef: -31969, WindowIDRef: -31968]
>>> useId = myIds[3].Id
>>> useId
-31970
Note that wx.NewIdRef
, wx.ID_ANY
and -1
can all be used in this menu context. See this simple example:
import wx
class Test(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,title="Frame aka Window",size = (300,200))
panel = wx.Panel(self)
self.status=self.CreateStatusBar()
self.status.SetStatusText("Status bar text")
menubar=wx.MenuBar()
firstm=wx.Menu()
secondm=wx.Menu()
fm1 = wx.MenuItem(firstm, wx.NewIdRef(), 'New Window\tAlt+N')
firstm.Append(fm1)
self.Bind(wx.EVT_MENU, self.OnMenu1, id=fm1.GetId())
fm2 = wx.MenuItem(firstm, wx.NewIdRef(), 'Open', "Text for the statusbar")
firstm.Append(fm2)
self.Bind(wx.EVT_MENU, self.OnMenu2, id=fm2.GetId())
fm3 = wx.MenuItem(firstm, -1, 'Quit\tAlt+Q')
firstm.Append(fm3)
self.Bind(wx.EVT_MENU, self.OnMenu3, id=fm3.GetId())
sm1 = wx.MenuItem(firstm, wx.ID_ANY, 'Re-Do', "Statusbar Re-Do")
secondm.Append(sm1)
self.Bind(wx.EVT_MENU, self.OnsMenu1, id=sm1.GetId())
sm2 = wx.MenuItem(secondm, wx.ID_ANY, 'Un-Do', "Statusbar Un-Do")
secondm.Append(sm2)
self.Bind(wx.EVT_MENU, self.OnsMenu2, id=sm2.GetId())
menubar.Append(firstm,"File")
menubar.Append(secondm,"Edit")
self.SetMenuBar(menubar)
t = wx.StaticText(panel,-1,"Hello i'm a test", pos=(10,20))
def OnMenu1(self, event):
print("Menu item 1",event.GetId())
def OnMenu2(self, event):
print("Menu item 2",event.GetId())
def OnMenu3(self, event):
print("Menu item 3 Quit",event.GetId())
self.Destroy()
def OnsMenu1(self, event):
print("2nd Menu item 1",event.GetId())
def OnsMenu2(self, event):
print("2nd Menu item 2",event.GetId())
if __name__=='__main__':
app=wx.App()
frame=Test(None)
frame.Show()
app.MainLoop()
Upvotes: 1
Reputation: 2433
The first parameter of fileMenu.Append is important. It is used to tell one menu item from the other one, but you used the same value for both.
m1 = fileMenu.Append(wx.ID_SAVE, 'Save')
self.Bind(wx.EVT_MENU, self.OnSave, m1)
m2 = fileMenu.Append(wx.ID_EXIT, 'Quit')
self.Bind(wx.EVT_MENU, self.OnQuit, m2)
In my programs I prefer getting a free id from system, using wx.NewId(). If you have these "stock" menu entries, ID_SAVE and ID_EXIT make perfect sense, but if you make your own entries, you can do:
m3 = fileMenu.Append(wx.NewId(), 'My own menu item')
self.Bind(wx.EVT_MENU, self.OnMyOwnFunction, m3)
m4 = fileMenu.Append (wx.NewId(), 'Another menu item')
self.Bind(wx.EVT_MENU, self.OnAnotherFunction, m4)
Upvotes: 0