Added wxWakeUpMainThread, wxMutexGuiEnter, wxMutexGuiLeave,

wxMutexGuiLocker and wxThread_IsMain to assist with dealing with GUI
access from non-GUI threads.

wxPyOnDemandOutputWindow is now thread safe if non-GUI threads use
print, sys.stdout.write, etc.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9590 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn 2001-03-26 22:17:24 +00:00
parent c1e820a40e
commit 6e18ca6cf4
8 changed files with 297 additions and 49 deletions

View File

@ -17,6 +17,13 @@ Also wxTheColourDatabase and added a library module (in the
wxPython.lib.colourdb module) to load LOTS more colour names into the
colour database.
Added wxWakeUpMainThread, wxMutexGuiEnter, wxMutexGuiLeave,
wxMutexGuiLocker and wxThread_IsMain to assist with dealing with GUI
access from non-GUI threads.
wxPyOnDemandOutputWindow is now thread safe if non-GUI threads use
print, sys.stdout.write, etc.

View File

@ -714,20 +714,22 @@ class wxPyOnDemandOutputWindow:
self.title = title
self.parent = None
def SetParent(self, parent):
self.parent = parent
def OnCloseWindow(self, event):
if self.frame != None:
self.frame.Destroy()
self.frame = None
self.text = None
# this provides the file-like output behaviour
# These methods provide the file-like output behaviour.
def write(self, str):
if not wxThread_IsMain():
# Aquire the GUI mutex before making GUI calls. Mutex is released
# when locker is deleted a the end of this function.
locker = wxMutexGuiLocker()
if not self.frame:
self.frame = wxFrame(self.parent, -1, self.title)
self.text = wxTextCtrl(self.frame, -1, "",
@ -737,13 +739,13 @@ class wxPyOnDemandOutputWindow:
EVT_CLOSE(self.frame, self.OnCloseWindow)
self.text.AppendText(str)
def close(self):
if self.frame != None:
if not wxThread_IsMain():
locker = wxMutexGuiLocker()
self.frame.Close()
_defRedirect = (wxPlatform == '__WXMSW__')
#----------------------------------------------------------------------

View File

@ -382,10 +382,28 @@ public:
//----------------------------------------------------------------------
bool wxSafeYield(wxWindow* win=NULL);
void wxPostEvent(wxEvtHandler *dest, wxEvent& event);
void wxWakeUpIdle();
bool wxSafeYield(wxWindow* win=NULL);
void wxWakeUpMainThread();
void wxMutexGuiEnter();
void wxMutexGuiLeave();
class wxMutexGuiLocker {
public:
wxMutexGuiLocker();
~wxMutexGuiLocker();
};
%inline %{
bool wxThread_IsMain() {
return wxThread::IsMain();
}
%}
//----------------------------------------------------------------------

View File

@ -66,12 +66,12 @@ extern PyObject *SWIG_newvarlink(void);
static PyObject* l_output_helper(PyObject* target, PyObject* o) {
PyObject* o2;
if (!target) {
if (!target) {
target = o;
} else if (target == Py_None) {
} else if (target == Py_None) {
Py_DECREF(Py_None);
target = o;
} else {
} else {
if (!PyList_Check(target)) {
o2 = target;
target = PyList_New(0);
@ -88,23 +88,23 @@ static PyObject* t_output_helper(PyObject* target, PyObject* o) {
PyObject* o2;
PyObject* o3;
if (!target) {
if (!target) {
target = o;
} else if (target == Py_None) {
} else if (target == Py_None) {
Py_DECREF(Py_None);
target = o;
} else {
} else {
if (!PyTuple_Check(target)) {
o2 = target;
target = PyTuple_New(1);
PyTuple_SetItem(target, 0, o2);
}
o3 = PyTuple_New(1);
PyTuple_SetItem(o3, 0, o);
o3 = PyTuple_New(1);
PyTuple_SetItem(o3, 0, o);
o2 = target;
target = PySequence_Concat(o2, o3);
Py_DECREF(o2);
target = PySequence_Concat(o2, o3);
Py_DECREF(o2);
Py_DECREF(o3);
}
return target;
@ -158,6 +158,10 @@ IMP_PYCALLBACK_BOOL_STRING(wxPyFontEnumerator, wxFontEnumerator, OnFacename);
IMP_PYCALLBACK_BOOL_STRINGSTRING(wxPyFontEnumerator, wxFontEnumerator, OnFontEncoding);
bool wxThread_IsMain() {
return wxThread::IsMain();
}
class wxPyTipProvider : public wxTipProvider {
public:
wxPyTipProvider(size_t currentTip)
@ -1547,6 +1551,32 @@ static PyObject *_wrap_wxCaret_SetBlinkTime(PyObject *self, PyObject *args, PyOb
return _resultobj;
}
static PyObject *_wrap_wxSafeYield(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxWindow * _arg0 = (wxWindow *) NULL;
PyObject * _argo0 = 0;
char *_kwnames[] = { "win", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"|O:wxSafeYield",_kwnames,&_argo0))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxWindow_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxSafeYield. Expected _wxWindow_p.");
return NULL;
}
}
{
wxPy_BEGIN_ALLOW_THREADS;
_result = (bool )wxSafeYield(_arg0);
wxPy_END_ALLOW_THREADS;
} _resultobj = Py_BuildValue("i",_result);
return _resultobj;
}
static PyObject *_wrap_wxPostEvent(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
wxEvtHandler * _arg0;
@ -1599,26 +1629,68 @@ static PyObject *_wrap_wxWakeUpIdle(PyObject *self, PyObject *args, PyObject *kw
return _resultobj;
}
static PyObject *_wrap_wxSafeYield(PyObject *self, PyObject *args, PyObject *kwargs) {
static PyObject *_wrap_wxWakeUpMainThread(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxWindow * _arg0 = (wxWindow *) NULL;
PyObject * _argo0 = 0;
char *_kwnames[] = { "win", NULL };
char *_kwnames[] = { NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"|O:wxSafeYield",_kwnames,&_argo0))
if(!PyArg_ParseTupleAndKeywords(args,kwargs,":wxWakeUpMainThread",_kwnames))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxWindow_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxSafeYield. Expected _wxWindow_p.");
return NULL;
}
}
{
wxPy_BEGIN_ALLOW_THREADS;
_result = (bool )wxSafeYield(_arg0);
wxWakeUpMainThread();
wxPy_END_ALLOW_THREADS;
} Py_INCREF(Py_None);
_resultobj = Py_None;
return _resultobj;
}
static PyObject *_wrap_wxMutexGuiEnter(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
char *_kwnames[] = { NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,":wxMutexGuiEnter",_kwnames))
return NULL;
{
wxPy_BEGIN_ALLOW_THREADS;
wxMutexGuiEnter();
wxPy_END_ALLOW_THREADS;
} Py_INCREF(Py_None);
_resultobj = Py_None;
return _resultobj;
}
static PyObject *_wrap_wxMutexGuiLeave(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
char *_kwnames[] = { NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,":wxMutexGuiLeave",_kwnames))
return NULL;
{
wxPy_BEGIN_ALLOW_THREADS;
wxMutexGuiLeave();
wxPy_END_ALLOW_THREADS;
} Py_INCREF(Py_None);
_resultobj = Py_None;
return _resultobj;
}
static PyObject *_wrap_wxThread_IsMain(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
char *_kwnames[] = { NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,":wxThread_IsMain",_kwnames))
return NULL;
{
wxPy_BEGIN_ALLOW_THREADS;
_result = (bool )wxThread_IsMain();
wxPy_END_ALLOW_THREADS;
} _resultobj = Py_BuildValue("i",_result);
@ -3160,6 +3232,58 @@ static PyObject *_wrap_delete_wxWindowDisabler(PyObject *self, PyObject *args, P
return _resultobj;
}
#define new_wxMutexGuiLocker() (new wxMutexGuiLocker())
static PyObject *_wrap_new_wxMutexGuiLocker(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
wxMutexGuiLocker * _result;
char *_kwnames[] = { NULL };
char _ptemp[128];
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,":new_wxMutexGuiLocker",_kwnames))
return NULL;
{
wxPy_BEGIN_ALLOW_THREADS;
_result = (wxMutexGuiLocker *)new_wxMutexGuiLocker();
wxPy_END_ALLOW_THREADS;
} if (_result) {
SWIG_MakePtr(_ptemp, (char *) _result,"_wxMutexGuiLocker_p");
_resultobj = Py_BuildValue("s",_ptemp);
} else {
Py_INCREF(Py_None);
_resultobj = Py_None;
}
return _resultobj;
}
#define delete_wxMutexGuiLocker(_swigobj) (delete _swigobj)
static PyObject *_wrap_delete_wxMutexGuiLocker(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
wxMutexGuiLocker * _arg0;
PyObject * _argo0 = 0;
char *_kwnames[] = { "self", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O:delete_wxMutexGuiLocker",_kwnames,&_argo0))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxMutexGuiLocker_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of delete_wxMutexGuiLocker. Expected _wxMutexGuiLocker_p.");
return NULL;
}
}
{
wxPy_BEGIN_ALLOW_THREADS;
delete_wxMutexGuiLocker(_arg0);
wxPy_END_ALLOW_THREADS;
} Py_INCREF(Py_None);
_resultobj = Py_None;
return _resultobj;
}
#define delete_wxTipProvider(_swigobj) (delete _swigobj)
static PyObject *_wrap_delete_wxTipProvider(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
@ -6616,6 +6740,8 @@ static PyMethodDef misc2cMethods[] = {
{ "wxTipProvider_GetCurrentTip", (PyCFunction) _wrap_wxTipProvider_GetCurrentTip, METH_VARARGS | METH_KEYWORDS },
{ "wxTipProvider_GetTip", (PyCFunction) _wrap_wxTipProvider_GetTip, METH_VARARGS | METH_KEYWORDS },
{ "delete_wxTipProvider", (PyCFunction) _wrap_delete_wxTipProvider, METH_VARARGS | METH_KEYWORDS },
{ "delete_wxMutexGuiLocker", (PyCFunction) _wrap_delete_wxMutexGuiLocker, METH_VARARGS | METH_KEYWORDS },
{ "new_wxMutexGuiLocker", (PyCFunction) _wrap_new_wxMutexGuiLocker, METH_VARARGS | METH_KEYWORDS },
{ "delete_wxWindowDisabler", (PyCFunction) _wrap_delete_wxWindowDisabler, METH_VARARGS | METH_KEYWORDS },
{ "new_wxWindowDisabler", (PyCFunction) _wrap_new_wxWindowDisabler, METH_VARARGS | METH_KEYWORDS },
{ "delete_wxBusyCursor", (PyCFunction) _wrap_delete_wxBusyCursor, METH_VARARGS | METH_KEYWORDS },
@ -6664,9 +6790,13 @@ static PyMethodDef misc2cMethods[] = {
{ "wxDragIcon", (PyCFunction) _wrap_wxDragIcon, METH_VARARGS | METH_KEYWORDS },
{ "wxCreateFileTipProvider", (PyCFunction) _wrap_wxCreateFileTipProvider, METH_VARARGS | METH_KEYWORDS },
{ "wxShowTip", (PyCFunction) _wrap_wxShowTip, METH_VARARGS | METH_KEYWORDS },
{ "wxSafeYield", (PyCFunction) _wrap_wxSafeYield, METH_VARARGS | METH_KEYWORDS },
{ "wxThread_IsMain", (PyCFunction) _wrap_wxThread_IsMain, METH_VARARGS | METH_KEYWORDS },
{ "wxMutexGuiLeave", (PyCFunction) _wrap_wxMutexGuiLeave, METH_VARARGS | METH_KEYWORDS },
{ "wxMutexGuiEnter", (PyCFunction) _wrap_wxMutexGuiEnter, METH_VARARGS | METH_KEYWORDS },
{ "wxWakeUpMainThread", (PyCFunction) _wrap_wxWakeUpMainThread, METH_VARARGS | METH_KEYWORDS },
{ "wxWakeUpIdle", (PyCFunction) _wrap_wxWakeUpIdle, METH_VARARGS | METH_KEYWORDS },
{ "wxPostEvent", (PyCFunction) _wrap_wxPostEvent, METH_VARARGS | METH_KEYWORDS },
{ "wxSafeYield", (PyCFunction) _wrap_wxSafeYield, METH_VARARGS | METH_KEYWORDS },
{ "wxCaret_SetBlinkTime", (PyCFunction) _wrap_wxCaret_SetBlinkTime, METH_VARARGS | METH_KEYWORDS },
{ "wxCaret_GetBlinkTime", (PyCFunction) _wrap_wxCaret_GetBlinkTime, METH_VARARGS | METH_KEYWORDS },
{ "wxToolTip_SetDelay", (PyCFunction) _wrap_wxToolTip_SetDelay, METH_VARARGS | METH_KEYWORDS },
@ -6744,6 +6874,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_wxCursor","_class_wxCursor",0},
{ "_wxNotifyEvent","_class_wxNotifyEvent",0},
{ "_wxPyProcess","_class_wxPyProcess",0},
{ "_wxMutexGuiLocker","_class_wxMutexGuiLocker",0},
{ "_wxLog","_class_wxLogWindow",SwigwxLogWindowTowxLog},
{ "_wxLog","_wxLogWindow",SwigwxLogWindowTowxLog},
{ "_wxLog","_class_wxLogGui",SwigwxLogGuiTowxLog},
@ -6760,6 +6891,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_byte","_unsigned_char",0},
{ "_wxDataObject","_class_wxDataObject",0},
{ "_class_wxPyFontEnumerator","_wxPyFontEnumerator",0},
{ "_wxColourDatabase","_class_wxColourDatabase",0},
{ "_wxPyDataObjectSimple","_class_wxPyDataObjectSimple",0},
{ "_wxPyDropSource","_class_wxPyDropSource",0},
{ "_long","_unsigned_long",0},
@ -6825,6 +6957,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_class_wxWindowDisabler","_wxWindowDisabler",0},
{ "_char","_wxChar",0},
{ "_wxBitmap","_class_wxBitmap",0},
{ "_wxPenList","_class_wxPenList",0},
{ "_wxWindowDC","_class_wxWindowDC",0},
{ "_wxTimerEvent","_class_wxTimerEvent",0},
{ "_wxPyTimer","_class_wxPyTimer",0},
@ -6832,9 +6965,11 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_class_wxNotifyEvent","_wxNotifyEvent",0},
{ "_class_wxValidator","_wxValidator",0},
{ "_class_wxPyEvent","_wxPyEvent",0},
{ "_class_wxMutexGuiLocker","_wxMutexGuiLocker",0},
{ "_class_wxIconizeEvent","_wxIconizeEvent",0},
{ "_class_wxBusyCursor","_wxBusyCursor",0},
{ "_wxDropTarget","_class_wxDropTarget",0},
{ "_class_wxColourDatabase","_wxColourDatabase",0},
{ "_wxScrollEvent","_class_wxScrollEvent",0},
{ "_EBool","_wxCoord",0},
{ "_EBool","_wxPrintQuality",0},
@ -6854,8 +6989,10 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_class_wxDC","_wxDC",0},
{ "_wxScrollWinEvent","_class_wxScrollWinEvent",0},
{ "_wxGenericDragImage","_class_wxGenericDragImage",0},
{ "_class_wxBrushList","_wxBrushList",0},
{ "_wxQueryNewPaletteEvent","_class_wxQueryNewPaletteEvent",0},
{ "_wxPyInputStream","_class_wxPyInputStream",0},
{ "_class_wxPenList","_wxPenList",0},
{ "_class_wxWindowCreateEvent","_wxWindowCreateEvent",0},
{ "_class_wxOutputStream","_wxOutputStream",0},
{ "_wxLogTextCtrl","_class_wxLogTextCtrl",0},
@ -6894,6 +7031,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_class_wxPyValidator","_wxPyValidator",0},
{ "_class_wxCloseEvent","_wxCloseEvent",0},
{ "_wxBusyInfo","_class_wxBusyInfo",0},
{ "_wxFontList","_class_wxFontList",0},
{ "_class_wxMenuEvent","_wxMenuEvent",0},
{ "_wxPaletteChangedEvent","_class_wxPaletteChangedEvent",0},
{ "_wxJoystick","_class_wxJoystick",0},
@ -7020,10 +7158,12 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_wxPyDropTarget","_class_wxPyDropTarget",0},
{ "_wxActivateEvent","_class_wxActivateEvent",0},
{ "_class_wxBusyInfo","_wxBusyInfo",0},
{ "_class_wxFontList","_wxFontList",0},
{ "_class_wxJoystick","_wxJoystick",0},
{ "_class_wxCommandEvent","_wxCommandEvent",0},
{ "_class_wxClientDC","_wxClientDC",0},
{ "_class_wxSizeEvent","_wxSizeEvent",0},
{ "_wxBrushList","_class_wxBrushList",0},
{ "_wxCustomDataObject","_class_wxCustomDataObject",0},
{ "_class_wxLogNull","_wxLogNull",0},
{ "_class_wxSize","_wxSize",0},

View File

@ -162,6 +162,23 @@ class wxWindowDisabler(wxWindowDisablerPtr):
class wxMutexGuiLockerPtr :
def __init__(self,this):
self.this = this
self.thisown = 0
def __del__(self,misc2c=misc2c):
if self.thisown == 1 :
misc2c.delete_wxMutexGuiLocker(self)
def __repr__(self):
return "<C wxMutexGuiLocker instance at %s>" % (self.this,)
class wxMutexGuiLocker(wxMutexGuiLockerPtr):
def __init__(self,*_args,**_kwargs):
self.this = apply(misc2c.new_wxMutexGuiLocker,_args,_kwargs)
self.thisown = 1
class wxTipProviderPtr :
def __init__(self,this):
self.this = this
@ -716,11 +733,19 @@ wxCaret_GetBlinkTime = misc2c.wxCaret_GetBlinkTime
wxCaret_SetBlinkTime = misc2c.wxCaret_SetBlinkTime
wxSafeYield = misc2c.wxSafeYield
wxPostEvent = misc2c.wxPostEvent
wxWakeUpIdle = misc2c.wxWakeUpIdle
wxSafeYield = misc2c.wxSafeYield
wxWakeUpMainThread = misc2c.wxWakeUpMainThread
wxMutexGuiEnter = misc2c.wxMutexGuiEnter
wxMutexGuiLeave = misc2c.wxMutexGuiLeave
wxThread_IsMain = misc2c.wxThread_IsMain
wxShowTip = misc2c.wxShowTip

View File

@ -59,12 +59,12 @@ extern PyObject *SWIG_newvarlink(void);
static PyObject* l_output_helper(PyObject* target, PyObject* o) {
PyObject* o2;
if (!target) {
if (!target) {
target = o;
} else if (target == Py_None) {
} else if (target == Py_None) {
Py_DECREF(Py_None);
target = o;
} else {
} else {
if (!PyList_Check(target)) {
o2 = target;
target = PyList_New(0);
@ -81,23 +81,23 @@ static PyObject* t_output_helper(PyObject* target, PyObject* o) {
PyObject* o2;
PyObject* o3;
if (!target) {
if (!target) {
target = o;
} else if (target == Py_None) {
} else if (target == Py_None) {
Py_DECREF(Py_None);
target = o;
} else {
} else {
if (!PyTuple_Check(target)) {
o2 = target;
target = PyTuple_New(1);
PyTuple_SetItem(target, 0, o2);
}
o3 = PyTuple_New(1);
PyTuple_SetItem(o3, 0, o);
o3 = PyTuple_New(1);
PyTuple_SetItem(o3, 0, o);
o2 = target;
target = PySequence_Concat(o2, o3);
Py_DECREF(o2);
target = PySequence_Concat(o2, o3);
Py_DECREF(o2);
Py_DECREF(o3);
}
return target;
@ -1829,6 +1829,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_wxPyProcess","_class_wxPyProcess",0},
{ "_wxPyTreeCtrl","_class_wxPyTreeCtrl",0},
{ "_wxImageHandler","_class_wxImageHandler",0},
{ "_wxMutexGuiLocker","_class_wxMutexGuiLocker",0},
{ "_wxLog","_class_wxLog",0},
{ "_class_wxToolBarBase","_wxToolBarBase",0},
{ "_wxMask","_class_wxMask",0},
@ -1974,6 +1975,7 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_wxMessageDialog","_class_wxMessageDialog",0},
{ "_class_wxValidator","_wxValidator",0},
{ "_class_wxPyEvent","_wxPyEvent",0},
{ "_class_wxMutexGuiLocker","_wxMutexGuiLocker",0},
{ "_wxTextEntryDialog","_class_wxTextEntryDialog",0},
{ "_wxConfig","_class_wxConfig",0},
{ "_class_wxIconizeEvent","_wxIconizeEvent",0},

View File

@ -1535,20 +1535,22 @@ class wxPyOnDemandOutputWindow:
self.title = title
self.parent = None
def SetParent(self, parent):
self.parent = parent
def OnCloseWindow(self, event):
if self.frame != None:
self.frame.Destroy()
self.frame = None
self.text = None
# this provides the file-like output behaviour
# These methods provide the file-like output behaviour.
def write(self, str):
if not wxThread_IsMain():
# Aquire the GUI mutex before making GUI calls. Mutex is released
# when locker is deleted a the end of this function.
locker = wxMutexGuiLocker()
if not self.frame:
self.frame = wxFrame(self.parent, -1, self.title)
self.text = wxTextCtrl(self.frame, -1, "",
@ -1558,13 +1560,13 @@ class wxPyOnDemandOutputWindow:
EVT_CLOSE(self.frame, self.OnCloseWindow)
self.text.AppendText(str)
def close(self):
if self.frame != None:
if not wxThread_IsMain():
locker = wxMutexGuiLocker()
self.frame.Close()
_defRedirect = (wxPlatform == '__WXMSW__')
#----------------------------------------------------------------------

View File

@ -0,0 +1,52 @@
from time import sleep
from threading import Thread
def test_a_window():
print "starting window thread"
from wxPython.wx import * # <-- the wxWin DLL is not loaded until here
app = wxPySimpleApp(1)
frame = wxFrame(None, -1, "Hello", size=(400,200))
frame.Show(true)
EVT_SIZE(frame, OnFrameSize)
app.MainLoop()
print "finishing window thread"
def OnFrameSize(evt):
print evt.GetSize()
keep_going = 1
def counter():
print "starting counter thread"
count = 0
while keep_going:
sleep(1)
count += 1
print count
print "finishing counter thread"
def main():
print "main startup"
ct = Thread(target=counter)
wt = Thread(target=test_a_window)
ct.start()
wt.start()
wt.join()
global keep_going
keep_going = 0
ct.join()
print "main finished"
main()