Fix wxPython and tkinter issues on Mac OS X

This commit is contained in:
rdb 2016-06-10 02:00:54 +02:00
parent 0a731d0545
commit 12873c0d7e
3 changed files with 46 additions and 8 deletions

View File

@ -205,7 +205,9 @@ class ShowBase(DirectObject.DirectObject):
## This is used to store the wx.Application object used when want-wx is ## This is used to store the wx.Application object used when want-wx is
## set or base.startWx() is called. ## set or base.startWx() is called.
self.wxApp = None self.wxApp = None
self.wxAppCreated = False
self.tkRoot = None self.tkRoot = None
self.tkRootCreated = False
# This is used for syncing multiple PCs in a distributed cluster # This is used for syncing multiple PCs in a distributed cluster
try: try:
@ -262,6 +264,17 @@ class ShowBase(DirectObject.DirectObject):
random.seed(seed) random.seed(seed)
#whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff) #whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff)
# For some reason, wx needs to be initialized before the graphics window
if sys.platform == "darwin":
if self.config.GetBool("want-wx", 0):
import wx
self.wxApp = wx.App()
# Same goes for Tk, which uses a conflicting NSApplication
if self.config.GetBool("want-tk", 0):
import Pmw
self.tkRoot = Pmw.initialise()
# Open the default rendering window. # Open the default rendering window.
if self.windowType != 'none': if self.windowType != 'none':
props = WindowProperties.getDefault() props = WindowProperties.getDefault()
@ -2804,15 +2817,16 @@ class ShowBase(DirectObject.DirectObject):
updated, but wxPython owns the main loop (which seems to make updated, but wxPython owns the main loop (which seems to make
it happier than the other way around). """ it happier than the other way around). """
if self.wxApp: if self.wxAppCreated:
# Don't do this twice. # Don't do this twice.
return return
init_app_for_gui() init_app_for_gui()
import wx import wx
# Create a new base.wxApp. if not self.wxApp:
self.wxApp = wx.PySimpleApp(redirect = False) # Create a new base.wxApp.
self.wxApp = wx.PySimpleApp(redirect = False)
if ConfigVariableBool('wx-main-loop', True): if ConfigVariableBool('wx-main-loop', True):
# Put wxPython in charge of the main loop. It really # Put wxPython in charge of the main loop. It really
@ -2847,6 +2861,7 @@ class ShowBase(DirectObject.DirectObject):
return task.again return task.again
self.taskMgr.add(wxLoop, 'wxLoop') self.taskMgr.add(wxLoop, 'wxLoop')
self.wxAppCreated = True
def __wxTimerCallback(self, event): def __wxTimerCallback(self, event):
if Thread.getCurrentThread().getCurrentTask(): if Thread.getCurrentThread().getCurrentTask():
@ -2881,7 +2896,7 @@ class ShowBase(DirectObject.DirectObject):
updated, but Tkinter owns the main loop (which seems to make updated, but Tkinter owns the main loop (which seems to make
it happier than the other way around). """ it happier than the other way around). """
if self.tkRoot: if self.tkRootCreated:
# Don't do this twice. # Don't do this twice.
return return
@ -2889,7 +2904,8 @@ class ShowBase(DirectObject.DirectObject):
import Pmw import Pmw
# Create a new Tk root. # Create a new Tk root.
self.tkRoot = Pmw.initialise() if not self.tkRoot:
self.tkRoot = Pmw.initialise()
builtins.tkroot = self.tkRoot builtins.tkroot = self.tkRoot
init_app_for_gui() init_app_for_gui()
@ -2925,6 +2941,7 @@ class ShowBase(DirectObject.DirectObject):
return task.again return task.again
self.taskMgr.add(tkLoop, 'tkLoop') self.taskMgr.add(tkLoop, 'tkLoop')
self.tkRootCreated = True
def __tkTimerCallback(self): def __tkTimerCallback(self):
if not Thread.getCurrentThread().getCurrentTask(): if not Thread.getCurrentThread().getCurrentTask():

View File

@ -26,4 +26,24 @@
[super sendEvent: event]; [super sendEvent: event];
} }
} }
- (void) _setup: (void *) interp {
// This is called by Tk when it launches and naively assumes that it is
// the first to create an NSApplication. We can't do anything about it
// at this point except display an error message.
cocoadisplay_cat.error()
<< "Detected attempt to initialize Tk after creating a Panda window. "
"This will likely cause a crash.\n"
"To fix this, set 'want-tk true' in Config.prc to force "
"initialization of Tk before opening the Panda window.\n";
}
- (void) _setupEventLoop {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self finishLaunching];
[self setWindowsNeedUpdate:YES];
[pool drain];
}
@end @end

View File

@ -17,13 +17,14 @@ try:
except: except:
sys.exit("Please install Python megawidgets") sys.exit("Please install Python megawidgets")
# Makes sure that Panda is configured to play nice with Tkinter
from panda3d.core import *
loadPrcFileData("", "want-tk true")
# Open the Panda window # Open the Panda window
from direct.showbase.ShowBase import ShowBase from direct.showbase.ShowBase import ShowBase
base = ShowBase() base = ShowBase()
# Makes sure that Panda is configured to play nice with Tkinter
base.startTk()
from direct.tkpanels.ParticlePanel import ParticlePanel from direct.tkpanels.ParticlePanel import ParticlePanel
pp = ParticlePanel() # Create the panel pp = ParticlePanel() # Create the panel