i am trying to do a small pandy app in python. what i want is some kind of application window with all the usual stuff (menubars, treeview, about dialog etc.) and an instance of panda3d als child of that window. this application should be used to load models and view them, not much more. (i know panda3d has already has some kind of modelviewer…)
the target operating systems will be linux and windows. thats why i chose wxpython. i figured the wxappshell would be a good starting point.
now my problem is that i can’t seem to find any kind of documentation on how to get this done. could someone point me to the right direction or provide a few code samples / instructions of what has to be done? this would be very nice. i’m a fulltime coder but without proper documentation it’s too difficult for me to figure out how this is supposed to work out.
this is how far i have come. a problem arises when i try to hide the panda window when the wx window gets minimized. i haven´t found a convenient method to achieve this, so i close the panda window and open it up again when wx gets shown again. but sometimes my application crashes yielding following error message (on linux). what am i doing wrong? see the (partial) sourcecode below.
'''
Created on 24.04.2009
@author: itti
'''
import wx
import sys
from pandac.PandaModules import WindowProperties
from direct.showbase import DirectObject
class ViewerApp(wx.PySimpleApp, DirectObject.DirectObject):
'''
Main Application Window
'''
def __init__(self):
'''
Constructor
'''
wx.PySimpleApp.__init__(self)
def OnInit(self):
self._initWx()
self._initPanda()
return True
def _initWx(self):
self.SetAppName('Schattencrash Modelviewer')
self.SetClassName('de.schattencrash')
self.parent = wx.MDIParentFrame(None, -1, 'Modelviewer')
self.child = wx.MDIChildFrame(self.parent, -1, 'Panda window')
self.parent.SetClientSize((600, 400))
self.parent.Show(True)
self.child.SetClientSize((400, 300))
self.child.Show(True)
self.parent.Bind(wx.EVT_MOVE, self._repositionPanda)
self.parent.Bind(wx.EVT_SIZE, self.OnSize)
self.parent.Bind(wx.EVT_ICONIZE, self._togglePanda)
self.parent.Bind(wx.EVT_CLOSE, sys.exit)
self.wxEventLoop = wx.EventLoop()
self.oldLoop = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.wxEventLoop)
self.eventLoop()
def _initPanda(self):
base.windowType = 'onscreen'
props = WindowProperties.getDefault()
# Currently not supported on Linux so we need a little hack...
#props.setParentWindow(self.child.GetHandle())
size = self.child.GetSize()
props.setZOrder(WindowProperties.ZTop)
props.setSize(size[0], size[1])
base.openDefaultWindow(props = props)
base.setFrameRateMeter(True)
def _repositionPanda(self, event):
position = self.parent.ClientToScreen(self.child.GetPosition())
wp = WindowProperties()
wp.setOrigin(position[0], position[1])
try:
if base.win:
base.win.requestProperties(wp)
except AttributeError:
pass
def _togglePanda(self, event):
print "iconize event"
if event.Iconized():
print "need to hide panda"
self.windowProperties = base.win.getProperties()
base.closeWindow(base.win)
else:
print "need to show panda again"
base.openDefaultWindow(props = self.windowProperties)
def OnSize(self, event):
print "resize event thrown"
wp = WindowProperties()
wp.setSize(event.Size[0], event.Size[1])
try:
if base.win:
base.win.requestProperties(wp)
except AttreibuteError:
pass
def eventLoop(self, task = None):
while self.wxEventLoop.Pending():
self.wxEventLoop.Dispatch()
#self.ProcessIdle()
if task != None:
return task.cont
def close(self):
wx.EventLoop.SetActive(self.oldLoop)
itti is difficult for me to dig into that code - especially cos is not a runnable whole piece - but first off I would invite you to try this code to see if works, to see if you got problems running this kind of hybrid scripts, and then, if works, you may also use it to study with to understand in what is different or you may use it as a starting point to modify it to suit your needs cos I made it for that purpose indeed.
It’s also not entirely clear to me why you’re trying to hide Panda’s window when its parent window becomes minimized. Doesn’t that happen automatically?
technically there is no parent to panda because the props.setParentWindow() seems to be currently not implemented for XWindow-handles. so when the wx window gets hidden/minimzed i have to get rid of the panda output too. otherwise i end up with an undecorated panda window with “always on top”-behaviour…
@astelix: i know your pod-code it’s always a source of inspiration for me. p3dwxpod works on my system without XWindow-errors.
Oh, hmm. Well, it seems like we ought to fix that lack of parent-window implementation in the X11 subsystem.
As to the crash, this sounds like a race condition in the X11 event stream. Probably you’re not allowed to do window creation or destruction while you’re responding to an X11-generated event. I recommend writing your code so that you set a flag when this happens, and then do the actual Panda window change in response to some other, non-X11 event (for instance, after a wx.Idle or wx.Timer event).
I implemented it a long time ago, already and many have been using setParentWindow on X11 without a problem. (For example the panda3d-editor used it.)
Why exactly is it not working for you? Are you maybe passing a handle of a window that has not been created yet, or are you just running a prehistorical version of Panda?
should have checked the date of the posts quoted above. if setParentWindow is actually working on linux now, i think all my problems could be solved. i will try it asap. thank you guys!