Added a demo showing how to use wxPostEvent

Added an MVCTree contribution
Some final tweaks for this release


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4536 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn 1999-11-13 05:52:53 +00:00
parent 3739399733
commit e19b716460
6 changed files with 1343 additions and 15 deletions

View File

@ -45,6 +45,7 @@ Or you can send mail directly to the list using this address:
----------------------------------------------------------------------
What's new in 2.1.11
--------------------
Skipped a few version numbers so wxMSW, wxGTK and wxPython are all
@ -88,13 +89,12 @@ Many updates to wxMenu, wxMenuBar.
wxPyEvent and wxPyCommandEvent derived classes now give you the actual
Python object in the event handler instead of a new shadow.
Added a Calendar widget from Lorne White.
Made some fixes to the wxFloatbar.
Added the HTML printing classes.
Added a Calendar widget from Lorne White to the library.
Made some fixes to the wxFloatbar. It still has some troubles on
wxGTK...
Added an MVC tree control from Bryn Keller to the library.

View File

@ -42,7 +42,8 @@ _treeList = [
('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator',
'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
'wxImage', 'PrintFramework', 'wxOGL', 'PythonEvents']),
'wxImage', 'PrintFramework', 'wxOGL', 'PythonEvents',
'Threads']),
('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',

View File

@ -0,0 +1,216 @@
from wxPython.wx import *
import thread
import time
from whrandom import random
#----------------------------------------------------------------------
wxEVT_UPDATE_BARGRAPH = 25015
def EVT_UPDATE_BARGRAPH(win, func):
win.Connect(-1, -1, wxEVT_UPDATE_BARGRAPH, func)
class UpdateBarEvent(wxPyEvent):
def __init__(self, barNum, value):
wxPyEvent.__init__(self)
self.SetEventType(wxEVT_UPDATE_BARGRAPH)
self.barNum = barNum
self.value = value
#----------------------------------------------------------------------
class CalcBarThread:
def __init__(self, win, barNum, val):
self.win = win
self.barNum = barNum
self.val = val
def Start(self):
self.keepGoing = self.running = true
thread.start_new_thread(self.Run, ())
def Stop(self):
self.keepGoing = false
def IsRunning(self):
return self.running
def Run(self):
while self.keepGoing:
evt = UpdateBarEvent(self.barNum, int(self.val))
wxPostEvent(self.win, evt)
del evt
sleeptime = (random() * 2) + 0.5
#print self.barNum, 'sleeping for', sleeptime
time.sleep(sleeptime)
sleeptime = sleeptime * 5
if int(random() * 2):
self.val = self.val + sleeptime
else:
self.val = self.val - sleeptime
if self.val < 0: self.val = 0
if self.val > 300: self.val = 300
self.running = false
#----------------------------------------------------------------------
class GraphWindow(wxWindow):
def __init__(self, parent, labels):
wxWindow.__init__(self, parent, -1)
self.values = []
for label in labels:
self.values.append((label, 0))
self.font = wxFont(12, wxSWISS, wxNORMAL, wxBOLD)
self.SetFont(self.font)
self.colors = [ wxRED, wxGREEN, wxBLUE, wxCYAN] #, wxNamedColour("Yellow") ]
def SetValue(self, index, value):
assert index < len(self.values)
cur = self.values[index]
self.values[index:index+1] = [(cur[0], value)]
def SetFont(self, font):
wxWindow.SetFont(self, font)
wmax = hmax = 0
for label, val in self.values:
w,h = self.GetTextExtent(label)
if w > wmax: wmax = w
if h > hmax: hmax = h
self.linePos = wmax + 10
self.barHeight = hmax
def OnPaint(self, evt):
size = self.GetSize()
dc = wxPaintDC(self)
dc.BeginDrawing()
dc.SetFont(self.font)
dc.SetTextForeground(wxBLUE)
dc.SetPen(wxPen(wxBLACK, 3, wxSOLID))
dc.DrawLine(self.linePos, 0, self.linePos, size.height-10)
bh = ypos = self.barHeight
for x in range(len(self.values)):
label, val = self.values[x]
dc.DrawText(label, 5, ypos)
if val:
color = self.colors[ x % len(self.colors) ]
dc.SetPen(wxPen(color))
dc.SetBrush(wxBrush(color))
dc.DrawRectangle(self.linePos+3, ypos, val, bh)
ypos = ypos + 2*bh
if ypos > size.height-10:
break
dc.EndDrawing()
#----------------------------------------------------------------------
class TestFrame(wxFrame):
def __init__(self, parent, log):
wxFrame.__init__(self, parent, -1, "Thread Test", size=(450,300))
self.log = log
#self.CenterOnParent()
panel = wxPanel(self, -1)
panel.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD))
wxStaticText(panel, -1,
"This demo shows multiple threads interacting with this\n"
"window by sending events to it.", wxPoint(5,5))
panel.Fit()
self.graph = GraphWindow(self, ['Zero', 'One', 'Two', 'Three'])
sizer = wxBoxSizer(wxVERTICAL)
sizer.Add(panel, 0, wxEXPAND)
sizer.Add(self.graph, 1, wxEXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(true)
#self.graph.SetValue(0, 25)
#self.graph.SetValue(1, 50)
#self.graph.SetValue(2, 75)
#self.graph.SetValue(3, 100)
EVT_UPDATE_BARGRAPH(self, self.OnUpdate)
self.threads = []
self.threads.append(CalcBarThread(self, 0, 25))
self.threads.append(CalcBarThread(self, 1, 50))
self.threads.append(CalcBarThread(self, 2, 75))
self.threads.append(CalcBarThread(self, 3, 100))
for t in self.threads:
t.Start()
def OnUpdate(self, evt):
self.graph.SetValue(evt.barNum, evt.value)
self.graph.Refresh()
def OnCloseWindow(self, evt):
busy = wxBusyInfo("One moment please, waiting for threads to die...")
for t in self.threads:
t.Stop()
running = 1
while running:
running = 0
for t in self.threads:
running = running + t.IsRunning()
time.sleep(0.1)
self.Destroy()
#----------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestFrame(frame, log)
frame.otherWin = win
win.Show(true)
return None
#----------------------------------------------------------------------
overview = """\
The main issue with multi-threaded GUI programming is the thread safty
of the GUI itself. On most platforms the GUI is not thread safe and
so any cross platform GUI Toolkit and applications written with it
need to take that into account.
The solution is to only allow interaction with the GUI from a single
thread, but this often severly limits what can be done in an
application and makes it difficult to use additional threads at all.
Since wxPython already makes extensive use of event handlers, it is a
logical extension to allow events to be sent to GUI objects from
alternate threads. A function called wxPostEvent allows you to do
this. It accepts an event and an event handler (window) and instead
of sending the event immediately in the current context like
ProcessEvent does, it processes it later from the context of the GUI
thread.
"""

File diff suppressed because it is too large Load Diff

View File

@ -450,20 +450,20 @@ PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) {
// themselves and some special case handling in wxPyCallback::EventThunker.
wxPySelfRef::wxPySelfRef() {
wxPyEvtSelfRef::wxPyEvtSelfRef() {
//m_self = Py_None; // **** We don't do normal ref counting to prevent
//Py_INCREF(m_self); // circular loops...
m_cloned = false;
}
wxPySelfRef::~wxPySelfRef() {
wxPyEvtSelfRef::~wxPyEvtSelfRef() {
bool doSave = wxPyRestoreThread();
if (m_cloned)
Py_DECREF(m_self);
wxPySaveThread(doSave);
}
void wxPySelfRef::SetSelf(PyObject* self, bool clone) {
void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
bool doSave = wxPyRestoreThread();
if (m_cloned)
Py_DECREF(m_self);
@ -475,7 +475,7 @@ void wxPySelfRef::SetSelf(PyObject* self, bool clone) {
wxPySaveThread(doSave);
}
PyObject* wxPySelfRef::GetSelf() const {
PyObject* wxPyEvtSelfRef::GetSelf() const {
Py_INCREF(m_self);
return m_self;
}

View File

@ -189,10 +189,10 @@ private:
// themselves and some special case handling in wxPyCallback::EventThunker.
class wxPySelfRef {
class wxPyEvtSelfRef {
public:
wxPySelfRef();
~wxPySelfRef();
wxPyEvtSelfRef();
~wxPyEvtSelfRef();
void SetSelf(PyObject* self, bool clone=FALSE);
PyObject* GetSelf() const;
@ -203,7 +203,7 @@ protected:
};
class wxPyEvent : public wxEvent, public wxPySelfRef {
class wxPyEvent : public wxEvent, public wxPyEvtSelfRef {
DECLARE_DYNAMIC_CLASS(wxPyEvent)
public:
wxPyEvent(int id=0);
@ -213,7 +213,7 @@ public:
};
class wxPyCommandEvent : public wxCommandEvent, public wxPySelfRef {
class wxPyCommandEvent : public wxCommandEvent, public wxPyEvtSelfRef {
DECLARE_DYNAMIC_CLASS(wxPyCommandEvent)
public:
wxPyCommandEvent(wxEventType commandType = wxEVT_NULL, int id=0);