panda as child in wxpython window/application ?

hi there,

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.

greets and thanks in advance

-itti

You can try these:

discourse.panda3d.org/viewtopic.php?t=5359

discourse.panda3d.org/viewtopic.php?t=5728

discourse.panda3d.org/viewtopic.php?t=5915

Or if you want a more simple straight-to-the-point sample program:
discourse.panda3d.org/viewtopic.php?t=2487

thank you both for your answers. i will look into it.

hi again,

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?

David

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 :wink: 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).

David

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?

oh my bad. i didn’t try it on linux actually. i took the info in discourse.panda3d.org/viewtopic.php?t=2487 for granted:

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!