I tried using this method, but when ever I exit the window created by wxPython, the application actually didn’t stop. I checked the Task Manager, there is still python.exe process running, and consuming quite a number of memory. Is there a new implementation for Panda 1.5.3 on using wxPython?
It has nothing to do with Panda.
If you want to shutdown Python when user closes wxPython-created window, you must respond to its close event.
self.parent.Bind(wx.EVT_CLOSE,sys.exit)
Import sys first.
wow… Stupid me… Thanks for the help!
I have done some small modifications to the code, because on my System (Windows Vista) the 3D-Area always has a big white Border around. I have set the Origin to (0,0). Also the 3D-Window is now resized automatically.
import wx
import time
import direct
from pandac.PandaModules import *
loadPrcFileData('startup', 'window-type none')
from direct.directbase.DirectStart import *
from direct.showbase import DirectObject
class App(wx.PySimpleApp, DirectObject.DirectObject):
def __init__(self):
wx.PySimpleApp.__init__(self)
#Create a new event loop (to overide default wxEventLoop)
self.evtloop = wx.EventLoop()
self.old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.evtloop)
taskMgr.add(self.wx, "Custom wx Event Loop")
# wxWindows calls this method to initialize the application
def OnInit(self):
self.SetAppName('Editor')
self.SetClassName('MyAppClass')
self.parent = wx.MDIParentFrame(None, -1, 'Editor')
self.child = wx.MDIChildFrame(self.parent, -1, 'Panda3D')
#Hauptfenster --> Main Window
self.parent.SetClientSize((1024, 768))
self.parent.Show(True)
#Panda Unter Fenster --> Panda Child Window
self.child.SetClientSize((640, 480))
self.child.Show(True)
base.windowType = 'onscreen'
props = WindowProperties.getDefault()
props.setParentWindow(self.child.GetHandle())
props.setOrigin(0,0) #
base.openDefaultWindow(props = props)
base.setFrameRateMeter(True) #base is panda
#Panda Child infos
self.child.Bind(wx.EVT_SIZE, self.childSize)
return True
def wx(self, task):
while self.evtloop.Pending():
self.evtloop.Dispatch()
#time.sleep(0.01)
self.ProcessIdle()
return task.cont
def childSize(self,event):
size = event.GetSize()
props = WindowProperties()
props.setOrigin(0,0)
props.setSize(size.width-10, size.height-10)
base.win.requestProperties(props)
def close(self):
wx.EventLoop.SetActive(self.old)
self.parent.Bind(wx.EVT_CLOSE,sys.exit)
app = App()
run()
Hi Folks,
some trouble with passing control between panda and wxPython
I took the above code
#!/usr/bin/env python
#Boa:PyApp:main
modules ={u'MDIParentFrame1': [0, '', u'MDIParentFrame1.py'],
u'MDIParentFrame2A': [0, '', u'../Shadows/MDIParentFrame2A.py']}
import wx
import time
import direct
from pandac.PandaModules import *
loadPrcFileData('startup', 'window-type none')
from direct.directbase.DirectStart import *
from direct.showbase import DirectObject
import MDIParentFrame1
import MDIParentFrame2A
class App(wx.PySimpleApp, DirectObject.DirectObject):
def __init__(self):
wx.PySimpleApp.__init__(self)
#Create a new event loop (to overide default wxEventLoop)
self.evtloop = wx.EventLoop()
self.old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.evtloop)
taskMgr.add(self.wx, "Custom wx Event Loop")
# wxWindows calls this method to initialize the application
def OnInit(self):
self.SetAppName('Editor')
self.SetClassName('MyAppClass')
#self.parent = wx.MDIParentFrame(None, -1, 'Editor')
self.parent = MDIParentFrame1.create(None)
#self.parent = MDIParentFrame2A.create(None)
self.child = wx.MDIChildFrame(self.parent, -1, 'Panda3D')
#Hauptfenster --> Main Window
self.parent.SetClientSize((1024, 768))
self.parent.Show(True)
#Panda Unter Fenster --> Panda Child Window
self.child.SetClientSize((640, 480))
self.child.Show(True)
base.windowType = 'onscreen'
props = WindowProperties.getDefault()
props.setParentWindow(self.child.GetHandle())
props.setOrigin(0,0) #
base.openDefaultWindow(props = props)
base.setFrameRateMeter(True) #base is panda
#Panda Child infos
self.child.Bind(wx.EVT_SIZE, self.childSize)
return True
def wx(self, task):
while self.evtloop.Pending():
self.evtloop.Dispatch()
time.sleep(0.01)
self.ProcessIdle()
return task.cont
def childSize(self,event):
size = event.GetSize()
props = WindowProperties()
props.setOrigin(0,0)
props.setSize(size.width-10, size.height-10)
base.win.requestProperties(props)
def close(self):
wx.EventLoop.SetActive(self.old)
self.parent.Bind(wx.EVT_CLOSE,sys.exit)
app = App()
run()
and a wx MDIParentFrame with just a panel and 2 buttons
#Boa:MDIParent:MDIParentFrame1
import wx
def create(parent):
return MDIParentFrame1(parent)
[wxID_MDIPARENTFRAME1, wxID_MDIPARENTFRAME1BUTTON1,
wxID_MDIPARENTFRAME1BUTTON2, wxID_MDIPARENTFRAME1PANEL1,
] = [wx.NewId() for _init_ctrls in range(4)]
class MDIParentFrame1(wx.MDIParentFrame):
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.MDIParentFrame.__init__(self, id=wxID_MDIPARENTFRAME1, name='',
parent=prnt, pos=wx.Point(685, 307), size=wx.Size(837, 656),
style=wx.DEFAULT_FRAME_STYLE | wx.VSCROLL | wx.HSCROLL,
title='MDIParentFrame1')
self.SetClientSize(wx.Size(829, 622))
self.panel1 = wx.Panel(id=wxID_MDIPARENTFRAME1PANEL1, name='panel1',
parent=self, pos=wx.Point(0, 0), size=wx.Size(800, 504),
style=wx.TAB_TRAVERSAL)
self.button1 = wx.Button(id=wxID_MDIPARENTFRAME1BUTTON1,
label='button1', name='button1', parent=self.panel1,
pos=wx.Point(688, 24), size=wx.Size(75, 23), style=0)
self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
id=wxID_MDIPARENTFRAME1BUTTON1)
self.button2 = wx.Button(id=wxID_MDIPARENTFRAME1BUTTON2,
label='button2', name='button2', parent=self.panel1,
pos=wx.Point(688, 56), size=wx.Size(75, 23), style=0)
def __init__(self, parent):
self._init_ctrls(parent)
def OnButton1Button(self, event):
self.log.write("Click! (%d)\n" % event.GetId())
that Button 2 is not reacting is evident but Button 1 also shows no reaction.
Greatful for any help
Martin
Hi,
I don’t have a solution for you, but here’s a bit of wx + panda code I’ve just got working; there don’t seem to be a whole ton of examples out there so hopefully this will be helpful. This is an example of loading an XRC file for the interface, and inserting a Panda window into it. The XRC file has a main window and a “properties” panel; this code sets up a splitter in the main window and inserts the properties panel and a panda panel into it.
import wxversion
wxversion.select('2.8')
import wx
from wx import xrc
from direct.showbase import DirectObject
from pandac.PandaModules import *
loadPrcFileData("", "window-type none")
from direct.directbase import DirectStart
class P3dViewport(wx.Panel):
# this panel contains the panda 3d window
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
def initialize(self):
# the panda3d window must be put into the panel after the wx-window has
# been created
assert self.GetHandle() != 0
# put the panda3d
wp = WindowProperties()
wp.setOrigin(0, 0)
wp.setSize(self.ClientSize.GetWidth(), self.ClientSize.GetHeight())
wp.setParentWindow(self.GetHandle())
base.openDefaultWindow(props = wp, gsg = None)
# attach the resize event
wx.EVT_SIZE(self, self.OnResize)
def OnResize(self, event):
# when the wx-panel is resized, fit the panda3d window into it
frame_size = event.GetSize()
wp = WindowProperties()
wp.setOrigin(0, 0)
wp.setSize(frame_size.GetWidth(), frame_size.GetHeight())
base.win.requestProperties(wp)
class EditorApp(DirectObject.DirectObject):
def __init__(self):
self.wxApp = wx.App(redirect = False)
self.wxApp.SetAppName("Panda Editor")
self.wxApp.SetClassName("PEditor")
self.appInit()
self.res = xrc.XmlResource ('viewer.xrc')
self.MainWindow = self.res.LoadFrame(None,'MainWindow')
self.MainWindow.Bind(wx.EVT_CLOSE, self.quit)
self.MainWindow.Show()
self.PropertiesPanel=self.res.LoadPanel(self.MainWindow,'PropertiesPanel')
self.MainSplitter = wx.SplitterWindow(self.MainWindow,style=wx.SP_3D | wx.SP_BORDER)
self.MainSplitter.SetMinimumPaneSize(200)
self.p3dViewport = P3dViewport(self.MainSplitter)
self.PropertiesPanel.Reparent(self.MainSplitter)
self.MainSplitter.SplitVertically (self.p3dViewport,self.PropertiesPanel,-220)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.MainSplitter,1,wx.EXPAND,0)
self.MainWindow.SetSizer(sizer)
self.MainWindow.Layout()
# update the wx-window and run a step (window created?)
self.MainWindow.Update()
self.wxStep()
# update the p3d window
self.p3dViewport.initialize()
# do something with the panda3d view
loader.loadModel('environment').reparentTo(render)
def appInit(self):
# Create a new event loop (to overide default wxEventLoop)
self.evtLoop = wx.EventLoop()
self.oldLoop = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.evtLoop)
taskMgr.add(self.wxStep, "evtLoopTask")
def onDestroy(self, evt):
# called on wx window destroy
wx.EventLoop.SetActive(self.oldLoop)
def quit(self,event):
self.onDestroy(event)
# to close Panda
try:
base
except NameError:
sys.exit()
base.userExit()
def wxStep(self, task = None):
# process the events wx sends
while self.evtLoop.Pending():
self.evtLoop.Dispatch()
self.wxApp.ProcessIdle()
if task != None: return task.cont
editorApp = EditorApp()
run()
Hi benchang,
could you include the .xrc as well? To analyse what’s going on this would be verry verry helpful.
Thanks
Martin
oh, yes - here you go. uh, I don’t see how to attach files so I’ll just paste it in. Sorry, it’s pretty long … save this as “viewer.xrc”. None of the gui elements do anything yet with this code, it’s just a starting point.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
<object class="wxFrame" name="MainWindow">
<style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
<size>783,560</size>
<title></title>
<object class="wxMenuBar" name="m_menubar1">
<label>MyMenuBar</label>
<object class="wxMenu" name="m_file">
<label>File</label>
<object class="wxMenuItem" name="m_menuItem141">
<label>&New</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem151">
<label>&Open</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem16">
<label>&Save</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem17">
<label>&Save As</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_Quit">
<label>&Quit</label>
<help></help>
</object>
</object>
<object class="wxMenu" name="m_edit">
<label>Edit</label>
<object class="wxMenuItem" name="m_menuItem11">
<label>Undo</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem12">
<label>Copy</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem13">
<label>Cut</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem14">
<label>Paste</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem15">
<label>Delete</label>
<help></help>
</object>
</object>
<object class="wxMenu" name="m_view">
<label>View</label>
</object>
<object class="wxMenu" name="m_settings">
<label>Settings</label>
<object class="wxMenuItem" name="m_menuItem9">
<label>Viewer Settings</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem10">
<label>Network Settings</label>
<help></help>
</object>
</object>
<object class="wxMenu" name="m_add">
<label>Add</label>
<object class="wxMenuItem" name="m_AddObject">
<label>Object</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem4">
<label>Environment</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem5">
<label>Animated Object</label>
<help></help>
</object>
<object class="separator" />
<object class="wxMenuItem" name="m_menuItem6">
<label>Point Light</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem7">
<label>Directional Light</label>
<help></help>
</object>
<object class="wxMenuItem" name="m_menuItem8">
<label>Spotlight</label>
<help></help>
</object>
</object>
</object>
<object class="wxStatusBar" name="m_statusBar1">
<style>wxST_SIZEGRIP</style>
<fields>1</fields>
</object>
</object>
<object class="wxPanel" name="PropertiesPanel">
<style>wxDOUBLE_BORDER|wxSUNKEN_BORDER|wxTAB_TRAVERSAL</style>
<size>238,589</size>
<font>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<option>0</option>
<flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText12">
<label>Properties</label>
</object>
</object>
<object class="sizeritem">
<option>1</option>
<flag>wxALL|wxEXPAND</flag>
<border>8</border>
<object class="wxPanel" name="m_panel7">
<style>wxTAB_TRAVERSAL</style>
<object class="wxGridSizer">
<rows>10</rows>
<cols>2</cols>
<vgap>2</vgap>
<hgap>2</hgap>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText2">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Translate X</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl5">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>10</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText3">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Translate Y</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl6">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText4">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Translate Z</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl7">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText6">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Rotate X</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl8">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText7">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Rotate Y</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl9">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText8">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Rotate Z</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl10">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText9">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Scale X</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl11">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText10">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Scale Y</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl12">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxStaticText" name="m_staticText11">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<label>Scale Z</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>5</border>
<object class="wxTextCtrl" name="m_textCtrl13">
<font>
<size>8</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
<value></value>
<maxlength>0</maxlength>
</object>
</object>
</object>
</object>
</object>
<object class="spacer">
<option>1</option>
<flag>wxEXPAND</flag>
<border>5</border>
<size>0,0</size>
</object>
</object>
</object>
</resource>
THX!
I have trouble with the xrc module on the machine I’m working now but I will get them sorted.
cheers
MArtin
Hi Benchang,
I get the following error when I try to run it:
C:\incoming>ppython viewer.py
DirectStart: Starting the game.
Traceback (most recent call last):
File “viewer.py”, line 111, in
editorApp = EditorApp()
File “viewer.py”, line 55, in init
self.PropertiesPanel=self.res.LoadPanel(self.MainWindow,‘PropertiesPanel’)
File “C:\Panda3D-1.6.2\python\lib\site-packages\wx-2.8-msw-unicode\wx\xrc.py”,
line 141, in LoadPanel
return _xrc.XmlResource_LoadPanel(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion “wxAssertFailure” failed at …\src\m
sw\window.cpp(1408) in wxWindow::MSWGetStyle(): unknown border style
oh, you’re on windows … I wonder if that panel has something linux-specific about it. Try opening the XRC file in WxFormBuilder?
Or, in the meantime: comment out that line, and the ones referring to PropertiesPanel; and replace the split() function so it just splits with a dummy panel
replace this
self.MainSplitter.SplitVertically (self.p3dViewport,self.PropertiesPanel,-220)
with this
self.MainSplitter.SplitVertically (self.p3dViewport,wx.Panel(),-220)
Hi sieracharlie,
or open the viewer.xrc with xrced and set a different border style under wxPanel"PropertiesPane"–Style.
and now I have get the buttons working.
By the way, benchang thank you; this will be a nice piece once its finished
thx
mARTIN
Turning off the double border style bit in the Properties panel lets the program come up on XP.
Very nice example of Panda hosted in WxPython.
Dear Folks,
I’m not shure if it’s coded elegantly but as benchang noted some exampels could be usefull
So I start with:
#!/usr/bin/env python
import wxversion
wxversion.select('2.8')
import wx
from wx import xrc
from direct.showbase import DirectObject
from pandac.PandaModules import *
loadPrcFileData("","window-type none")
from direct.directbase import DirectStart
#----------------------------------------------------------------------
# There are better ways to do IDs, but this demo requires that the window
# IDs be in a specific range. There are better ways to do that, too, but
# this will do for purposes of this demo.
ID_Menu_New = 5004
ID_Menu_Exit = 5005
ID_WINDOW_TOP = 5000
ID_WINDOW_LEFT1 = 5001
ID_WINDOW_LEFT2 = 5002
ID_WINDOW_BOTTOM = 5003
#----------------------------------------------------------------------
class P3dViewport(wx.Panel):
# this panel contains the panda 3d window
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
def initialize(self):
# the panda3d window must be put into the panel after the wx-window has
# been created
assert self.GetHandle() != 0
# put the panda3d
wp = WindowProperties()
wp.setOrigin(0,0)
wp.setSize(self.ClientSize.GetWidth(), self.ClientSize.GetHeight())
wp.setParentWindow(self.GetHandle())
base.openDefaultWindow(props = wp, gsg = None)
# attach the resize event
wx.EVT_SIZE(self, self.OnResize)
def OnResize(self, event):
# when the wx-panel is resized, fit the panda3d window into it
frame_size = event.GetSize()
wp = WindowProperties()
wp.setOrigin(0,0)
wp.setSize(frame_size.GetWidth(), frame_size.GetHeight())
base.win.requestProperties(wp)
class MyParentFrame(wx.MDIParentFrame):
def __init__(self):
wx.MDIParentFrame.__init__(
self, None, -1, "MDI Parent B", size=(690,785),
style = wx.DEFAULT_FRAME_STYLE | wx.HSCROLL | wx.VSCROLL
)
self.winCount = 0
self.res = xrc.XmlResource('WWLayout.xrc')
menubar = self.res.LoadMenuBar('Menu')
self.SetMenuBar(menubar)
self.CreateStatusBar()
#self.Bind(wx.EVT_MENU, self.OnNewWindow, id=ID_Menu_New)
self.Bind(wx.EVT_MENU, self.OnExit, id=ID_Menu_Exit)
self.Bind(
wx.EVT_SASH_DRAGGED_RANGE, self.OnSashDrag, id=ID_WINDOW_TOP,
id2=ID_WINDOW_BOTTOM
)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.MainWindow = self.res.LoadFrame(None,'Main')
self.p3dViewport = P3dViewport(self.MainWindow)
self.MainWindow.SetWindowStyle(wx.NO_BORDER)
self.MainWindow.Refresh()
self.MainWindow.Reparent(self)
self.MainWindow.Show()
self.MainWindow.Update()
# update the p3d window
self.p3dViewport.initialize()
#Create TopPanel
win = wx.SashLayoutWindow(self,-1,style=wx.SW_3D | wx.NO_BORDER)
win = wx.SashLayoutWindow(self, ID_WINDOW_TOP, style=wx.NO_BORDER|wx.SW_3D)
win.SetDefaultSize((690, 60))
win.SetOrientation(wx.LAYOUT_HORIZONTAL)
win.SetAlignment(wx.LAYOUT_TOP)
win.SetBackgroundColour(wx.Colour(0, 0, 0))
#win.SetSashVisible(wx.SASH_BOTTOM, True)
panel = self.res.LoadPanel(win,'TopPanel')
self.topWindow = win
#Create BottomPanel
win = wx.SashLayoutWindow(self, ID_WINDOW_BOTTOM, style=wx.NO_BORDER|wx.SW_3D)
win.SetDefaultSize((690,90))
win.SetOrientation(wx.LAYOUT_HORIZONTAL)
win.SetAlignment(wx.LAYOUT_BOTTOM)
win.SetBackgroundColour(wx.Colour(0, 0, 0))
#win.SetSashVisible(wx.SASH_TOP, True)
panel = self.res.LoadPanel(win,'BottomPanel')
self.bottomWindow = win
#Create LeftPanel
win = wx.SashLayoutWindow(self, ID_WINDOW_LEFT1, style=wx.NO_BORDER|wx.SW_3D)
win.SetDefaultSize((100, 645))
win.SetOrientation(wx.LAYOUT_VERTICAL)
win.SetAlignment(wx.LAYOUT_LEFT)
win.SetBackgroundColour(wx.Colour(0, 0, 0))
#win.SetSashVisible(wx.SASH_RIGHT, True)
#win.SetExtraBorderSize(10)
panel = self.res.LoadPanel(win,'LeftPanel')
self.leftWindow1 = win
#Create RightPanel
win = wx.SashLayoutWindow(self, ID_WINDOW_LEFT2, style=wx.NO_BORDER|wx.SW_3D)
win.SetDefaultSize((100, 645))
win.SetOrientation(wx.LAYOUT_VERTICAL)
win.SetAlignment(wx.LAYOUT_RIGHT)
win.SetBackgroundColour(wx.Colour(0, 0, 0))
#win.SetSashVisible(wx.SASH_LEFT, True)
panel = self.res.LoadPanel(win,'RightPanel')
self.leftWindow2 = win
def OnSashDrag(self, event):
if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
return
eID = event.GetId()
if eID == ID_WINDOW_TOP:
self.topWindow.SetDefaultSize((1000, event.GetDragRect().height))
elif eID == ID_WINDOW_LEFT1:
self.leftWindow1.SetDefaultSize((event.GetDragRect().width, 1000))
elif eID == ID_WINDOW_LEFT2:
self.leftWindow2.SetDefaultSize((event.GetDragRect().width, 1000))
elif eID == ID_WINDOW_BOTTOM:
self.bottomWindow.SetDefaultSize((1000, event.GetDragRect().height))
wx.LayoutAlgorithm().LayoutMDIFrame(self)
self.GetClientWindow().Refresh()
def OnSize(self, event):
wx.LayoutAlgorithm().LayoutMDIFrame(self)
xsize = self.GetSize().width-189
ysize = self.GetSize().height-227
self.MainWindow.SetSize((xsize,ysize))
self.MainWindow.SetPosition((83,60))
def OnExit(self, evt):
self.Close(True)
#def OnNewWindow(self, evt):
#self.winCount = self.winCount + 1
#win = wx.MDIChildFrame(self, -1, "Child Window: %d" % self.winCount)
#canvas = ScrolledWindow.MyCanvas(win)
#win.Show(True)
#----------------------------------------------------------------------
class EditorApp(DirectObject.DirectObject):
def __init__(self):
self.wxApp = wx.App(redirect = False)
self.wxApp.SetAppName("Panda Editor")
self.wxApp.SetClassName("PEditor")
self.appInit()
self.frame = MyParentFrame()
self.frame.Show()
self.frame.Update()
self.wxStep()
# do something with the panda3d view
loader.loadModel('A4.egg').reparentTo(render)
def appInit(self):
# Create a new event loop (to overide default wxEventLoop)
self.evtLoop = wx.EventLoop()
self.oldLoop = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.evtLoop)
taskMgr.add(self.wxStep, "evtLoopTask")
def onDestroy(self, evt):
# called on wx window destroy
wx.EventLoop.SetActive(self.oldLoop)
def quit(self,event):
self.onDestroy(event)
# to close Panda
try:
base
except NameError:
sys.exit()
base.userExit()
def wxStep(self, task = None):
# process the events wx sends
while self.evtLoop.Pending():
self.evtLoop.Dispatch()
self.wxApp.ProcessIdle()
if task != None: return task.cont
editorApp = EditorApp()
run()
with the .xrc
<?xml version="1.0" encoding="UTF-8"?>
<resource version="2.3.0.1" xmlns="http://www.wxwindows.org/wxxrc">
<object class="wxMenuBar" name="Menu">
<object class="wxMenu" name="File">
<label>File</label>
<object class="wxMenuItem" name="Open">
<label>Open</label>
</object>
<object class="separator"/>
<object class="wxMenuItem" name="Exit">
<label>Exit</label>
</object>
</object>
</object>
<object class="wxPanel" name="TopPanel">
</object>
<object class="wxPanel" name="LeftPanel">
</object>
<object class="wxPanel" name="RightPanel">
</object>
<object class="wxPanel" name="BottomPanel">
</object>
<object class="wxFrame" name="Main">
<pos>100,90</pos>
<size>490,635</size>
</object>
</resource>
I’m not using the sash to resize the panda window so they have been disabeled
cheers
Martin
I have shortened it a bit, as I find it useful to have the most concise example possible so that I can elaborate on it myself. So if you’re like me, you might appreciate this :
import sys
import wx
import direct
from pandac.PandaModules import *
loadPrcFileData('startup', 'window-type none')
from direct.directbase.DirectStart import *
from direct.showbase import DirectObject
class PandaPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
def initialize(self):
assert self.GetHandle() != 0
wp = WindowProperties()
wp.setOrigin(0,0)
wp.setSize(self.ClientSize.GetWidth(), self.ClientSize.GetHeight())
wp.setParentWindow(self.GetHandle())
base.openDefaultWindow(props = wp, gsg = None)
self.Bind(wx.EVT_SIZE, self.OnResize)
def OnResize(self, event):
frame_size = event.GetSize()
wp = WindowProperties()
wp.setOrigin(0,0)
wp.setSize(frame_size.GetWidth(), frame_size.GetHeight())
base.win.requestProperties(wp)
class PandaFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.pandapanel = PandaPanel(self, wx.ID_ANY)
self.pandapanel.initialize()
class PandaApp(wx.App, DirectObject.DirectObject):
def __init__(self):
wx.App.__init__(self)
self.replaceEventLoop()
self.frame = PandaFrame(None, wx.ID_ANY, 'Panda App')
self.frame.Bind(wx.EVT_CLOSE, self.quit)
self.frame.Show()
self.wxStep()
def replaceEventLoop(self):
self.evtLoop = wx.EventLoop()
self.oldLoop = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(self.evtLoop)
taskMgr.add(self.wxStep, "evtLoopTask")
def onDestroy(self, event=None):
self.wxStep()
wx.EventLoop.SetActive(self.oldLoop)
def quit(self, event=None):
self.onDestroy(event)
try:
base
except NameError:
sys.exit()
base.userExit()
def wxStep(self, task=None):
while self.evtLoop.Pending():
self.evtLoop.Dispatch()
self.ProcessIdle()
if task != None: return task.cont
app = PandaApp()
run()
Edit to add, no .xrc file needed - it’s just a single frame.
I’ve got this message repetedly from command shell, that when I close the application I can’t use the command shell anymore and I have to close it immediately:
:display:gsg:dxgsg8(error): show_frame() - Present() failed at (panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx:3952), hr=D3DERR_INVALIDCALL: Invalid call
I’m using the dwrw code in the first page
I guess Panda is mad that its window has been destroyed by some external event (such as wx shutting down). Perhaps you need to have a callback on wx.Exit() or whatever call it is that wx makes when the program exits, and call base.destroy() at that point.
David
Thanks David for giving me a light. Panda is not mad anymore.
I found this on this thread, benchang posted it:
def onDestroy(self, evt):
# called on wx window destroy
wx.EventLoop.SetActive(self.old)
def quit(self,event):
self.onDestroy(event)
# to close Panda
try:
base
except NameError:
sys.exit()
base.userExit()
hey, do you know why wxpython takes long to respond to shortcuts such as Ctrl+key when running with panda? how do I avoid this behavior?
thanks.
Thanks for this, steego! I had to make two minor adjustments to get it to work, though. I’m using Ubuntu 10.04, with wxPython 2.8.10.1.
With the code you provided, I got the following error:
(python:10821): Gdk-WARNING **: /build/buildd/gtk+2.0-2.20.1/gdk/x11/gdkdrawable-x11.c:952 drawable is not a pixmap or window
Traceback (most recent call last):
File "panda-in-wx.py", line 71, in <module>
app = PandaApp()
File "panda-in-wx.py", line 42, in __init__
self.frame = PandaFrame(None, wx.ID_ANY, 'Panda App')
File "panda-in-wx.py", line 35, in __init__
self.pandapanel.initialize()
File "panda-in-wx.py", line 15, in initialize
assert self.GetHandle() != 0
AssertionError
To solve this, I had to make the PandaFrame show itself before initializing the PandaPanel. So I changed its init function to the following:
class PandaFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.Show()
self.pandapanel = PandaPanel(self, wx.ID_ANY)
self.pandapanel.initialize()
Of course, this means you can remove the self.frame.Show() line from the PandaApp init function.
But after getting it to work, I noticed that the PandaPanel started out much smaller than the window size: just 20x20. It didn’t grow to match the window size until I actually resized the window (with the mouse, while the app was running). So I explicitly passed the PandaFrame’s size to the PandaPanel constructor:
class PandaFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.Show()
self.pandapanel = PandaPanel(self, wx.ID_ANY, size=self.ClientSize)
self.pandapanel.initialize()
That did the trick.