I am making a quick and dirty soundboard using the wxPython package and was wondering how to go by implementing a scroll-list of sounds to play.
Here is a picture of what I am trying to convey:
http://i.imgur.com/av0E5jC.png
and here is my code so far:
import wx
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass,self).__init__(*args,**kwargs)
self.basicGUI()
def basicGUI(self):
panel = wx.Panel(self)
menuBar = wx.MenuBar()
fileButton = wx.Menu()
editButton = wx.Menu()
exitItem = fileButton.Append(wx.ID_EXIT, 'Exit','status msg...')
menuBar.Append(fileButton, 'File')
menuBar.Append(editButton, 'Edit')
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.Quit, exitItem)
wx.TextCtrl(panel,pos=(10,10), size=(250,150))
self.SetTitle("Soundboard")
self.Show(True)
def Quit(self, e):
self.Close()
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
My question remains, how does one load a list of sounds on that panel and click a certain button to play that sound. I don't really care about implementing pause and fast forward features since this is only going to play really quick sound files.
Thanks in advance.
Just removed the text widget, replaced by a listbox, and hooked a callback on item click, slightly elaborate: when clicking, it finds the position of the item, retrieves the label name and fetches the filename in the dictionary
(we want to play a .wav file with a path, but not necessarily display the full filename)
I refactored the code so callbacks and other attributes are private, helps the lisibility.
import wx
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass,self).__init__(*args,**kwargs)
self.__basicGUI()
def __basicGUI(self):
panel = wx.Panel(self)
menuBar = wx.MenuBar()
fileButton = wx.Menu()
editButton = wx.Menu()
exitItem = fileButton.Append(wx.ID_EXIT, 'Exit','status msg...')
menuBar.Append(fileButton, 'File')
menuBar.Append(editButton, 'Edit')
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.__quit, exitItem)
self.__sound_dict = { "a" : "a.wav","b" : "b.wav","c" : "c2.wav"}
self.__sound_list = sorted(self.__sound_dict.keys())
self.__list = wx.ListBox(panel,pos=(20,20), size=(250,150))
for i in self.__sound_list: self.__list.Append(i)
self.__list.Bind(wx.EVT_LISTBOX,self.__on_click)
#wx.TextCtrl(panel,pos=(10,10), size=(250,150))
self.SetTitle("Soundboard")
self.Show(True)
def __on_click(self,event):
event.Skip()
name = self.__sound_list[self.__list.GetSelection()]
filename = self.__sound_dict[name]
print("now playing %s" % filename)
def __quit(self, e):
self.Close()
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
Related
I'm trying to pull data from a text entry dialog box that's opened by a button click event using wxpython using this code.
import wx
class apple(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'PyLabs', size=(840,600))
panel = wx.Panel(self)
box = wx.TextEntryDialog(None, 'hi', 'hi', 'hi')
status_bar = self.CreateStatusBar()
menu_bar = wx.MenuBar()
options_menu = wx.Menu()
options_menu.Append(wx.NewId(), "Settings", "OpenSettings...")
options_menu.Append(wx.NewId(), "Advanced", "Check Advanced...")
menu_bar.Append(options_menu, "Options")
self.SetMenuBar(menu_bar)
New_Experiment_Button = wx.Button(panel, pos=(10,10), label='New Experiment', size=(120, 40))
answer = self.Bind(wx.EVT_BUTTON, self.openFrame, New_Experiment_Button)
print(answer)
def openFrame(self, event):
box = wx.TextEntryDialog(None, 'hi', 'hi', 'hi')
if box.ShowModal() == wx.ID_OK:
answer = str(box.getValue)
event.Skip()
return answer
if __name__=='__main__':
app=wx.PySimpleApp()
frame = apple(parent=None, id=-1)
frame.Show()
app.MainLoop()
I'm extremely new to wxpython coding and i don't understand how i'm to grab the data pulled by the button event when it's called from inside the Bind() function.
The output of print(answer) is "None"
If anybody could help me with this it'd be greatly appreciated!
Why not just have the print in the function, why would you need to return it to def __init__ ?
def openFrame(self, event):
box = wx.TextEntryDialog(None, 'hi', 'hi', 'hi')
if box.ShowModal() == wx.ID_OK:
answer = box.GetValue()
event.Skip()
print answer
The "answer" is box.GetValue(), however you have a few more issues with your experiment, see below, check the differences
Edited with reference to your comments, store you result in a self variable and see the difference in the Bind statements on the buttons.
import wx
class apple(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'PyLabs', size=(840,600))
panel = wx.Panel(self)
status_bar = self.CreateStatusBar()
menu_bar = wx.MenuBar()
options_menu = wx.Menu()
options_menu.Append(wx.NewId(), "Settings", "OpenSettings...")
options_menu.Append(wx.NewId(), "Advanced", "Check Advanced...")
menu_bar.Append(options_menu, "Options")
self.SetMenuBar(menu_bar)
New_Experiment_Button = wx.Button(panel, pos=(10,10), label='New Experiment', size=(130, 30))
New_Experiment_Button.Bind(wx.EVT_BUTTON, self.openFrame)
Result_Button = wx.Button(panel, pos=(10,60), label='Result of Experiment', size=(130, 30))
Result_Button.Bind(wx.EVT_BUTTON, self.resultValue)
self.Text = wx.TextCtrl(panel, -1, "Nothing yet", pos=(10,100), size=(200,30))
def openFrame(self, event):
box = wx.TextEntryDialog(None, 'What is your answer', 'Heading','Hi')
if box.ShowModal() == wx.ID_OK:
self.answer = box.GetValue()
box.Destroy()
def resultValue(self, event):
try:
self.Text.SetValue(self.answer)
except:
self.Text.SetValue("No answer yet supplied")
if __name__=='__main__':
app=wx.App()
frame = apple(parent=None, id=-1)
frame.Show()
app.MainLoop()
I'm having trouble getting sensible output when I try to bind menu buttons to a function. First, I pass a few items to create a menu in my application:
imported_applications = ["foo", "bar"]
application_menu = wx.Menu()
for app in imported_applications:
# Create Items
item = wx.MenuItem(application_menu, wx.ID_ANY, app, )
application_menu.Append(item)
# Bind to function
self.Bind(wx.EVT_MENU, self.select_application, item, id=app)
# Add to menubar
menubar.Append(application_menu, '&Applications')
self.SetMenuBar(menubar)
Then I try to get that parameter when select_application is called:
def select_application(self, event):
id_selected = event.GetId()
print(id_selected)
Outputs:
-2014
-2015
Not sure where that is coming from but I expect it to output the id that I set at bind. The contents of imported_applications are two strings, i.e. ["foo", "bar]
app = [ "foo", "bar", ]
for app in ...
Here, your app variable is overwritten.
You are not appending the items correctly.The wx.Menu requires other parameters to its Append method. You should be receiving an error if you run that code as-is. Instead, you'll want to use AppendItem. If you want the menu's label to be printed in the event handler, then you'll have to extraxt the id from the event and use that to acquire the label's text. Here is a demo that does just that:
import wx
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
menuBar = wx.MenuBar()
fileMenu = wx.Menu()
imported_applications = ["foo", "bar"]
for item in imported_applications:
item = wx.MenuItem(fileMenu, wx.ID_ANY, item)
fileMenu.AppendItem(item)
self.Bind(wx.EVT_MENU, self.onMenuPress, item)
menuBar.Append(fileMenu, "&File")
self.SetMenuBar(menuBar)
#----------------------------------------------------------------------
def onMenuPress(self, event):
""""""
menu_id = event.GetId()
obj = event.GetEventObject()
menu_label = obj.GetLabelText(menu_id)
print menu_label
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()
I am trying to set up modified ALT+key accelerators in wxpython that will open the menus in the menubar, but without pressing the ALT key. Hence, pressing the 'R' key in my example below would in theory open the Run menu, but everything that I have tried so far doesn't work. (I have tried sending custom events to the menu item, to the menubar, etc.) It seems that wx.Menu classes just do not have any sort of Popup or Show methods, which would otherwise be ideal. There is of course PopupMenu, but that can't be used for menus that are in a menubar. And menubar doesn't have any useful methods for popping up a menu that is part of it as far as I can tell
import wx
class MainFrame(wx.Frame):
def __init__(self, parent, *args, **kwargs):
wx.Frame.__init__(self, parent, *args, **kwargs)
self.make_menu_bar()
# INSERT MAGIC CODE HERE TO OPEN THE RUN MENU WITHOUT CLICKING ON IT
def make_menu_bar(self):
self.menuRun = wx.Menu()
self.menuRunGo = wx.MenuItem(self.menuRun, -1, "&Go", "", wx.ITEM_NORMAL)
self.menuRun.AppendItem(self.menuRunGo)
self.menuBar = wx.MenuBar()
self.menuBar.Append(self.menuRun, "&Run")
self.SetMenuBar(self.menuBar)
if __name__=='__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
EDIT Here is a snippet trying at this with accelerators
import wx
class MainFrame(wx.Frame):
def __init__(self, parent, *args, **kwargs):
wx.Frame.__init__(self, parent, *args, **kwargs)
self.make_menu_bar()
accelEntries = []
accelEntries.append((wx.ACCEL_NORMAL, ord("R"), self.menuRunId))
accelTable = wx.AcceleratorTable(accelEntries)
self.SetAcceleratorTable(accelTable)
def make_menu_bar(self):
self.menuRun = wx.Menu()
self.menuRunGo = wx.MenuItem(self.menuRun, -1, "&Go", "", wx.ITEM_NORMAL)
self.menuRun.AppendItem(self.menuRunGo)
self.menuBar = wx.MenuBar()
self.menuRunId = self.menuBar.Append(self.menuRun, "&Run")
self.SetMenuBar(self.menuBar)
if __name__=='__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
I am learning wxpython following the tutorials on zetcode about menu bars and status bars. Please forgive me if the question is stupid.
The code below from the website works fine, but I am curious how to hide the status bar by default (when the application window popup).
import wx
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
def InitUI(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
viewMenu = wx.Menu()
self.shst = viewMenu.Append(wx.ID_ANY, 'Show statubar',
'Show Statusbar', kind=wx.ITEM_CHECK)
self.shtl = viewMenu.Append(wx.ID_ANY, 'Show toolbar',
'Show Toolbar', kind=wx.ITEM_CHECK)
viewMenu.Check(self.shst.GetId(), True)
viewMenu.Check(self.shtl.GetId(), True)
self.Bind(wx.EVT_MENU, self.ToggleStatusBar, self.shst)
self.Bind(wx.EVT_MENU, self.ToggleToolBar, self.shtl)
menubar.Append(fileMenu, '&File')
menubar.Append(viewMenu, '&View')
self.SetMenuBar(menubar)
self.toolbar = self.CreateToolBar()
self.toolbar.AddLabelTool(1, '', wx.Bitmap('texit.png'))
self.toolbar.Realize()
self.statusbar = self.CreateStatusBar()
self.statusbar.SetStatusText('Ready')
self.SetSize((350, 250))
self.SetTitle('Check menu item')
self.Centre()
self.Show(True)
def ToggleStatusBar(self, e):
if self.shst.IsChecked():
self.statusbar.Show()
else:
self.statusbar.Hide()
def ToggleToolBar(self, e):
if self.shtl.IsChecked():
self.toolbar.Show()
else:
self.toolbar.Hide()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
I have tried to change one line above into:
viewMenu.Check(self.shst.GetId(), False)
Sadly, that didn't work out.
Willing to hear any advice! Thanks in advance!
Specs: wxpython: 2.8.12.1; python 2.7; Ubuntu 12.04
IMHO, because viewMenu.Check(..) is called before UI initialization is done (before event loop begin), it may not fire event.
How about manually call ToggleStatusBar method after viewMenu.Check?
def InitUI(self):
....
viewMenu.Check(self.shst.GetId(), False)
self.ToggleStatusBar(None)
This might be what you mean by Just curious if any built-in functions can do that kind of "update" job?
There is a wx.EVT_UPDATE_UI event, i've modifed your code to use it.
UpdateUIEvent
import wx
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
def InitUI(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
viewMenu = wx.Menu()
self.shst = viewMenu.Append(-1, 'Show statubar', 'Show Statusbar',
kind=wx.ITEM_CHECK)
self.shtl = viewMenu.Append(-1, 'Show toolbar', 'Show Toolbar',
kind=wx.ITEM_CHECK)
self.shst.Check(False)
self.shtl.Check(True)
menubar.Append(fileMenu, '&File')
menubar.Append(viewMenu, '&View')
self.SetMenuBar(menubar)
self.toolbar = self.CreateToolBar()
self.toolbar.AddLabelTool(1, '', wx.EmptyBitmap(16, 16))
self.toolbar.Realize()
self.statusbar = self.CreateStatusBar()
self.statusbar.SetStatusText('Ready')
self.Bind(wx.EVT_UPDATE_UI, self.on_update_status_bar, self.statusbar)
self.Bind(wx.EVT_UPDATE_UI, self.on_update_tool_bar, self.toolbar)
self.SetSize((350, 250))
self.SetTitle('Check menu item')
self.Centre()
self.Show(True)
def on_update_status_bar(self, event):
event.Show(self.shst.IsChecked())
def on_update_tool_bar(self, event):
event.Show(self.shtl.IsChecked())
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
I think this way would be better.
statusBarHandle.Hide()
self.SetStatusBar(None) #Disable Status Bar
#Enable
statusBarHandle.Show()
self.SetStatusBar(statusBarHandle) #Back created StatusBar(self.CreateStatusBar function)
#Useful tip: for update all widgets in AUI, use AUI function Update()
#For sizers you need to use the Layout() or Update() function
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