I am a newbie in wx.python and python and wanted to use the MultiSplitterWindow.py demo code in my own application.
I have read other stackoverflow entries regarding this subject but the answers given there don't seem to work for me.
I would really appreciate if anybody could help me to solve this issue.
As the demos use the demo framework:
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
It does not work in my app, I have tried replacing the above using the example given in:
[] http://wiki.wxpython.org/Using%20wxPython%20Demo%20Code
But I might be doing something wrong because I does not work.
Any help is much appreciated.
I wrote about this on the wxPython wiki:
http://wiki.wxpython.org/Using%20wxPython%20Demo%20Code
Most of the time, you can copy the relevant portions of the widget code in question and paste it in your own code. The part you don't want is the references to self.log. That just allows the demo to log the messages and is demo specific code. I would actually rewrite my initial example to look like the following though:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
########################################################################
class MyFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Demo Test")
panel = MyPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Now if you want to copy the code in from the demo, you won't have to change all the self instances to `self.panel':
import wx
from wx.lib.wordwrap import wordwrap
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
b = wx.Button(self, -1, "Show a wx.AboutBox", (50,50))
self.Bind(wx.EVT_BUTTON, self.OnButton, b)
def OnButton(self, evt):
# First we create and fill the info object
info = wx.AboutDialogInfo()
info.Name = "Hello World"
info.Version = "1.2.3"
info.Copyright = "(C) 2006 Programmers and Coders Everywhere"
info.Description = wordwrap(
"A \"hello world\" program is a software program that prints out "
"\"Hello world!\" on a display device. It is used in many introductory "
"tutorials for teaching a programming language."
"\n\nSuch a program is typically one of the simplest programs possible "
"in a computer language. A \"hello world\" program can be a useful "
"sanity test to make sure that a language's compiler, development "
"environment, and run-time environment are correctly installed.",
350, wx.ClientDC(self))
info.WebSite = ("http://en.wikipedia.org/wiki/Hello_world", "Hello World home page")
info.Developers = [ "Joe Programmer",
"Jane Coder",
"Vippy the Mascot" ]
info.License = wordwrap(licenseText, 500, wx.ClientDC(self))
# Then we call wx.AboutBox giving it that info object
wx.AboutBox(info)
########################################################################
class MyFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Demo Test")
panel = MyPanel(self)
self.Show()
licenseText = "blah " * 250 + "\n\n" +"yadda " * 100
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Download demos from here http://wxpython.org/download.php install and go C:\Program Files\wxPython3.0-Docs-and-Demos\demo and run.
Related
i am trying to make a windows 10 toast notification that will run code if its clicked but my code only shows the notification and gives me an error when i click it
import os
import wx
import wx.adv
class MyApp(wx.App):
def OnInit(self):
sTitle = 'test'
sMsg = 'test'
nmsg = wx.adv.NotificationMessage(title=sTitle, message=sMsg)
nmsg.SetFlags(wx.ICON_INFORMATION)
nmsg.Show(timeout=wx.adv.NotificationMessage.Timeout_Auto)
self.Bind(wx.EVT_NOTIFICATION_MESSAGE_CLICK, self.notifclicked)
return True
def _notifclicked(self, evt):
print("notification has been clicked")
app = MyApp()
app.MainLoop()
error code : AttributeError: module 'wx' has no attribute 'EVT_NOTIFICATION_MESSAGE_CLICK'
Without wishing to say definitely that NotificationMessage is unfinished business, I'm going to suggest it.
I suspect that it is based on notify and notify2 which purport to support action callbacks but don't.
They should be relying on Dbus sending stuff back but it doesn't look like it does or you have to jump through hoops to make it happen. (Dbus MainLoop setup for example)
I have decided to adapt your code slightly, just to show how to add action buttons, although they are nothing more than eye candy and to show how I think the event callbacks should work, if it ever comes to reality.
Of course, if it currently does work and I haven't worked out how to do it, I'll happily eat these words. I code exclusively on Linux, so there's that as a caveat.
import wx
import wx.adv
Act_Id_1 = wx.NewIdRef()
Act_Id_2 = wx.NewIdRef()
class MyFrame(wx.Frame):
def __init__(self, parent=None, id=wx.ID_ANY, title="", size=(360,100)):
super(MyFrame, self).__init__(parent, id, title, size)
self.m_no = 0
self.panel = wx.Panel(self)
self.Mbutton = wx.Button(self.panel, wx.ID_ANY, label="Fire off a message", pos=(10,10))
self.Bind(wx.EVT_BUTTON, self.OnFire, self.Mbutton)
#self.Bind(wx.adv.EVT_NOTIFICATION_MESSAGE_CLICK, self._notifclicked)
#self.Bind(wx.adv.EVT_NOTIFICATION_MESSAGE_DISMISSED, self._notifdismissed)
#self.Bind(wx.adv.EVT_NOTIFICATION_MESSAGE_ACTION, self._notifaction, id=Act_Id_1)
self.Show()
def OnFire(self, event):
self.m_no +=1
sTitle = 'Test heading'
sMsg = 'Test message No '
nmsg = wx.adv.NotificationMessage(title=sTitle, message=sMsg+str(self.m_no))
nmsg.SetFlags(wx.ICON_INFORMATION)
nmsg.AddAction(Act_Id_1, "Cancel")
nmsg.AddAction(Act_Id_2, "Hold")
nmsg.Show(timeout=10)
def _notifclicked(self, event):
print("notification has been clicked")
def _notifdismissed(self, event):
print("notification dismissed")
def _notifaction(self, event):
print("Action")
app = wx.App()
frame = MyFrame()
app.MainLoop()
I have the following code and I'm on OSX. However, I'm expecting to see a toolbar icon but I'm not seeing one. Am I doing something wrong or should it work on Windows? Here's the code
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,size=(400, 350))
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
self.panel = wx.Panel(self)
toolbar = wx.ToolBar(self, size=(-1, 128))
toolbar.SetToolBitmapSize((128,128))
bmp2 = wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_OTHER, (128,128))
toolbar.AddLabelTool(-1, label="Add", bitmap=bmp2,
shortHelp="Add", kind=wx.ITEM_NORMAL)
toolbar.Realize()
self.SetToolBar(toolbar)
if __name__ == '__main__':
app = wx.App()
Example(None, title='')
app.MainLoop()
Thanks
The call to Realize needs to happen after the SetToolBar. This is because there are two different kinds of toolbars on OSX and which is chosen depends on if it is attached to a frame or not, and all that happens in the Realize call. Also, OSX is picky about the size of the tools, and the 128 you use will likely be reduced to a supported size.
I am having a hard time restoring a window after it has been minimized.
Minimize works fine, but i am trying to open the window back up.. self restores but Vodka_Frame doesn't.
Here is my code:
def minimizeProgram(event):
self.Iconize()
Vodka_Frame.Iconize()
def maximizeProgram(event):
if self.IsIconized()=='True' or Vodka_Frame.IsIconized()=='True':
self.Iconize(False)
Vodka_Frame.Iconize(False)
self.Show(True)
Vodka_Frame.Show(True)
self.Raise()
Vodka_Frame.Raise()
#### Catch the minimize event and minimize both windows.
self.Bind(wx.EVT_ICONIZE,minimizeProgram)
#### Catch the maximize event and maximize both windows.
self.Bind(wx.EVT_LEFT_DCLICK,maximizeProgram)
What am i doing wrong? How can i get my windows back! :)
I'm not sure what you're doing wrong without a small runnable example. However, I created the following simple script that works for me:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, parent=None, title="Test")
panel = MyPanel(self)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.toggleIconize, self.timer)
self.timer.Start(5000)
self.Show()
#----------------------------------------------------------------------
def toggleIconize(self, event):
""""""
if self.IsIconized() == True:
print "raising..."
self.Iconize(False)
self.Raise()
else:
print "minimizing!"
self.Iconize()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Basically it just minimizes and raises itself every 5 seconds. I am using Python 2.6.6 and wxPython 2.8.12.1 on Windows 7 Pro.
The relationship between your frames is not clear, but if you make the other frame child of the main one (i.e. specify the main frame as its parent when creating it), then it will be minimized and restored automatically when the main frame is minimized or restored, without you having to do anything special.
I've boiled my problem down to the example code shown in this post. Note that I'm not calling app.MainLoop() because this isn't an interactive window; I want it to pop up at the beginning, show some progress bars while work happens, and disappear when complete.
My (limited) understanding of wxPython and wx.Yield() led me to believe that calling wx.Yield() after some UI work would flush those changes to the display. That is not occurring -- when I run this script, there is a gray box where "Hello World" should be.
What am I doing wrong?
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, size=(400,400))
self.panel = wx.Panel(self, -1)
wx.StaticText(self.panel, -1, "Hello World", (20,20))
wx.Yield()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, -1)
self.frame.Show(True)
self.SetTopWindow(self.frame)
return True
def run():
app = MyApp(redirect=False)
import time; time.sleep(5)
run()
You need to be yielding or updating on a regular basis, so that when your OS/window manager sends repaint messages to your app, it can handle them. I am not 100% sure about wxPython as I haven't used it recently but I don't think you can do what you want without the main loop to handle the messages appropriately.
You might find something useful here about threading the main loop, however (as well as explanation of why the main loop is important): http://wiki.wxpython.org/MainLoopAsThread
instead of wx.Yield()
just call self.Update()
Without the MainLoop no events will be fired and also .Refresh will not work.
I guess wxSplashscreen may be what you are looking for. Example: http://wiki.wxpython.org/SplashScreen
Not that it will do the original poster any good after all this time but wx.Yield() would have done the job. It just needs to be in the right place as does the self.Show()
The following outputs a progress bar which gets updated.
import wx
import time
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, size=(290,200))
self.panel = wx.Panel(self, -1)
wx.StaticText(self.panel, -1, "Hello World", (20,20))
self.gauge = wx.Gauge(self.panel, -1, 50, pos=(20,50), size=(250, 20))
self.Show()
n = 0
while n < 50:
n = n+1
self.gauge.SetValue(n)
wx.Yield()
time.sleep(1)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, -1)
self.SetTopWindow(self.frame)
return True
def run():
app = MyApp()
run()
Is it possible to run a wxApp from another wxApp?
I am trying to simply call a program I wrote (called DataDeck) from a method of another wxApp, like it was a plugin.
something like:
def on_datadeck_btn_click(self, event):
import datadeck.main
datadeck.main.run()
event.Skip()
where datadeck.main.run() is a classic start of a wxApp:
def run():
app = DataDeck(0)
app.SetAppName("DataDeck")
app.MainLoop()
Right now, it correctly opens DataDeck the first time and it works, but it won't reopen DataDeck a second time after I close it. This would freeze everything.
Update: based on #Mike Driscoll answer, I documented myself more and came to the following solution:
I added an "entry point" in datadeck
def run_as_plugin():
#[do some stuff related to XRC layouts and sysout redirection]
MainGUI = datadeck.gui.maingui.MainGUI()
Where the constructor of MainGUI() automatically shows the wxFrame. Now my application behaves like it was a component of the caller wxApp.
Therefore, I modify the application method as follows:
def on_datadeck_btn_click(self, event):
import datadeck.main
datadeck.main.run_as_plugin()
event.Skip()
It was very simple, indeed! I just had to modify my objects that deal with stdout redirection (not part of this question, I omit the details), and everything worked fine.
There should only be on wx.App. From what I've read online, you can't have two wx.App objects running in one script. You could probably do it using the subprocess module to open a new process though. Take a look at Editra to see some examples for how to do plugins. It is included with wxPython or you can download it separately.
It is perfectly feasible. Not sure why it doesnt work for you.
This example works perfectly:
--main.py--
import wx
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title='Main', size=(353,270))
button= wx.Button(self, -1, 'call app', pos=(10,10), size=(-1,30))
self.Bind(wx.EVT_BUTTON, self.capp, button)
def capp(self, event):
import datadeck
datadeck.run()
if __name__ == '__main__':
app = wx.App(0)
frame = MainFrame(None)
frame.Show()
app.MainLoop()
--datadeck.py--
import wx
class DDFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title='DDFrame', size=(353,270))
button = wx.Button(self, -1, 'print something', pos=(100,100), size=(-1,30))
self.Bind(wx.EVT_BUTTON, self.say_hello, button)
def say_hello(self, event):
print 'something'
class DataDeck(wx.App):
def OnInit(self):
frame = DDFrame(None)
frame.Show()
return True
def run():
app = DataDeck(1)
app.SetAppName("DataDeck")
app.MainLoop()
if you press the 'call app' button you get the new frame open. And you can open as many as you want.
Created aplications/frames are independent of each other. You can close any of them without affecting the others. And the system doesnt freeze.