What event is used when I close a tab in an auinotebook? I tested with
EVT_AUINOTEBOOK_PAGE_CLOSE(D). It didn't work.
I would also like to fire a right click on the tab itself event.
Where can I find all the events that can be used with the aui manager/notebook? Might just be my poor searching skills, but I can't find any lists over the different events that exist, not for mouse/window events either. It would be really handy to have a complete list.
#!/usr/bin/python
#12_aui_notebook1.py
import wx
import wx.lib.inspection
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.nb = wx.aui.AuiNotebook(self)
self.new_panel('Page 1')
self.new_panel('Page 2')
self.new_panel('Page 3')
self.nb.Bind(wx.EVT_AUINOTEBOOK_PAGE_CLOSED, self.close)
def new_panel(self, nm):
pnl = wx.Panel(self)
pnl.identifierTag = nm
self.nb.AddPage(pnl, nm)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(self.sizer)
def close(self, event):
print 'closed'
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, '12_aui_notebook1.py')
frame.Show()
self.SetTopWindow(frame)
return 1
if __name__ == "__main__":
app = MyApp(0)
# wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
Oerjan Pettersen
This is the bind command you want:
self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSED, self.close, self.nb)
To detect a right click on the tab (e.g. to show a custom context menu):
self.Bind(wx.aui.EVT_AUINOTEBOOK_TAB_RIGHT_DOWN, self.right, self.nb)
Here's a list of the aui notebook events:
EVT_AUINOTEBOOK_PAGE_CLOSE
EVT_AUINOTEBOOK_PAGE_CLOSED
EVT_AUINOTEBOOK_PAGE_CHANGED
EVT_AUINOTEBOOK_PAGE_CHANGING
EVT_AUINOTEBOOK_BUTTON
EVT_AUINOTEBOOK_BEGIN_DRAG
EVT_AUINOTEBOOK_END_DRAG
EVT_AUINOTEBOOK_DRAG_MOTION
EVT_AUINOTEBOOK_ALLOW_DND
EVT_AUINOTEBOOK_DRAG_DONE
EVT_AUINOTEBOOK_BG_DCLICK
EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
EVT_AUINOTEBOOK_TAB_MIDDLE_UP
EVT_AUINOTEBOOK_TAB_RIGHT_DOWN
EVT_AUINOTEBOOK_TAB_RIGHT_UP
From: {python folder}/Lib/site-packages/{wxpython folder}/wx/aui.py
Related
I'm trying to create an App which allows the user to switch the information show using buttons. The basic idea of the code is that the user sees buttons on the left side of the screen and when the user presses "button 1", the code shows Panel1. I've made 2 buttons so far and the code for 2 panels is written as well but i can't figure out how to update my MainFrame so it show a different panel when one of the buttons is pressed.
Code:
import wx
TabNumber = 1
class ButtonPanel(wx.Panel):
def __init__(self, parent):
global TabNumber
super(ButtonPanel, self).__init__(parent, -1)
self.Tab1Button = wx.Button(self, label="TAB 1")
self.Tab1Button.Bind(wx.EVT_BUTTON, self.SwitchTab(1))
self.Tab2Button = wx.Button(self, label="TAB 2")
self.Tab2Button.Bind(wx.EVT_BUTTON, self.SwitchTab(2))
self.Sizer = wx.BoxSizer(wx.VERTICAL)
self.Sizer.Add(self.Tab1Button, wx.CENTER,0)
self.Sizer.Add(self.Tab2Button, wx.CENTER, 0)
self.SetSizer(self.Sizer)
def SwitchTab(self, tab):
def OnClick(event):
print(f"Switch to tab {tab} started")
TabNumber = tab
print(TabNumber)
return OnClick
class Panel1(wx.Panel):
def __init__(self, parent):
super(Panel1, self).__init__(parent, -1)
self.panel = wx.Panel(self)
self.text = wx.StaticText(self.panel, label="1")
class Panel2(wx.Panel):
def __init__(self, parent):
super(Panel2, self).__init__(parent, -1)
self.panel = wx.Panel(self)
self.text = wx.StaticText(self.panel, label="2")
class MainFrame(wx.Frame):
def __init__(self):
super(MainFrame, self).__init__(None, -1, "Test Application")
self.Panels = {
"Panel1": Panel1(self),
"Panel2": Panel2(self)
}
self.MySizer = wx.BoxSizer(wx.HORIZONTAL)
self.tabpanel = ButtonPanel(self)
self.MySizer.Add(self.tabpanel,wx.CENTER,0)
self.InfoPanel = self.Panels["Panel"+str(TabNumber)]
self.MySizer.Add(self.InfoPanel, wx.CENTER,0)
self.SetSizer(self.MySizer)
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
I was also wondering how I can adjust the ratio for the space that is given to my ButtonPanel and my InfoPanel.
As far as I can see, you are trying to do something that works like a Wizard... On the one hand, you can use wx.adv.Wizard. On the other hand, you can look at this tutorial that does something very similar and adapt it to what you need:
WXPython: How to create a generic wizard
Good luck!
I would like to make a wxpython program that has a notification center just like the one on windows or mac. Whenever I have a message, the message will show inside the the notification panel, and the user could close that message afterwards.
I have a sample code for illustration as follows:
import wx
import wx.lib.scrolledpanel as scrolled
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
topPanel = wx.Panel(self)
panel1 = wx.Panel(topPanel, -1)
button1 = wx.Button(panel1, -1, label="generate message")
self.panel2 = scrolled.ScrolledPanel(
topPanel, -1, style=wx.SIMPLE_BORDER)
self.panel2.SetAutoLayout(1)
self.panel2.SetupScrolling()
button1.Bind(wx.EVT_BUTTON, self.onAdd)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(panel1,-1,wx.EXPAND|wx.ALL,border=10)
sizer.Add(self.panel2,-1,wx.EXPAND|wx.ALL,border=10)
self.sizer2 = wx.BoxSizer(wx.VERTICAL)
topPanel.SetSizer(sizer)
self.panel2.SetSizer(self.sizer2)
def onAdd(self, event):
new_text = wx.TextCtrl(self.panel2, value="New Message")
self.sizer2.Add(new_text,0,wx.EXPAND|wx.ALL,border=1)
self.panel2.Layout()
self.panel2.SetupScrolling()
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'frame')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
In the above I code, the right panel (i.e. panel2) serves as a notification center that all the messages should shown inside it. On the left panel (i.e. panel1) I have a button to generate message just to mimic the notification behavior. Ideally the message on the right panel should be a message box that you could close (maybe a frame? Or a MessageDialog?)
Any hint or advice is much appreciated, and an example would be the best!
Thanks!
Finally figured out myself, it was easier than I initially thought.
Here is the code:
import wx
import wx.lib.scrolledpanel as scrolled
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
self.number_of_panels = 0
topPanel = wx.Panel(self)
panel1 = wx.Panel(topPanel, -1)
button1 = wx.Button(panel1, -1, label="generate message")
self.panel2 = scrolled.ScrolledPanel(
topPanel, -1, style=wx.SIMPLE_BORDER)
self.panel2.SetAutoLayout(1)
self.panel2.SetupScrolling()
button1.Bind(wx.EVT_BUTTON, self.onAdd)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(panel1,0,wx.EXPAND|wx.ALL,border=5)
sizer.Add(self.panel2,1,wx.EXPAND|wx.ALL,border=5)
self.sizer2 = wx.BoxSizer(wx.VERTICAL)
topPanel.SetSizer(sizer)
self.panel2.SetSizer(self.sizer2)
def onAdd(self, event):
self.number_of_panels += 1
panel_label = "Panel %s" % self.number_of_panels
panel_name = "panel%s" % self.number_of_panels
new_panel = wx.Panel(self.panel2, name=panel_name, style=wx.SIMPLE_BORDER)
self.closeButton = wx.Button(new_panel, label='Close %s' % self.number_of_panels)
self.closeButton.panel_number = self.number_of_panels
self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
self.sizer2.Add(new_panel,0,wx.EXPAND|wx.ALL,border=1)
self.panel2.Layout()
self.panel2.SetupScrolling()
def OnClose(self, e):
if self.panel2.GetChildren():
e.GetEventObject().GetParent().Destroy()
self.number_of_panels -= 1
self.panel2.Layout() # Reset layout after destroy the panel
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'frame')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
Basically I can destroy the newly created panel. I just need to know which panel it is when I click the close button. This should work very similar to the Notification Center.
i have two py files that each have its own frame made using wxPython, MainWindow and RecWindow. MainWindow has the RecWindow python file included using the keyword "recovery".
MainWindow code:
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self, parent, wx.ID_ANY,title,pos=(500,200), size = (650,500), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
self.Bind(wx.EVT_CLOSE,self.OnExit)
self.SetIcon(wx.Icon('etc\icons\download.ico', wx.BITMAP_TYPE_ICO))
panel = wx.Panel(self)
RecWindow code:
class RecWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self, parent, wx.ID_ANY,title,pos=(400,200), size = (700,600), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
self.SetIcon(wx.Icon('etc\icons\download.ico', wx.BITMAP_TYPE_ICO))
self.count = 0
when i click on a button in MainWindow , it will hide the MainWindow create an instance of RecWindow, shown below;
def OpenRec(self,event):#this will be used to open the next frame
OR = recovery(None,-1,"RAVE")
OR.Show(True)
MainWindow.Hide()
now, what i am unsure of is how i can return to the MainWindow once i close the RecWindow. RecWindow has a cancel and finish button which both map to a self.close() function. How would i then get MainWindow to show itself again?
Use pubsub to send a message to the main window telling it to Show itself again. I actually have an example of how to do that here:
http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
Note that this tutorial is using slightly older API that was available in wxPython 2.8. If you're using wxPython 2.9, then you'll have to use the slightly different API that I detail in this article:
http://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/
When you create an instance of RecWindow keep a reference to it on main_window and bind to its close event.
In the main_window's close handler check if the window closed was the RecWindow.
If it was, clear the reference to it and show the main_window.
Elif the closed window was main_window carry out any required code.
Finally call event.Skip() so the windows get destroyed.
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, (500, 200), (650, 500),
wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
panel = wx.Panel(self)
button = wx.Button(panel, wx.ID_OPEN)
panel.sizer = wx.BoxSizer(wx.VERTICAL)
panel.sizer.Add(button, 0, wx.ALL, 7)
panel.SetSizer(panel.sizer)
button.Bind(wx.EVT_BUTTON, self.on_button)
self.Bind(wx.EVT_CLOSE, self.on_close)
self.rec_window = None
def on_button(self, event):
rec_window = RecWindow(self, 'Rec window')
rec_window.Show()
self.Hide()
rec_window.Bind(wx.EVT_CLOSE, self.on_close)
self.rec_window = rec_window
def on_close(self, event):
closed_window = event.EventObject
if closed_window == self.rec_window:
self.rec_window = None
self.Show()
elif closed_window == self:
print 'Carry out your code for when Main window closes'
event.Skip()
class RecWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, (400, 200), (700, 600),
wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
app = wx.App(False)
main_window = MainWindow(None, 'Main window')
main_window.Show()
app.MainLoop()
Hi, everyone.
I have a little python GUI program based on wxPython 2.8.x.
It create a wx.Dialog widget and show the dialog by calling ShowModal().
At some situation, the wx.Dialog will show a wx.PopupWindow with a wx.ListCtrl locate inside.
The wx.PopupWindow appears correctly, but trouble comes.
wx.ListCtrl, and its parent widget, wx.PopupWindow, couldn't receive any mouse event,
this cause wx.ListCtrl and wx.PopupWindow have no response while user generate any mouse action.
If wx.Dialog is opened by calling Show(),the above situation won't happen, wx.PopupWindow and wx.ListCtrl work correctly.
However, the above situation won't happen in windows version of wxPython 2.8.x even if we show wx.Dialog by calling ShowModal(),it happen in linux only.
Any suggestion?
Thanks.
Here is my source code.
It may be too long but is easy enough to test the above situation (just copy and paste).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import wx
class TestPopupWindow(wx.PopupWindow): # modify here to change different Widget
def __init__(self, *args, **kwargs):
super(TestPopupWindow, self).__init__(*args, **kwargs)
self.SetSize((200, 200))
self.testButton = wx.Button(self, label='Test')
self.testButton.Bind(wx.EVT_BUTTON, self.__onEvtButton, self.testButton)
self.Show()
def __onEvtButton(self, event):
event.Skip()
print 'PopupWindow: test button pushed!'
self.Hide()
class TestDialog(wx.Dialog):
def __init__(self, *args, **kwargs):
wx.Dialog.__init__(self, *args, **kwargs)
panel = wx.Panel(self)
panel.SetAutoLayout(True)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Fit(panel)
sizer.SetSizeHints(panel)
panel.SetSizer(sizer)
for i in xrange(2):
ctrl = wx.TextCtrl(panel)
sizer.Add(ctrl, 0, wx.ADJUST_MINSIZE|wx.EXPAND, 0)
for i in xrange(2):
ctrl = wx.ComboBox(panel)
sizer.Add(ctrl, 0, wx.ADJUST_MINSIZE|wx.EXPAND, 0)
self.openPopupWindowButton = wx.Button(panel, label='Open PopupWindow')
sizer.Add(self.openPopupWindowButton, 0, 0, 0)
standardDialogButtonSizer = wx.StdDialogButtonSizer()
self.standardDialogButtonSizerOK = wx.Button(panel, wx.ID_OK)
standardDialogButtonSizer.AddButton(self.standardDialogButtonSizerOK)
self.standardDialogButtonSizerCancel = wx.Button(panel, wx.ID_CANCEL)
standardDialogButtonSizer.AddButton(self.standardDialogButtonSizerCancel)
standardDialogButtonSizer.Realize()
sizer.Add(standardDialogButtonSizer, 0, wx.EXPAND, 0)
panel.Layout()
# event binding
self.openPopupWindowButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpenPopupWindow, self.openPopupWindowButton)
self.popupWindow = None
# event handler
def __onEvtButtonOpenPopupWindow(self, event):
event.Skip()
if self.popupWindow is not None:
self.popupWindow.Close()
self.popupWindow = TestPopupWindow(self)
class TestFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
panel = wx.Panel(self)
panel.SetAutoLayout(True)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Fit(panel)
sizer.SetSizeHints(panel)
panel.SetSizer(sizer)
self.openButton = wx.Button(panel, label='Open Dialog')
sizer.Add(self.openButton, 0, 0, 0)
self.openPopupWindowButton = wx.Button(panel, label='Open PopupWindow')
sizer.Add(self.openPopupWindowButton, 0, 0, 0)
panel.Layout()
# event binding
self.openButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpen, self.openButton)
self.openPopupWindowButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpenPopupWindow, self.openPopupWindowButton)
self.Show()
self.popupWindow = None
# event handler
def __onEvtButtonOpenPopupWindow(self, event):
event.Skip()
if self.popupWindow is not None:
self.popupWindow.Close()
self.popupWindow = TestPopupWindow(self)
def __onEvtButtonOpen(self, event):
event.Skip()
dialog = TestDialog(self, title='TestDialog')
result = dialog.ShowModal()
if result == wx.ID_OK:
print >>sys.stderr, 'OK!'
else:
print >>sys.stderr, 'Cancel!'
def main(argv=sys.argv[:]):
app = wx.PySimpleApp()
frame = TestFrame(None, title='TestFrame', style=wx.TAB_TRAVERSAL|wx.DEFAULT_FRAME_STYLE)
app.SetTopWindow(frame)
app.MainLoop()
return 0
if __name__ == '__main__':
sys.exit(main())
Instead of using a PopupWindow, just show a second wx.Dialog. Or open a frame. PopupWindows can be kind of weird with complex widgets like the ListCtrl.
How can I find out from which AuiNotebook page an event occurred?
EDIT: Sorry about that. Here are a code example. How do I find the notebook page
from witch the mouse was clicked in?
#!/usr/bin/python
#12_aui_notebook1.py
import wx
import wx.lib.inspection
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.nb = wx.aui.AuiNotebook(self)
self.new_panel('Pane 1')
self.new_panel('Pane 2')
self.new_panel('Pane 3')
def new_panel(self, nm):
pnl = wx.Panel(self)
self.nb.AddPage(pnl, nm)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(self.sizer)
pnl.Bind(wx.EVT_LEFT_DOWN, self.click)
def click(self, event):
print 'Mouse click'
#How can I find out from witch page this click came from?
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, '12_aui_notebook1.py')
frame.Show()
self.SetTopWindow(frame)
return 1
if __name__ == "__main__":
app = MyApp(0)
# wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
Oerjan Pettersen
For a mouse click you can assume the current selected page is the one that got the click. I added a few lines to your code. See comments
def new_panel(self, nm):
pnl = wx.Panel(self)
# just to debug, I added a string attribute to the panel
# don't you love dynamic languages? :)
pnl.identifierTag = nm
self.nb.AddPage(pnl, nm)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(self.sizer)
pnl.Bind(wx.EVT_LEFT_DOWN, self.click)
def click(self, event):
print 'Mouse click'
# get the current selected page
page = self.nb.GetPage(self.nb.GetSelection())
# notice that it is the panel that you created in new_panel
print page.identifierTag