Steve Freedenburg wrote:
let's say I have 2 instances of a button on a frame.
And those 2 buttons are bound to an event.
___Snip___
I looked at how Robin's book did this sort of thing and came up with
def onEvent(self, event):
item = self.GetMenuBar().FindItemById(event.GetId())
text = item.GetText()
wx.MessageBox("You selected the '%s' item" % text)
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()
</code>
Notice the GetMenuBar() and FindItemById() methods. You'll probably also
like the FindMenuItem() method (which I'm not using) helpful.
···
Subject: Re: [wxpython-users] GetEventObject() /
From: Mike Driscoll <mike@pythonlibrary.org>
-------------------
Mike Driscoll
Hi!
In my case could not find the find method when I wrote mine which is
helpful as Mike pointed out. The other way is to make a copy of all the
menu's and storing
the ID of each. It is better to have the computer assign the id's instead of
making one, but my example does use sequential ID's which could run into
duplication.
I discovered in my example that having all the menu's stored inside a
global list is another approach, but did not even know the find method
existed. In either case the dictionary you want to have located would also
have to use the ID as a key which I assume you are doing to be able to find
that dictionary.
so take a look at my approach and I use the self.menuItems as the
storage place of all the menu's.
My example only stores what is needed for the handler call and what it
needs and that is the text of the menu. Now that text also could be the key
for the dictionary, I guess depending on how you store your dictionaries...
The menu text is the HotKey text and there is a built in function for
that as you will see when you go down to the OnMenu handler Call.
#LAST MODIFIED SUNDAY, AUGUST 10 2008
#ADDED MENUITEMS LIST FOR ID SEARCH.
#MODIFIED WEDNESDAY, JULY 23 2008
#CREATED TUPLES FOR ALL MENU ITEMS!
#ADDED MENUBAR_SETTINGS TO FIND SETTINGS PARMS.
#MODIFIED TUESDAY, JULY 22 2008
#ADDED OR WENT BACK TO SLIDER CONTROL FOR BETTER MOVEMENT USING PAGE UP AND
DOWN!
#ERASE ALL MAX AND MIN CHECKS INSIDE FUNCTION SETVOICE!
#MODIFIED MONDAY, JULY 21 2008
#ADDED SPIN CONTROL FOR VOICE SETTINGS!
#ADDED KEY EVENT FOR SPIN CONTROL SO ENTER KEY EXITS AND KILLS SPIN!
#MODIFIED THURSDAY, JULY 17 2008
#ADDED TTS2 A DICTIONARY OF VOICES TO CONTROL ANY TYPE OF VOICE, SAPI 4 OR
SAPI 5
#ADDED TTSP POINTER TO WHICH VOICE TO USE!
#ADDED CHANGE VOICE TOGGLE FUNCTION AND VOICE MENU ITEM FOR THE VOICE
CHANGE!
#MODIFIED TUESDAY, JULY 15 2008
#ADDED THE SAPI 4 ENGINE FOR EXTRA VOICES.
desc="""In the following example we use a sizer with vertical layout"""
#Editor.py
import wx
import os
#import errors2file
import Sapi5, Sapi4
tts5 = Sapi5.Create( {"name":"Mary"})
tts4 = Sapi4.Create( {"name":"Fred"})
#tts = tts5
TS4=4
TS5=5
TTS2 = {TS4:tts4, TS5:tts5}
purge = tts5._purge
async = tts5._async
punc = tts5._punc
ID=0
class MenuParms( object):
def __init__(self, id4item, hk4item, khlp4item, handler4item):
self.id4item = id4item
self.hk4item = hk4item
self.khlp4item = khlp4item
self.handler4item = handler4item
class MainWindow( wx.Frame):
def __init__(self, parent, id, title):
self.ttsp = TS5
self.tts = TTS2[ TS5]
self.dirname=os.getcwd() #SEARCH FROM PRESENT DIRECTORY!
self.filename=""
#CREATING A TUPLE WITHIN A TUPLE FOR THE MENUBAR!
self.items4menu = (
("File", (
MenuParms(102, "&Open", " Open a file to edit", self.OnOpen),
MenuParms(103, "&Save", " save file to disk", self.OnSave),
MenuParms(104, "&Edit", " Do editing", self.Do_Edit),
MenuParms(101, "&About", " Information about this program",
self.OnAbout),
MenuParms(109, "E&xit", " Terminate the program", self.OnExit),
), #END OF FILE PARMS!
), #END OF FILE MENU!
("Voice", (
MenuParms(202, "&Read", " Open a file to read",
self.OnWav2Read),
MenuParms(203, "&Save", " save text to audio file",
self.OnSave2Wav),
MenuParms(204, "&Text", " read text field", self.OnRead),
MenuParms(205, "&Quit", " Stop Reading", self.OnQuitRead),
MenuParms(206, "Tts&4", " Sapi 4 test", self.OnTtsRead),
MenuParms(207, "&Change TTS", " Change-Toggle Sapi 4 to 5",
self.OnTtsFlip),
), #END OF VOICE PARMS!
), #END OF VOICE MENU!
("Settings", (
MenuParms(302, "&Speaker", " Name for voice", self.OnSettings),
MenuParms(303, "&Rate", " Rate for voice", self.OnSettings),
MenuParms(304, "&Pitch", " Pitch for voice", self.OnSettings),
MenuParms(305, "&Volume", " Volume for voice", self.OnSettings),
) #END OF SETTINGS PARMS!
) #END OF SETTINGS MENU!
) #END OF ITEMS FOR MENU!
wx.Frame.__init__(self, parent, wx.ID_ANY, title)
self.control = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE)
self.control.Bind( wx.EVT_KEY_UP, self.OnKey_Up) #, self.control)
self.control.Bind( wx.EVT_KEY_DOWN, self.OnKey_Down) #,
self.control)
self.control.Bind( wx.EVT_CHAR, self.OnKey) #, self.control)
self.CreateStatusBar() #A Statusbar in the bottom of the window
#Setting up the menubar.
self.menuBar = wx.MenuBar()
self.menuItems = wx.Menu()
for menuname, items in self.items4menu:
menu = wx.Menu()
for o in items:
menu.Append( o.id4item, o.hk4item, o.khlp4item)
self.menuItems.Append( o.id4item, o.hk4item, o.khlp4item)
menu.AppendSeparator()
wx.EVT_MENU(self, o.id4item, o.handler4item)
wx.EVT_MENU_HIGHLIGHT(self, o.id4item, self.OnMenu)
if menuname == "Settings":
menu.Bind( wx.EVT_CHAR, self.OnKey) #, menu)
self.menuBar.Append( menu, menuname)
# Adding the MenuBar to the Frame content.
self.SetMenuBar( self.menuBar)
# Use some sizers to see layout options
self.sizer=wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.control,1,wx.EXPAND)
#Layout sizers
self.SetSizer(self.sizer)
self.SetAutoLayout(1)
self.sizer.Fit(self)
self.Show(1)
#TEXT CONTROL KEYS!
def OnMenu(self, event):
event.Skip()
id4btn = event.GetId()
label4btn = self.menuItems.GetLabelText( id4btn)
TTS2[ self.ttsp].Speak( label4btn)
def OnKey(self, event):
"KEY CAPTURE FOR EDITING! MUST USE EVT_CHAR FOR ALL CODES."
event.Skip()
k = event.GetKeyCode()
m = event.GetModifiers()
#comment rk = event.GetRawKeyCode() #not in all platforms
#comment uk = event.GetUnicodeKey() #Not on platforms that unicode
was not installed!#comment
ch=""
if k<256:
self.sayCap( chr(k))
#CHECK FOR BACK SPACE DELETE!
def OnKey_Down(self, e):
"CAPTURE KEY BEING DELETED BEHIND PRESENT POSITION!"
e.Skip()
k = e.GetKeyCode()
m = e.GetModifiers()
c = self.control.GetInsertionPoint() #present line column position
when event fired!
if c>0 and k == wx.WXK_BACK:
col, line = self.control.PositionToXY( c)
col-=1
if col<0:
line-=1
col = self.control.GetLineLength( line) #length of line
specified!
c = self.control.XYToPosition( col, line)
ch = self.control.GetRange( c,c+1)
pt = self.tts.getPitch()
self.tts.setPitch( pt -30)
rt = self.tts.getRate()
self.tts.setRate( rt -10)
if ch:
if ord(ch)==10: ch="Return"
elif ord(ch)==wx.WXK_SPACE: ch="space"
TTS2[ self.ttsp].Speak( ch, purge, punc)
self.tts.setPitch( pt)
self.tts.setRate( rt)
#KEY UP OR KEY RELEASED!
def OnKey_Up(self, event):
"SAY CHAR OR LINE ON WHEN KEY RELEASED!"
event.Skip()
k = event.GetKeyCode()
m = event.GetModifiers()
c = self.control.GetInsertionPoint() #present line column position
when event fired!
tl = self.control.GetLastPosition() #last point in textctrl
colmax, linemax = self.control.PositionToXY( tl)
col, line = self.control.PositionToXY( c)
lx = self.control.GetLineLength( line) #length of line specified!
#comment c = self.control.XYToPosition( col, line) #CURSOR POSITION!
cs = self.control.XYToPosition( 0, line) #LINE START!
ce = self.control.XYToPosition( lx, line) #LINE END!
ch = self.control.GetRange( c,c+1)
if ch:
if ord(ch)==10: ch="Return"
elif ord(ch)==wx.WXK_SPACE: ch="space"
elif c==tl and k in [wx.WXK_RIGHT, wx.WXK_END]: ch="end of text"
if c<tl and event.ControlDown() and k in [wx.WXK_LEFT,
wx.WXK_RIGHT]:
for i in range(c+1, c+lx-col):
ch2 = self.control.GetRange( i,i+1)
if ch2=="" or ch2 in "!@ #$%^&*(){}_.,;:": break
else: ch+=ch2
if k in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PAGEUP, wx.WXK_PAGEDOWN]: ch
= self.control.GetRange( cs,ce)
if k in [wx.WXK_INSERT, wx.WXK_DELETE, wx.WXK_HOME, wx.WXK_END,
wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PAGEUP,
wx.WXK_PAGEDOWN]:
if c==0 and (k==wx.WXK_HOME or not event.ControlDown() and
k==wx.WXK_LEFT): ch = " Start Of Text "+ch
self.sayCap( ch) #self.tts.Speak( " %s " % ch, async, punc,
purge)
#SAY CAPITALS IN HIGHER PITCH!
def sayCap(self, ch):
"CHANGE PITCH AND RATE IF AN ALPHA SINGLE CHAR!"
if len(ch)==1 and ch.isalpha() and ch.isupper():
pt = self.tts.getPitch()
self.tts.setPitch( pt+30)
rt = self.tts.getRate()
self.tts.setRate( rt+30)
if len(ch)==1 and ord(ch)<128:
if ord( ch)==13: ch="Return"
elif ord( ch)==10: ch="Line Feed"
elif ord( ch)==32: ch="space"
self.tts.Speak( " %s " % ch, async, purge, punc)
if len(ch)==1 and ch.isalpha() and ch.isupper():
self.tts.setPitch( pt)
self.tts.setRate( rt)
# VOICE SETTINGS!
def OnSettings(self, e):
"SETTINGS MENU BUTTONS, WHEN ENTERING SAY LABEL OF BUTTON!"
eventType = e.GetEventType()
eventName = e.GetClassName()
self.menuId = e.GetId()
# TTS2[ self.ttsp].Speak( self.menuId)
btn = e.GetEventObject()
label4btn = self.menuItems.GetLabelText( self.menuId)
#NOTE: THE SELF MUST BE USED FOR ANY BTN ITEM IN ORDER TO BE SEEN. ADDED
SELF.FILEMENU INSTEAD OF FILEMENU
# label4btn = btn.filemenu.GetLabelText( 102) #SAYS OPEN!
set_value = " Error In Label!"
min = 0
max = 100
steps = 10
tics = 5
if label4btn == "Speaker":
present = TTS2[ self.ttsp].getVoiceNum()
set_value = TTS2[ self.ttsp].getVoiceName()
max = TTS2[ self.ttsp].getVoiceCount()-1
if self.ttsp==4: min = 1; max+=1
steps = 1
tics = 1
elif label4btn == "Rate":
present = TTS2[ self.ttsp].getRate()
set_value = str( present) +"%"
elif label4btn == "Pitch":
present = TTS2[ self.ttsp].getPitch()
set_value = str( present) +"%"
elif label4btn == "Volume":
present = TTS2[ self.ttsp].getVolume()
set_value = str( present) +"%"
TTS2[ self.ttsp].Speak( " %s %s" % (label4btn, set_value), async,
purge)
#SET UP SPIN CTRL FOR THE SETTING SELECTED!!
self.sldr_ctrl = wx.Slider(
self, 999, present, min, max, (-1, -1), (-1, -1),
wx.SL_AUTOTICKS|wx.SL_HORIZONTAL|wx.SL_LABELS|wx.SL_INVERSE
) #END OF CTRL DEFINITION!
self.sldr_ctrl.Bind( wx.EVT_SLIDER, self.SetVoice, self.sldr_ctrl)
self.sldr_ctrl.Bind( wx.EVT_KEY_UP, self.KillSlider, self.sldr_ctrl)
self.sldr_ctrl.SetFocus()
def KillSlider(self, e):
"KILL THE SPIN CONTROL IF ENTER KEY PRESSED!"
k = e.GetKeyCode()
if k == wx.WXK_RETURN:
TTS2[ self.ttsp].Speak(" %s Set " %
self.menuItems.GetLabelText( self.menuId))
self.Do_Edit( e)
def SetVoice(self,e):
"SET VOICE PARAMETER ADJUSTED!"
btn = e.GetEventObject()
spin_Id = e.GetId()
value = self.sldr_ctrl.GetValue()
max = self.sldr_ctrl.GetMax()
min = self.sldr_ctrl.GetMin()
label4btn = self.menuItems.GetLabelText( self.menuId)
TTS2[ self.ttsp].Speak( " %s %s" % (label4btn, str(value)), async,
purge)
if label4btn == "Speaker":
rt = TTS2[ self.ttsp].getRate()
pt = TTS2[ self.ttsp].getPitch()
TTS2[ self.ttsp].setVoice( value)
if self.ttsp==TS5:
TTS2[ self.ttsp].setRate( rt)
TTS2[ self.ttsp].setPitch( pt)
set_value = TTS2[ self.ttsp].getVoiceName()
elif label4btn == "Rate":
TTS2[ self.ttsp].setRate( value)
set_value = str( value)+"%"
elif label4btn == "Pitch":
TTS2[ self.ttsp].setPitch( value)
set_value = str( value)+"%"
elif label4btn == "Volume":
if value < min+5:
TTS2[ self.ttsp].setVolume( 50)
TTS2[ self.ttsp].Speak( "Volume Minimum!")
value = 0
TTS2[ self.ttsp].setVolume( value)
set_value = str( value)+"%"
TTS2[ self.ttsp].Speak(" %s %s" % (label4btn, set_value), async,
purge)
def OnAbout(self,e):
"A dialog box saying what the editor is about!"
text = " A sample editor with voice \n in wxPython."
self.tts.Speak( "About A Sample Editor!"+text)
d= wx.MessageDialog( self, text, "About Sample Editor", wx.OK)
# Create a message dialog box
d.ShowModal() # Shows it
d.Destroy() # finally destroy it when finished.
def OnExit(self,e):
self.Close(True) # Close the frame.
def OnOpen(self,e):
""" Open a file"""
self.setFilePath( "o")
f=open(os.path.join(self.dirname, self.filename),'r')
self.control.SetValue(f.read())
f.close()
def OnSave(self,e):
""" Save a file"""
self.setFilePath( "s")
f=open(os.path.join(self.dirname, self.filename),'w')
# self.control.SetValue(f.read())
f.write( self.control.GetValue())
f.close()
def setFilePath(self, type4file=""):
" Search directory for path and file name!"
fn=self.filename
t4f = wx.OPEN
if type4file[0] in "sS":
t4f = wx.SAVE|wx.FD_OVERWRITE_PROMPT
# fn = self.filename
dlg = wx.FileDialog(self, self.filename +" or Choose a file",
self.dirname, fn, "*.*", t4f)
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetFilename()
self.dirname = dlg.GetDirectory()
dlg.Destroy()
def OnWav2Read(self,e):
""" Open a file to read"""
self.setFilePath( "o")
self.tts.SpeakFromWav( os.path.join(self.dirname, self.filename),
async, purge)
def OnSave2Wav(self,e):
""" Save text to a wav file"""
self.setFilePath( "s")
self.tts.SpeakToWav( os.path.join(self.dirname, self.filename),
self.control.GetValue())
def OnRead(self,e):
""" Read the text"""
self.tts.Speak( self.control.GetValue(), async, purge)
def OnQuitRead(self,e):
""" Quit the reading of the text"""
self.tts.Speak( " Talking Stopped!", purge)
def OnTtsRead(self,e):
"""SAPI 4 TEST!"""
tts4.Speak( " Sapi %d, %s Talking!" % (tts4.getVoiceNum(),
tts4.getVoiceName()))
tts4.setVoiceByName( "Sandy")
tts4.Speak( " Number of Sapi 4 voices: %d!" % tts4.getVoiceCount())
def OnTtsFlip(self,e):
""" FLIP THE TTS ENGINE FOR SETTING ADJUSTMENTS!"""
if self.ttsp==TS4:
self.ttsp=TS5
txt="Sapi 5 Now!"
else:
self.ttsp=TS4
txt="Sapi 4 Now!"
#TTS2[ self.ttsp].Speak( txt)
self.tts = TTS2[ self.ttsp] #.Speak( txt)
self.tts.Speak( txt)
def Do_Edit(self,e):
""" Edit the file"""
if self.sldr_ctrl:
self.sldr_ctrl.Destroy()
self.control.SetFocus()
app = wx.PySimpleApp()
frame = MainWindow(None, -1, "Voice Editor")
app.MainLoop()