How to get a song to play automatically in WxPython MediaCtrl? - python

I am making a music player and everything goes well except when I click the next button, it loads the next song, but wont play it unless the user presses the play button. Is there anyway to make this play automatically just by hitting the next button and not having to press the play button afterwards. I have tried binding the play function and the load function to the button and that did not work, I have also tried just including mc.Play() in my load function, but that does not work either.
Here is my code:
import wx
import wx.media
import os
class MainWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Music Player',size=(900,670),style=wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN)
wx.Frame.CenterOnScreen(self)
bg = wx.Image('bg.png', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap1 = wx.StaticBitmap(self, -1, bg, (0,0))
panel = wx.Panel(self,style=wx.STAY_ON_TOP)
##MENU AND STATUS BAR
self.status = self.CreateStatusBar()
self.status.SetStatusText('Ready')
menubar = wx.MenuBar()
file_menu = wx.Menu()
view_menu = wx.Menu()
controls_menu = wx.Menu()
help_menu = wx.Menu()
#MENU ID'S
ID_FILE_LOAD = 2
ID_FILE_EXIT = 3
ID_VIEW_SHOW_STATUSBAR = 4
ID_CONTROLS_PLAY = 5
ID_CONTROLS_PAUSE = 6
ID_CONTROLS_STOP = 7
ID_HELP_ABOUT = 8
##FILE MENU
file_menu.Append(ID_FILE_LOAD, "&Load...\tCtrl+L", "This will let you choose a song to load")
file_menu.AppendSeparator()
file_menu.Append(ID_FILE_EXIT,"Exit","This will exit the program")
##VIEW MENU
self.check_statusbar = view_menu.Append(ID_VIEW_SHOW_STATUSBAR,'Show Stat&usbar\tCtrl+U', "This will disable the statusbar", kind=wx.ITEM_CHECK)
view_menu.Check(self.check_statusbar.GetId(), True)
##CONTROLS MENU
controls_menu.Append(ID_CONTROLS_PLAY,"&Play\tEnter", "Play the selected song")
controls_menu.Append(ID_CONTROLS_PAUSE,"&Pause\tSpace", "Pause the selected song")
##MENUBAR APPEND
menubar.Append(file_menu,"File")
menubar.Append(view_menu,"View")
menubar.Append(controls_menu,"Controls")
menubar.Append(help_menu,"Help")
self.SetMenuBar(menubar)
##MENU ACTION BINDING
self.Bind(wx.EVT_MENU, self.Load, None, 2)
self.Bind(wx.EVT_MENU, self.Close, None, 3)
self.Bind(wx.EVT_MENU, self.ToggleStatusBar, self.check_statusbar)
self.Bind(wx.EVT_MENU, self.Play, None, 5)
self.Bind(wx.EVT_MENU, self.Pause, None, 6)
self.Bind(wx.EVT_MENU, self.About, None, 8)
##FONTS
font1 = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
font2 = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
try:
self.mc = wx.media.MediaCtrl(self)
except NotImplementedError:
raise
##BUTTONS
bttnprt = self.bitmap1
loadButton = wx.Button(bttnprt, -1, "Load File...", pos=(308,435), size=(281,31))
self.Bind(wx.EVT_BUTTON, self.Load, loadButton)
playButton = wx.Button(bttnprt, -1, "Play", pos=(458,491), size=(57,57))
self.Bind(wx.EVT_BUTTON, self.Play, playButton)
pauseButton = wx.Button(bttnprt, -1, "Pause", pos=(383,491), size=(57,57))
self.Bind(wx.EVT_BUTTON, self.Pause, pauseButton)
volumeUpButton = wx.Button(bttnprt, -1, "Up", pos=(400,299), size=(95,52))
self.Bind(wx.EVT_BUTTON, self.onSetVolumeUp, volumeUpButton)
volumeDownButton = wx.Button(bttnprt, -1, "Down", pos=(400,363), size=(95,52))
self.Bind(wx.EVT_BUTTON, self.onSetVolumeDown, volumeDownButton)
backButton = wx.Button(bttnprt, -1, "Back", pos=(308,491), size=(57,57))
self.Bind(wx.EVT_BUTTON, self.previousSong, backButton)
nextButton = wx.Button(bttnprt, -1, "Next", pos=(533,491), size=(57,57))
self.Bind(wx.EVT_BUTTON, self.nextSong, nextButton)
self.volumeCtrl = wx.Slider(bttnprt, value=50, minValue=0, maxValue=100, style=wx.SL_VERTICAL|wx.SL_INVERSE, pos=(300,300))
# self.volumeCtrl.Bind(wx.EVT_SLIDER, self.onSetVolume)
self.volumeCtrl.Hide()
songlist = os.listdir('songs')
self.myListBox = listbox = wx.ListBox(bttnprt, -1, (301,80), (296,206), songlist, wx.LB_SINGLE)
self.Bind(wx.EVT_LISTBOX, self.selLoadFile, listbox)
# self.st_file = wx.StaticText(bttnprt, -1, "Blank", pos=(30,30))
def newWin(self, event):
self.new = NewWindow(parent=self, id=-1)
self.new.Show()
def Close(self, event):
box=wx.MessageDialog(None, 'Are you sure you want to exit?', 'Exit program?', wx.YES_NO)
answer=box.ShowModal()
if answer==wx.ID_YES:
self.Destroy()
def About(self, event):
self.new = AboutWindow(parent=self, id=-1)
self.new.Show()
def selLoadFile(self, event):
my_selection = self.myListBox.GetStringSelection()
file_path = os.path.join(os.getcwd(),"songs",my_selection)
self.doLoadFile2(file_path)
def Load(self, event):
dlg = wx.FileDialog(self, "Choose a media file", "songs", "", "*.*", wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self.doLoadFile(path)
dlg.Destroy()
def load2(self):
my_selection = self.myListBox.GetStringSelection()
file_path = os.path.join(os.getcwd(),"songs",my_selection)
self.doLoadFile2(file_path)
self.mc.Play()
def doLoadFile(self, path):
if not self.mc.Load(path):
wx.MessageBox("Unable to load %s: Unsupported format?" % path, "ERROR", wx.ICON_ERROR | wx.OK)
else:
folder, filename = os.path.split(path)
self.mc.SetBestFittingSize()
self.mc.Play()
def doLoadFile2(self, file_path):
if not self.mc.Load(file_path):
wx.MessageBox("Unable to load %s: Unsupported format?" % file_path, "ERROR", wx.ICON_ERROR | wx.OK)
else:
folder, filename = os.path.split(file_path)
#self.st_file.SetLabel('%s' % filename)
self.status.SetStatusText("Now Playing: " +'%s' % filename)
self.mc.SetBestFittingSize()
self.mc.Play()
def Play(self, event):
self.mc.Play()
def Pause(self, event):
self.mc.Pause()
def onSetVolumeUp(self, event):
self.currentVolume = self.volumeCtrl.GetValue()
self.newVolumeAdd = self.currentVolume + 1.5
self.volumeCtrl.SetValue(self.newVolumeAdd)
self.mc.SetVolume(float(self.currentVolume) / 100)
def onSetVolumeDown(self, event):
self.currentVolume = self.volumeCtrl.GetValue()
self.newVolumeSub = self.currentVolume - 1.5
self.volumeCtrl.SetValue(self.newVolumeSub)
self.mc.SetVolume(float(self.currentVolume) / 100)
def previousSong(self, event):
current = self.myListBox.GetSelection()
new = current - 1
self.myListBox.SetSelection(new)
self.mc.Stop()
self.load2()
def nextSong(self, event):
current = self.myListBox.GetSelection()
new = current + 1
self.myListBox.SetSelection(new)
self.mc.Stop()
self.load2()
def ToggleStatusBar(self, e):
if self.check_statusbar.IsChecked():
self.status.Show()
self.status.SetStatusText('Ready')
else:
self.status.Hide()
##RUN##
if __name__=='__main__':
app=wx.PySimpleApp()
frame=MainWindow(parent=None,id=-1)
frame.Show()
app.MainLoop()

If this is windows, and possibly specifically Win 7, 64bit, you need to do 2 things to get this to work.
As J.F. Sebastian mentioned, you need to call the play from a method that is bound to the EVT_MEDIA_LOADED event. The docs actually mention this.
Specify a backend when you create the MediaCtrl. I'm not sure why its needed, but it didn't work for me until I did that.
So try the following changes:
...
#change this existing line
self.mc = wx.media.MediaCtrl(self, szBackend=wx.media.MEDIABACKEND_WMP10)
...
# add this new line
self.Bind(wx.media.EVT_MEDIA_LOADED, self.song_is_loaded)
...
# add this new method
def song_is_loaded(self, event):
self.mc.Play()
You can also remove all the self.mc.Play() calls now except the one in the Play() function itself (since loading the file will now cause it to play).
I also noticed you've defined a bunch of ID_XXX constants, but then just used numbers when you bound your menu buttons.

Related

Learning Python: RuntimeError: wrapped C/C++ object of type StaticBitmap has been deleted

I'm currently learning to program with Python, I got this example code for a simple image viewer (see below), which produces the following error message when I close the app, run it again and open any directory to browse the images in it:
File "...\image_viewer4.py", line 103, in update_photo
self.image_ctrl.SetBitmap(wx.Bitmap(img))
RuntimeError: wrapped C/C++ object of type StaticBitmap has been
deleted.
This happens every time unless I restart the kernel in Spyder.
I already read through PyQt: RuntimeError: wrapped C/C++ object has been deleted, Understanding the “underlying C/C++ object has been deleted” error, and Can a PyQt4 QObject be queried to determine if the underlying C++ instance has been destroyed?, but I don't understand what causes the error in the code example above. I mean, the error states that the bitmap object is deleted but i have no clue as to how or why.
I appreciate any productive help anyone can give me. I'd like to understand what exactly causes the error in the code and how to avoid it.
Here is the code:
import glob
import os
import wx
from pubsub import pub
class ImagePanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
disW, disH = wx.DisplaySize()
self.max_size = 800
self.photos = []
self.current_photo = 0
self.total_photos = 0
self.layout()
pub.subscribe(self.update_photos_via_pubsub, "update")
def layout(self):
"""
Layout the widgets on the panel
"""
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
img = wx.Image(self.max_size, self.max_size)
self.image_ctrl = wx.StaticBitmap(self, wx.ID_ANY,
wx.Bitmap(img))
self.main_sizer.Add(self.image_ctrl, 0, wx.ALL|wx.CENTER, 5)
self.image_label = wx.StaticText(self, label="")
self.main_sizer.Add(self.image_label, 0, wx.ALL|wx.CENTER, 5)
btn_data = [("Previous", btn_sizer, self.on_previous),
("Next", btn_sizer, self.on_next)]
for data in btn_data:
label, sizer, handler = data
self.btn_builder(label, sizer, handler)
self.main_sizer.Add(btn_sizer, 0, wx.CENTER)
self.SetSizer(self.main_sizer)
def btn_builder(self, label, sizer, handler):
"""
Builds a button, binds it to an event handler and adds it to a sizer
"""
btn = wx.Button(self, label=label)
btn.Bind(wx.EVT_BUTTON, handler)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
def on_next(self, event):
"""
Loads the next picture in the directory
"""
if not self.photos:
return
if self.current_photo == self.total_photos - 1:
self.current_photo = 0
else:
self.current_photo += 1
self.update_photo(self.photos[self.current_photo])
def on_previous(self, event):
"""
Displays the previous picture in the directory
"""
if not self.photos:
return
if self.current_photo == 0:
self.current_photo = self.total_photos - 1
else:
self.current_photo -= 1
self.update_photo(self.photos[self.current_photo])
def update_photos_via_pubsub(self, photos):
self.photos = photos
self.total_photos = len(self.photos)
self.update_photo(self.photos[0])
self.current_photo = 0
def update_photo(self, image):
"""
Update the currently shown photo
"""
img = wx.Image(image, wx.BITMAP_TYPE_ANY)
# scale the image, preserving the aspect ratio
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.max_size
NewH = self.max_size * H / W
else:
NewH = self.max_size
NewW = self.max_size * W / H
img = img.Scale(NewW, NewH)
self.image_ctrl.SetBitmap(wx.Bitmap(img))
self.Refresh()
def reset(self):
img = wx.Image(self.max_size,
self.max_size)
bmp = wx.Bitmap(img)
self.image_ctrl.SetBitmap(bmp)
self.current_photo = 0
self.photos = []
class MainFrame(wx.Frame):
def __init__(self):
disW, disH = wx.DisplaySize()
super().__init__(None, title='Image Viewer',
size=(disW-500, disH-100))
self.panel = ImagePanel(self)
# create status bar
self.CreateStatusBar()
# create the menu bar
menuBar = wx.MenuBar()
# create a menu
fileMenu = wx.Menu()
openBut = wx.MenuItem(fileMenu, wx.ID_OPEN, '&Open', 'Open Working Directory')
fileMenu.Append(openBut)
fileMenu.Bind(wx.EVT_MENU, self.on_open_directory, openBut)
# add a line separator to the file menu
fileMenu.AppendSeparator()
# add a quit button to fileMenu
quitBut = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit', 'Exit the Programm')
fileMenu.Append(quitBut)
# connect the quit button to the actual event of quitting the app
fileMenu.Bind(wx.EVT_MENU, self.onQuit, quitBut)
# give the menu a title
menuBar.Append(fileMenu, "&File")
# connect the menu bar to the frame
self.SetMenuBar(menuBar)
self.create_toolbar()
self.Show()
def create_toolbar(self):
"""
Create a toolbar
"""
self.toolbar = self.CreateToolBar()
self.toolbar.SetToolBitmapSize((16,16))
open_ico = wx.ArtProvider.GetBitmap(
wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16,16))
openTool = self.toolbar.AddTool(
wx.ID_ANY, "Open", open_ico, "Open an Image Directory")
self.Bind(wx.EVT_MENU, self.on_open_directory, openTool)
self.toolbar.Realize()
def on_open_directory(self, event):
"""
Open a directory dialog
"""
with wx.DirDialog(self, "Choose a directory",
style=wx.DD_DEFAULT_STYLE) as dlg:
if dlg.ShowModal() == wx.ID_OK:
self.folder_path = dlg.GetPath()
photos = glob.glob(os.path.join(self.folder_path, '*.jpg'))
if photos:
pub.sendMessage("update", photos=photos)
else:
self.panel.reset()
def onQuit(self, event):
# get the frame's top level parent and close it
wx.GetTopLevelParent(self).Destroy()
if __name__ == '__main__':
app = wx.App(redirect=False)
frame = MainFrame()
app.MainLoop()
In case they are needed, here is the traceback:
File "...\image_viewer4.py", line 183, in on_open_directory
pub.sendMessage("update", photos=photos)
File "C:\Anaconda\lib\site-packages\pubsub\core\publisher.py", line 216, in sendMessage
topicObj.publish(**msgData)
File "C:\Anaconda\lib\site-packages\pubsub\core\topicobj.py", line 452, in publish
self.__sendMessage(msgData, topicObj, msgDataSubset)
File "C:\Anaconda\lib\site-packages\pubsub\core\topicobj.py", line 482, in __sendMessage
listener(data, self, allData)
File "C:\Anaconda\lib\site-packages\pubsub\core\listener.py", line 237, in __call__
cb(**kwargs)
File "...\image_viewer4.py", line 84, in update_photos_via_pubsub
self.update_photo(self.photos[0])
It isn't immediately obvious but I notice that you don't cancel your pubsub subscription.
Try:
def onQuit(self, event):
# get the frame's top level parent and close it
pub.unsubscribe(self.panel.update_photos_via_pubsub, "update")
wx.GetTopLevelParent(self).Destroy()
See if that makes a difference.
To ensure that onQuit is also executed when closing the application by using the X in the top right of the frame, use the following (in MainFrame) :
self.Bind(wx.EVT_CLOSE, self.onQuit)
That should cover all the bases.
That may be the same issue as in
Defining a wx.Panel destructor in wxpython
It may come from the fact that a deleted window, containing the pub.subscribe(), answers the pub.sendMessage().
To avoid this you can try to put in your method the following:
def update_photo(self, image):
if self.__nonzero__():
do something
...
you can see wx.PyDeadObjectError –> RuntimeError in following documentation:
https://wxpython.org/Phoenix/docs/html/MigrationGuide.html

Hiding the menubar in WxPython

I'm trying to find a way to hide the menubar when the mouse isnt over it, i know i could get the mouse xy position and check if its in a certain area but im having no luck hiding the menubar itself.
My code:
class HelloFrame(wx.Frame):
images = []
def __init__(self, *args, **kw):
# ensure the parent's __init__ is called
super(HelloFrame, self).__init__(*args, **kw)
# create a panel in the frame
pnl = wx.Panel(self)
# create a menu bar
self.makeMenuBar()
# and a status bar
#self.CreateStatusBar()
#self.SetStatusText("Welcome to wxPython!")
def makeMenuBar(self):
fileMenu = wx.Menu()
helloItem = fileMenu.Append(-1, "&Load Backround Image")
fileMenu.AppendSeparator()
exitItem = fileMenu.Append(wx.ID_EXIT)
helpMenu = wx.Menu()
aboutItem = helpMenu.Append(wx.ID_ABOUT)
menuBar = wx.MenuBar()
menuBar.Append(fileMenu, "&File")
#menuBar.Append(OptionsMenu, "&Options") TBM
menuBar.Append(helpMenu, "&Help")
# Give the menu bar to the frame
self.SetMenuBar(menuBar)
# Finally, associate a handler function with the EVT_MENU event for
# each of the menu items. That means that when that menu item is
# activated then the associated handler function will be called.
self.Bind(wx.EVT_MENU, self.OpenImage, helloItem)
self.Bind(wx.EVT_MENU, self.OnExit, exitItem)
self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)
def OnExit(self, event):
self.Close(True)
def OnAbout(self, event):
wx.MessageBox("Test",
"About",
wx.OK|wx.ICON_INFORMATION)
def OpenImage(self, event):
with wx.FileDialog (None, "Choose image", wildcard="PNG files (*.png)|*.png", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return # the user changed their mind
else:
# Gets rid of other images
for i in self.images:
i.Destroy()
self.images.remove(i)
# Displays image and adds image object to [self.images]
ImageName = fileDialog.GetPath()
png = wx.Image(ImageName, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.images.append(wx.StaticBitmap(self, -1, png, (0, 0), (png.GetWidth(), png.GetHeight())))
print(ImageName)
if __name__ == '__main__':
app = wx.App()
frm = HelloFrame(None, title='FileHeader Test')
frm.Show()
app.MainLoop()
ive tried just adding menubar.Hide() in the function makemenubar but to no avail
ive also tried self.Hide() in the same area but no luck
I should start by saying that I don't recommend that you do this.
It's non-standard and could confuse.
It's expensive cpu-wise for no obvious benefit.
That said, here is one way of doing it, using Show, Hide and EVT_MOTION.
The issue is that once it is hidden/removed, the next mouse OVER doesn't happen because it is no longer there. As you suppose, we can assign a territorial range where we suppose it would be. If the cursor strays into that zone, the menu can be shown or hidden.
import wx
class HelloFrame(wx.Frame):
images = []
def __init__(self, *args, **kw):
# ensure the parent's __init__ is called
super(HelloFrame, self).__init__(*args, **kw)
# create a panel in the frame
pnl = wx.Panel(self)
pnl2 = wx.Panel(self)
pnl.SetBackgroundColour("green")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(pnl,1, wx.EXPAND,10)
sizer.Add(pnl2,1, wx.EXPAND,10)
self.SetSizer(sizer)
# create a menu bar
self.makeMenuBar()
# and a status bar
#self.CreateStatusBar()
#self.SetStatusText("Welcome to wxPython!")
pnl.Bind(wx.EVT_MOTION, self.MenuPos)
def makeMenuBar(self):
fileMenu = wx.Menu()
helloItem = fileMenu.Append(-1, "&Load Backround Image")
fileMenu.AppendSeparator()
exitItem = fileMenu.Append(wx.ID_EXIT)
helpMenu = wx.Menu()
aboutItem = helpMenu.Append(wx.ID_ABOUT)
self.menuBar = wx.MenuBar()
self.menuBar.Append(fileMenu, "&File")
self.menuBar.Append(helpMenu, "&Help")
# Give the menu bar to the frame
self.SetMenuBar(self.menuBar)
self.menuBar.Hide()
# Finally, associate a handler function with the EVT_MENU event for
# each of the menu items. That means that when that menu item is
# activated then the associated handler function will be called.
self.Bind(wx.EVT_MENU, self.OpenImage, helloItem)
self.Bind(wx.EVT_MENU, self.OnExit, exitItem)
self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)
def MenuPos(self, event):
x, y = event.GetPosition()
if y <= 2:
self.menuBar.Show()
if y >= 3:
self.menuBar.Hide()
event.Skip()
def OnExit(self, event):
self.Close(True)
def OnAbout(self, event):
wx.MessageBox("Test",
"About",
wx.OK|wx.ICON_INFORMATION)
def OpenImage(self, event):
with wx.FileDialog (None, "Choose image", wildcard="PNG files (*.png)|*.png", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return # the user changed their mind
else:
# Gets rid of other images
for i in self.images:
i.Destroy()
self.images.remove(i)
# Displays image and adds image object to [self.images]
ImageName = fileDialog.GetPath()
png = wx.Image(ImageName, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.images.append(wx.StaticBitmap(self, -1, png, (0, 0), (png.GetWidth(), png.GetHeight())))
print(ImageName)
if __name__ == '__main__':
app = wx.App()
frm = HelloFrame(None, title='FileHeader Test')
frm.Show()
app.MainLoop()

wxPython: Calculator won't display value in Textctrlenter

I am working on a Calculator using wxPyhton. I'm having trouble on displaying the value in a Textctrlenter.
self.nameTxt = wx.TextCtrl( self, wx.ID_ANY,"",pos=(10,20),size=(260,30))
self.clickcount1 = 1
one = self.clickcount1
getBtn = wx.Button(self, self.clickcount1,label="1",pos=(10,60),size(40,40))
btn.Bind(wx.EVT_BUTTON, lambda btnClick, temp=button_name:
self.OnButton(btnClick(1), temp) )
Your lamba function is incorrect.
The size(40,40) parameter in getBtn, should be size=(40,40)
The Bind should be on getBtn not btn
The variable one is not used at all
You're using self.clickcount as the button id, don't, use -1 or wx.ID_ANY and wxpython will generate a unique id for you.
I assume that you are trying to do something like this:
import wx
class TestFrame(wx.Frame):
def __init__(self, *args):
wx.Frame.__init__(self, *args)
self.nameTxt = wx.TextCtrl( self, wx.ID_ANY,"",pos=(10,20),size=(260,30))
getBtn1 = wx.Button(self, id=-1, label="1", pos=(10,60), size=(40,40))
getBtn1.Bind(wx.EVT_BUTTON, lambda event: self.OnButton(event, button=1) )
getBtn2 = wx.Button(self, id=-1, label="2", pos=(50,60), size=(40,40))
getBtn2.Bind(wx.EVT_BUTTON, lambda event: self.OnButton(event, button=2) )
getBtn3 = wx.Button(self, id=-1, label="3", pos=(90,60), size=(40,40))
getBtn3.Bind(wx.EVT_BUTTON, lambda event: self.OnButton(event, button=3) )
self.Show()
def OnButton(self, event, button):
print ("Button number ", button)
curr_value = self.nameTxt.GetValue()
# If a value exists add to it, otherwise display value of pressed button
try:
curr_value = int(curr_value) + button
self.nameTxt.SetValue(str(curr_value))
except:
self.nameTxt.SetValue(str(button))
if __name__ == "__main__":
app = wx.App()
myframe = TestFrame(None, -1, "Calculator Test")
app.MainLoop()
With regard to your comment about wanting "11111111":
change the function OnButton to:
def OnButton(self, event, button):
print ("Button number ", button)
curr_value = self.nameTxt.GetValue()
curr_value = curr_value + str(button)
self.nameTxt.SetValue(curr_value)

Need help with wxPython, NotebookCtrl in particular

I am trying to write a non-webbased client for a chat service on a web site, it connects to it fine via socket and can communicate with it and everything. I am writing a GUI for it (I tried writing it in tkinter but I hit some walls I really wantd to get passed, so I switched to wxPython)
What I'm having a problem with:
This application uses an extended Notebook widget called NotebookCtrl. However the same problem appears with regular Notebook. First it creates a page in which things are logged to, which is successful, and then it connects, and it's supposed to add pages with each chatroom it joins on the service. However, when it adds a tab after it's mainloop has been started (I am communicating with the GUI and the sockets via queues and threading), the tab comes up completely blank. I have been stuck on this for hours and hours and got absolutely nowhere
The example that came with the NotebookCtrl download adds and deletes pages by itself perfectly fine. I am on the edge of completely giving up on this project. Here is what the code looks like (note this is a very small portion of the application, but this covers the wxPython stuff)
class Chatroom(Panel):
''' Frame for the notebook widget to tabulate a chatroom'''
def __init__(self, ns, parent):
Panel.__init__(self, parent, -1)
self.msgs, self.typed, self.pcbuff = [], [], {}
self.members, self._topic, self._title, self.pc = None, None, None, None
self.name, self.tabsign, = ns, 0
self.hSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.vSizer = wx.BoxSizer(wx.VERTICAL)
self.Grid = wx.GridBagSizer(5, 2)
self.Title = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Topic = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Privclasses = TreeCtrl(self, size=(150, -1))
self.Buffer = wx.html.HtmlWindow(self)
self.Buffer.SetStandardFonts(8)
self.templbl = StaticText(self, -1, 'This is where the formatting buttons will go!')
# note to remember: self.templbl.SetLabel('string') sets the label
self.Typer = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE)
self.Grid.Add(self.Title, (0,0), (1,2), wx.EXPAND, 2)
self.Grid.Add(self.Topic, (1,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.Privclasses, (1,1), (2,1), wx.EXPAND, 2)
self.Grid.Add(self.Buffer, (2,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.templbl, (3,0), (1,1), wx.EXPAND | wx.ALIGN_LEFT, 2)
self.Grid.Add(self.Typer, (4,0), (1,1), wx.EXPAND, 2)
self.Grid.AddGrowableCol(0)
self.Grid.AddGrowableRow(2)
self.SetSizerAndFit(self.Grid)
self.Show(True)
self.Typer.Bind(EVT_CHAR, self.Typer_OnKeyDown)
def Typer_OnKeyDown(self, event):
keycode = event.GetKeyCode()
if event.ShiftDown():
if keycode == WXK_RETURN:
pass
elif keycode == WXK_BACK:
pass
elif keycode == WXK_UP:
pass
elif keycode == WXK_DOWN:
pass
else:
if keycode == WXK_RETURN:
pass
event.Skip()
def Write(self, msg, K):
self.msgs.append(msg)
if len(self.msgs) > 300:
self.msgs = self.msgs[50:]
self.Buffer.SetPage('<br>'.join(self.msgs))
class Application(App):
def __init__(self, K):
self.Queue = Queue.Queue()
self.current = ''
self.chatorder = []
self.Window = App(0)
self.frame = MainFrame(None, 0, "Komodo Dragon")
self.Pages = NC.NotebookCtrl(self.frame, 9000)
self.Channels = {}
self.AddChatroom('~Komodo', K)
self.frame.Show(True)
self.Window.SetTopWindow(self.frame)
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
self.Pages.Bind(NC.EVT_NOTEBOOKCTRL_PAGE_CHANGED, self.onPageChanged)
self.Pages.Bind(NC.EVT_NOTEBOOKCTRL_PAGE_CHANGING, self.onPageChanging)
self.Pages.Bind(EVT_PAINT, self.onPaint)
self.Pages.Bind(EVT_SIZE, self.onSize)
def onPaint(self, event):
event.Skip()
def onSize(self, event):
event.Skip()
def Run(self):
self.Window.MainLoop()
def onPageChanged(self, event):
event.Skip()
def onPageChanging(self, event):
event.Skip()
# Timer and Queue functions
def OnTimer(self):
self.CheckQueue()
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
def CheckQueue(self): # the Application needs to use a queue to do things in order to prevent
try: # overlaps from happening, such as runtime errors and widgets changing
while not self.Queue.empty(): # suddenly. The most common error seems to be size
func = self.Queue.get_nowait() # changes during iterations. Everything from
func() # packet processing to adding widgets needs to wait in line this way
except Queue.Empty:
pass
def AddQueue(self, func):
self.Queue.put(func)
# Channel controls
def AddChatroom(self, ns, K):
if ns in self.Channels: return
#self.typedindex = 0
c = K.format_ns(ns)
self.chatorder.append(ns)
self.current = ns
self.Channels[ns] = Chatroom(ns, self.Pages)
self.Pages.AddPage(self.Channels[ns], ns, True)
def DeleteChatroom(self, ns, bot): # Delete a channel, it's properties, and buttons
ind = self.chatorder.index(ns)
del self.chatorder[ind]
for each in self.chatorder[ind:]:
x = self.channels[each].tab.grid_info()
if x['column'] == '0': r, c = int(x['row'])-1, 9
else: r, c = int(x['row']), int(x['column'])-1
self.channels[each].tab.grid_configure(row=r, column=c)
x = self.channels[each].tab.grid_info()
self.channels[ns].Tab.destroy()
self.channels[ns].tab.destroy()
self.channels[self.chatorder[-1]].tab.select()
self.switchtab(bot, self.chatorder[-1])
x = self.tabids_reverse[ns]
del self.tabids_reverse[ns], self.tabids[x], self.channels[ns]
The Chatroom class covers what each tab should have in it. the first tab that is added in class Application's init function is perfectly fine, and even prints messages it receives from the chat service when it attempts to connect. Once the service sends a join packet to me, it calls the same exact function used to add that tab, AddChatroom(), and should create the exact same thing, only printing messages specifically for that chatroom. It creates the tab, but the Chatroom page is completely empty and grey. I am very sad :C
Thanks in advance if you can help me.
EDIT
I have written a working example of this script you can run yourself (if you have wxPython). It uses regular Notebook instead of NotebookCtrl so you don't have to download that widget as well, but the bug happens for both. The example sets up the window, and sets up the main debug tab and then a chatroom tab before entering mainloop. After mainloop, any chatrooms added afterwords are completely blank
from wx import *
import Queue, time
from threading import Timer as _Timer
from threading import Thread
# import System._NotebookCtrl.NotebookCtrl as NC ## Using regular notebook for this example
class MainFrame(Frame):
def __init__(self, parent, ID, title):
ID_FILE_LOGIN = 100
ID_FILE_RESTART = 101
ID_FILE_EXIT = 102
ID_HELP_ABOUT = 200
Frame.__init__(self, parent, ID, title,
DefaultPosition, Size(1000, 600))
self.CreateStatusBar()
self.SetStatusText("This is the statusbar")
menu_File = Menu()
menu_Help = Menu()
menu_Edit = Menu()
menu_Config = Menu()
menu_File.Append(ID_FILE_LOGIN, "&Login Info",
"Enter your deviantArt Login information")
menu_File.AppendSeparator()
menu_File.Append(ID_FILE_RESTART, "&Restart",
"Restart the program")
menu_File.Append(ID_FILE_EXIT, "E&xit",
"Terminate the program")
menu_Help.Append(ID_HELP_ABOUT, "&About",
"More information about this program")
menuBar = MenuBar()
menuBar.Append(menu_File, "&File");
menuBar.Append(menu_Edit, "&Edit");
menuBar.Append(menu_Config, "&Config");
menuBar.Append(menu_Help, "&Help");
self.SetMenuBar(menuBar)
EVT_MENU(self, ID_FILE_LOGIN, self.OnLogin)
EVT_MENU(self, ID_FILE_RESTART, self.OnRestart)
EVT_MENU(self, ID_FILE_EXIT, self.OnQuit)
EVT_MENU(self, ID_HELP_ABOUT, self.OnAbout)
def OnAbout(self, event):
dlg = MessageDialog(self, "Hi! I am Komodo Dragon! I am an application\n"
"that communicates with deviantArt's Messaging Network (dAmn)",
"Komodo", OK | ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def OnQuit(self, event):
self.Close(True)
def OnRestart(self, event):
pass
def OnLogin(self, event):
dlg = MessageDialog(self, "Enter your Login information here:\n"
"Work in progress, LOL",
"Login", OK | ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
class Chatroom(Panel):
''' Frame for the notebook widget to tabulate a chatroom'''
def __init__(self, parent, ns):
Panel.__init__(self, parent, -1)
self.msgs, self.typed, self.pcbuff = [], [], {}
self.members, self._topic, self._title, self.pc = None, None, None, None
self.name, self.tabsign, = ns, 0
self.hSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.vSizer = wx.BoxSizer(wx.VERTICAL)
self.Grid = wx.GridBagSizer(5, 2)
self.Title = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Topic = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Privclasses = TreeCtrl(self, size=(150, -1))
self.Buffer = wx.html.HtmlWindow(self)
self.Buffer.SetStandardFonts(8)
self.templbl = StaticText(self, -1, 'This is where the formatting buttons will go!')
self.Typer = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE)
self.Grid.Add(self.Title, (0,0), (1,2), wx.EXPAND, 2)
self.Grid.Add(self.Topic, (1,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.Privclasses, (1,1), (2,1), wx.EXPAND, 2)
self.Grid.Add(self.Buffer, (2,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.templbl, (3,0), (1,1), wx.EXPAND | wx.ALIGN_LEFT, 2)
self.Grid.Add(self.Typer, (4,0), (1,1), wx.EXPAND, 2)
self.Grid.AddGrowableCol(0)
self.Grid.AddGrowableRow(2)
self.SetSizerAndFit(self.Grid)
self.Show(True)
self.Typer.Bind(EVT_CHAR, self.Typer_OnKeyDown)
def Typer_OnKeyDown(self, event):
keycode = event.GetKeyCode()
if event.ShiftDown():
if keycode == WXK_RETURN:
pass
elif keycode == WXK_BACK:
pass
elif keycode == WXK_UP:
pass
elif keycode == WXK_DOWN:
pass
else:
if keycode == WXK_RETURN:
pass
event.Skip()
def Write(self, msg):
self.msgs.append(msg)
if len(self.msgs) > 300:
self.msgs = self.msgs[50:]
self.Buffer.SetPage('<br>'.join(self.msgs))
class Application(App):
def __init__(self, K):
self.Queue = Queue.Queue()
self.current = ''
self.chatorder = []
self.Window = App(0)
self.frame = MainFrame(None, 0, "Komodo Dragon")
self.Pages = Notebook(self.frame, 9000)
self.Channels = {}
self.AddChatroom('~Komodo', K)
self.frame.Show(True)
self.Window.SetTopWindow(self.frame)
self.Timer = _Timer(0.050, self.OnTimer)
self.Pages.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)
self.Pages.Bind(EVT_NOTEBOOK_PAGE_CHANGING, self.onPageChanging)
self.Pages.Bind(EVT_PAINT, self.onPaint)
self.Pages.Bind(EVT_SIZE, self.onSize)
def onPaint(self, event):
event.Skip()
def onSize(self, event):
event.Skip()
def onPageChanged(self, event):
event.Skip()
def onPageChanging(self, event):
event.Skip()
def Run(self):
self.Window.MainLoop()
# Timer and Queue functions
def OnTimer(self):
self.CheckQueue()
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
def CheckQueue(self): # the Application needs to use a queue to do things in order to prevent
try: # overlaps from happening, such as runtime errors and widgets changing
while not self.Queue.empty(): # suddenly. The most common error seems to be size
func = self.Queue.get_nowait() # changes during iterations. Everything from
if func is not None:
func() # packet processing to adding widgets needs to wait in line this way
except Queue.Empty:
pass
def AddQueue(self, func):
self.Queue.put(func)
# Channel controls
def AddChatroom(self, ns, K):
if ns in self.Channels: return
self.chatorder.append(ns)
self.current = ns
self.Channels[ns] = Chatroom(self.Pages, ns)
self.Pages.AddPage(self.Channels[ns], ns, True)
class _Thread(Thread):
def __init__(self, K):
Thread.__init__(self)
self.K = K
def run(self):
self.K.Mainloop()
class K:
def __init__(self):
self.App = Application(self)
self.App.AddQueue(self.App.Channels['~Komodo'].Write('>> Welcome!') )
self.App.AddQueue(self.App.Channels['~Komodo'].Write('>> Entering mainloop...') )
self.App.AddChatroom('#TestChatroom1', self)
self.roomcount = 1
self.timer = time.time() + 3
self.thread = _Thread(self)
self.thread.start()
self.App.Timer.start()
self.App.Run()
def Mainloop(self):
while True:
if time.time() > self.timer:
self.App.AddQueue(
lambda: self.App.Channels['~Komodo'].Write('>> Testing') )
if self.roomcount < 5:
self.roomcount += 1
self.App.AddQueue(
lambda: self.App.AddChatroom('#TestChatroom{0}'.format(self.roomcount), self) )
self.timer = time.time() + 3
if __name__ == '__main__':
test = K()
Here is your problem:
lambda: self.App.AddChatroom('#TestChatroom{0}'.format(self.roomcount), self) )
Fixed by using wx.CallAfter (tested on win xp sp3):
lambda: wx.CallAfter(self.App.AddChatroom, '#TestChatroom{0}'.format(self.roomcount), self)
You were probably tying up the GUI by calling wx objects from thread code. See this wxPython wiki article.
It doesn't look like you're creating your Chatroom with its parent as the Notebook. What is "K" in Application.__init__? (you didn't post a fully runnable sample)
When adding or deleting tabs, you probably need to call Layout() right after you're done. One easy way to find out is to grab an edge of the frame and resize it slightly. If you see widgets magically appear, then it's because Layout() was called and your page re-drawn.

Python - Bitmap won't draw/display on button

I have been working on this project for some time now - it was originally supposed to be a test to see if, using wxPython, I could build a button 'from scratch.' From scratch means: that i would have full control over all the aspects of the button (i.e. controlling the BMP's that are displayed... what the event handlers did... etc.)
I have run into several problems (as this is my first major python project.) Now, when the all the code is working for the life of me I can't get an image to display.
Basic code - not working
dc = wx.BufferedPaintDC(self)
dc.SetFont(self.GetFont())
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dc.DrawBitmap(wx.Bitmap("/home/wallter/Desktop/Mouseover.bmp"), 100, 100)
self.Refresh()
self.Update()
Full Main.py
import wx
from Custom_Button import Custom_Button
from wxPython.wx import *
ID_ABOUT = 101
ID_EXIT = 102
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wxFrame.__init__(self, parent, ID, title,
wxDefaultPosition, wxSize(400, 400))
self.CreateStatusBar()
self.SetStatusText("Program testing custom button overlays")
menu = wxMenu()
menu.Append(ID_ABOUT, "&About", "More information about this program")
menu.AppendSeparator()
menu.Append(ID_EXIT, "E&xit", "Terminate the program")
menuBar = wxMenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
# The call for the 'Experiential button'
self.Button1 = Custom_Button(parent, -1,
wx.Point(100, 100),
wx.Bitmap("/home/wallter/Desktop/Mouseover.bmp"),
wx.Bitmap("/home/wallter/Desktop/Normal.bmp"),
wx.Bitmap("/home/wallter/Desktop/Click.bmp"))
# The following three lines of code are in place to try to get the
# Button1 to display (trying to trigger the Paint event (the _onPaint.)
# Because that is where the 'draw' functions are.
self.Button1.Show(true)
self.Refresh()
self.Update()
# Because the Above three lines of code did not work, I added the
# following four lines to trigger the 'draw' functions to test if the
# '_onPaint' method actually worked.
# These lines do not work.
dc = wx.BufferedPaintDC(self)
dc.SetFont(self.GetFont())
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.DrawBitmap(wx.Bitmap("/home/wallter/Desktop/Mouseover.bmp"), 100, 100)
EVT_MENU(self, ID_ABOUT, self.OnAbout)
EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def OnAbout(self, event):
dlg = wxMessageDialog(self, "Testing the functions of custom "
"buttons using pyDev and wxPython",
"About", wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def TimeToQuit(self, event):
self.Close(true)
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(NULL, -1, "wxPython | Buttons")
frame.Show(true)
self.SetTopWindow(frame)
return true
app = MyApp(0)
app.MainLoop()
Full CustomButton.py
import wx
from wxPython.wx import *
class Custom_Button(wx.PyControl):
def __init__(self, parent, id, Pos, Over_BMP, Norm_BMP, Push_BMP, **kwargs):
wx.PyControl.__init__(self,parent, id, **kwargs)
self.Bind(wx.EVT_LEFT_DOWN, self._onMouseDown)
self.Bind(wx.EVT_LEFT_UP, self._onMouseUp)
self.Bind(wx.EVT_LEAVE_WINDOW, self._onMouseLeave)
self.Bind(wx.EVT_ENTER_WINDOW, self._onMouseEnter)
self.Bind(wx.EVT_ERASE_BACKGROUND,self._onEraseBackground)
self.Bind(wx.EVT_PAINT,self._onPaint)
self.pos = Pos
self.Over_bmp = Over_BMP
self.Norm_bmp = Norm_BMP
self.Push_bmp = Push_BMP
self._mouseIn = False
self._mouseDown = False
def _onMouseEnter(self, event):
self._mouseIn = True
def _onMouseLeave(self, event):
self._mouseIn = False
def _onMouseDown(self, event):
self._mouseDown = True
def _onMouseUp(self, event):
self._mouseDown = False
self.sendButtonEvent()
def sendButtonEvent(self):
event = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
event.SetInt(0)
event.SetEventObject(self)
self.GetEventHandler().ProcessEvent(event)
def _onEraseBackground(self,event):
# reduce flicker
pass
def Iz(self):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.Norm_bmp, 100, 100)
def _onPaint(self, event):
# The printing functions, they should work... but don't.
dc = wx.BufferedPaintDC(self)
dc.SetFont(self.GetFont())
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dc.DrawBitmap(self.Norm_bmp)
# This never printed... I don't know if that means if the EVT
# is triggering or what.
print '_onPaint'
# draw whatever you want to draw
# draw glossy bitmaps e.g. dc.DrawBitmap
if self._mouseIn: # If the Mouse is over the button
dc.DrawBitmap(self.Over_bmp, self.pos)
else: # Since the mouse isn't over it Print the normal one
# This is adding on the above code to draw the bmp
# in an attempt to get the bmp to display; to no avail.
dc.DrawBitmap(self.Norm_bmp, self.pos)
if self._mouseDown: # If the Mouse clicks the button
dc.DrawBitmap(self.Push_bmp, self.pos)
This code won't work? I get no BMP displayed why? How do i get one? I've gotten the staticBitmap(...) to display one, but it won't move, resize, or anything for that matter... - it's only in the top left corner of the frame?
Note: the frame is 400pxl X 400pxl - and the "/home/wallter/Desktop/Mouseover.bmp"
Are your sure you code is working without exceptions because when I run it i get many errors, read the points below and you should have a button which at least draws correctly
When O run it it gives error because Custom_Button is passed NULL parent instead pass frame e.g. Custom_Button(self, ...)
Your drawBitmap call is also wrong, it throws exception, instead of dc.DrawBitmap(self.Norm_bmp) it should be dc.DrawBitmap(self.Norm_bmp, 0, 0)
dc.DrawBitmap(self.Over_bmp, self.pos) also throws error as pos should be x,y not a tuple so instead do dc.DrawBitmap(self.Over_bmp, *self.pos)
and lastly you do not need to do "from wxPython.wx import *" instead just do "from wx import *" and instead of wxXXX class names use wx.XXX, instead of true use True etc
here is my working code
from wx import *
ID_ABOUT = 101
ID_EXIT = 102
class Custom_Button(wx.PyControl):
def __init__(self, parent, id, Pos, Over_BMP, Norm_BMP, Push_BMP, **kwargs):
wx.PyControl.__init__(self,parent, id, **kwargs)
self.Bind(wx.EVT_LEFT_DOWN, self._onMouseDown)
self.Bind(wx.EVT_LEFT_UP, self._onMouseUp)
self.Bind(wx.EVT_LEAVE_WINDOW, self._onMouseLeave)
self.Bind(wx.EVT_ENTER_WINDOW, self._onMouseEnter)
self.Bind(wx.EVT_ERASE_BACKGROUND,self._onEraseBackground)
self.Bind(wx.EVT_PAINT,self._onPaint)
self.pos = Pos
self.Over_bmp = Over_BMP
self.Norm_bmp = Norm_BMP
self.Push_bmp = Push_BMP
self._mouseIn = False
self._mouseDown = False
def _onMouseEnter(self, event):
self._mouseIn = True
def _onMouseLeave(self, event):
self._mouseIn = False
def _onMouseDown(self, event):
self._mouseDown = True
def _onMouseUp(self, event):
self._mouseDown = False
self.sendButtonEvent()
def sendButtonEvent(self):
event = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
event.SetInt(0)
event.SetEventObject(self)
self.GetEventHandler().ProcessEvent(event)
def _onEraseBackground(self,event):
# reduce flicker
pass
def Iz(self):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.Norm_bmp, 100, 100)
def _onPaint(self, event):
# The printing functions, they should work... but don't.
dc = wx.BufferedPaintDC(self)
dc.SetFont(self.GetFont())
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dc.DrawBitmap(self.Norm_bmp, 0, 0)
# This never printed... I don't know if that means if the EVT
# is triggering or what.
print '_onPaint'
# draw whatever you want to draw
# draw glossy bitmaps e.g. dc.DrawBitmap
if self._mouseIn: # If the Mouse is over the button
dc.DrawBitmap(self.Over_bmp, *self.pos)
else: # Since the mouse isn't over it Print the normal one
# This is adding on the above code to draw the bmp
# in an attempt to get the bmp to display; to no avail.
dc.DrawBitmap(self.Norm_bmp, *self.pos)
if self._mouseDown: # If the Mouse clicks the button
dc.DrawBitmap(self.Push_bmp, *self.pos)
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title,
wx.DefaultPosition, wx.Size(400, 400))
self.CreateStatusBar()
self.SetStatusText("Program testing custom button overlays")
menu = wx.Menu()
menu.Append(ID_ABOUT, "&About", "More information about this program")
menu.AppendSeparator()
menu.Append(ID_EXIT, "E&xit", "Terminate the program")
menuBar = wx.MenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
# The call for the 'Experiential button'
s = r"D:\virtual_pc\mockup\mockupscreens\embed_images\toolbar\options.png"
self.Button1 = Custom_Button(self, -1,
wx.Point(100, 100),
wx.Bitmap(s),
wx.Bitmap(s),
wx.Bitmap(s))
self.Button1.Show(True)
EVT_MENU(self, ID_ABOUT, self.OnAbout)
EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def OnAbout(self, event):
dlg = wxMessageDialog(self, "Testing the functions of custom "
"buttons using pyDev and wxPython",
"About", wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def TimeToQuit(self, event):
self.Close(true)
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, "wxPython | Buttons")
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()

Categories

Resources