Typically events that deal with a window as a window (size, motion,\r
paint, mouse, keyboard, etc.) are sent only to the window. Events\r
that have a higher level of meaning or are generated by the window\r
-itself, (button click, menu select, tree expand, etc.) are command\r
+itself (button click, menu select, tree expand, etc.) are command\r
events and are sent up to the parent to see if it is interested in the event.\r
-\r
-As mentioned above, only command events are recursively applied to the parents\r
-event handler in the library itself. As this quite often causes confusion for\r
-users, here is a list of system events that will @em not get sent to the\r
-parent's event handler:\r
-\r
-@li wxEvent: The event base class\r
-@li wxActivateEvent: A window or application activation event\r
-@li wxCloseEvent: A close window or end session event\r
-@li wxEraseEvent: An erase background event\r
-@li wxFocusEvent: A window focus event\r
-@li wxKeyEvent: A keypress event\r
-@li wxIdleEvent: An idle event\r
-@li wxInitDialogEvent: A dialog initialisation event\r
-@li wxJoystickEvent: A joystick event\r
-@li wxMenuEvent: A menu event\r
-@li wxMouseEvent: A mouse event\r
-@li wxMoveEvent: A move event\r
-@li wxPaintEvent: A paint event\r
-@li wxQueryLayoutInfoEvent: Used to query layout information\r
-@li wxSetCursorEvent: Used for special cursor processing based on current mouse position\r
-@li wxSizeEvent: A size event\r
-@li wxScrollWinEvent: A scroll event sent by a scrolled window (not a scroll bar)\r
-@li wxSysColourChangedEvent: A system colour change event\r
+More precisely, as said above, all event classes @b not deriving from wxCommandEvent\r
+(see the wxEvent inheritance map) do @b not propagate upward.\r
\r
In some cases, it might be desired by the programmer to get a certain number\r
of system events in a parent window, for example all key events sent to, but not\r
\r
\r
\r
-@subsection overview_events_macros Event Handling Summary\r
+@subsection overview_events_list List of wxWidgets events\r
\r
For the full list of event classes, please see the\r
@ref group_class_events "event classes group page".\r
/**
-@page overview_thread Multithreading
+@page overview_thread Multithreading Overview
Classes: wxThread, wxThreadHelper, wxMutex, wxCriticalSection, wxCondition, wxSemaphore
+
+@section overview_thread_intro When to use multiple threads
+
wxWidgets provides a complete set of classes encapsulating objects necessary in
multithreaded (MT) programs: the wxThread class itself and different
synchronization objects: mutexes (see wxMutex) and critical sections (see
- use wxIdleEvent (e.g. to perform a long calculation while updating a progress dialog)
- do everything at once but call wxWindow::Update() or wxApp::YieldFor(wxEVT_CATEGORY_UI)
periodically to update the screen.
+If instead you choose to use threads in your application, please read also
+the following sections of this overview.
+
+@section overview_thread_notes Important notes for multithreaded applications
-If instead you choose to use threads in your application, it is strongly recommended
+When writing a multi-threaded application, it is strongly recommended
that <b>no secondary threads call GUI functions</b>.
The design which uses one GUI thread and several worker threads which communicate
with the main one using @b events is much more robust and will undoubtedly save you
countless problems (example: under Win32 a thread can only access GDI objects such
-as pens, brushes, c created by itself and not by the other threads).
+as pens, brushes, device contexts created by itself and not by the other threads).
For communication between secondary threads and the main thread, you may use
wxEvtHandler::QueueEvent or its short version ::wxQueueEvent. These functions
yourself. In particular, please note that it is not enough to derive
your class from wxThread and wxEvtHandler to send messages to it: in fact, this
does not work at all.
+You're instead encouraged to use wxThreadHelper as it greatly simplifies the
+communication and the sharing of resources.
+
+You should also look at the wxThread docs for important notes about secondary
+threads and their deletion.
+
+Last, remember that if wxEventLoopBase::YieldFor() is used directly or indirectly
+(e.g. through wxProgressDialog) in your code, then you may have both re-entrancy
+problems and also problems caused by the processing of events out of order.
+To resolve the last problem wxThreadEvent can be used: thanks to its implementation
+of the wxThreadEvent::GetEventCategory function wxThreadEvent classes in fact
+do not get processed by wxEventLoopBase::YieldFor() unless you specify the
+@c wxEVT_CATEGORY_THREAD flag.
See also the @sample{thread} for a sample showing some simple interactions
between the main and secondary threads.
/**
Returns a generic category for this event.
+ wxEvent implementation returns @c wxEVT_CATEGORY_UI by default.
This function is used to selectively process events in wxEventLoopBase::YieldFor.
*/
This event class contains information about command events, which originate
from a variety of simple controls.
+ Note that wxCommandEvents and wxCommandEvent-derived event classes by default
+ and unlike other wxEvent-derived classes propagate upward from the source
+ window (the window which emits the event) up to the first parent which processes
+ the event. Be sure to read @ref overview_events_propagation.
+
More complex controls, such as wxTreeCtrl, have separate command event classes.
@beginEventTable{wxCommandEvent}
This class adds some simple functionalities to wxCommandEvent coinceived
for inter-threads communications.
+ This event is not natively emitted by any control/class: this is just
+ an helper class for the user.
+ Its most important feature is the GetEventCategory() implementation which
+ allows thread events to @b NOT be processed by wxEventLoopBase::YieldFor calls
+ (unless the @c wxEVT_CATEGORY_THREAD is specified - which is never in wx code).
+
@library{wxcore}
@category{events}
@class wxProgressDialog
This class represents a dialog that shows a short message and a
- progress bar. Optionally, it can display ABORT and SKIP buttons,
+ progress bar. Optionally, it can display ABORT and SKIP buttons, and
the elapsed, remaining and estimated time for the end of the progress.
+ Note that you must be aware that wxProgressDialog internally calls
+ wxEventLoopBase::YieldFor with @c wxEVT_CATEGORY_UI and @c wxEVT_CATEGORY_USER_INPUT
+ and this may cause unwanted re-entrancies or the out-of-order processing
+ of pending events (to help preventing the last problem if you're using
+ wxProgressDialog in a multi-threaded application you should be sure to use
+ wxThreadEvent for your inter-threads communications).
+
@beginStyleTable
@style{wxPD_APP_MODAL}
Make the progress dialog modal. If this flag is not given, it is
Example:
@code
- extern const wxEventType wxEVT_COMMAND_MYTHREAD_UPDATE;
+ wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
class MyFrame : public wxFrame, public wxThreadHelper
{
...
void DoStartALongTask();
- void OnThreadUpdate(wxCommandEvent& evt);
+ void OnThreadUpdate(wxThreadEvent& evt);
void OnClose(wxCloseEvent& evt);
...
DECLARE_EVENT_TABLE()
};
- DEFINE_EVENT_TYPE(wxEVT_COMMAND_MYTHREAD_UPDATE)
+ wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
EVT_CLOSE(MyFrame::OnClose)
// VERY IMPORTANT: do not call any GUI function inside this
// function; rather use wxQueueEvent():
- wxQueueEvent(this, new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_UPDATE));
+ wxQueueEvent(this, new wxThreadEvent(wxEVT_COMMAND_MYTHREAD_UPDATE));
// we used pointer 'this' assuming it's safe; see OnClose()
}
Destroy();
}
- void MyFrame::OnThreadUpdate(wxCommandEvent&evt)
+ void MyFrame::OnThreadUpdate(wxThreadEvent& evt)
{
// ...do something... e.g. m_pGauge->Pulse();
@library{wxbase}
@category{threading}
- @see wxThread
+ @see wxThread, wxThreadEvent
*/
class wxThreadHelper
{
@code
// declare a new type of event, to be used by our MyThread class:
- extern const wxEventType wxEVT_COMMAND_MYTHREAD_COMPLETED;
- extern const wxEventType wxEVT_COMMAND_MYTHREAD_UPDATE;
+ wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent);
+ wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
class MyFrame;
class MyThread : public wxThread
// a resume routine would be nearly identic to DoPauseThread()
void DoResumeThread() { ... }
- void OnThreadCompletion(wxCommandEvent&);
+ void OnThreadUpdate(wxThreadEvent&);
+ void OnThreadCompletion(wxThreadEvent&);
void OnClose(wxCloseEvent&);
protected:
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_COMPLETED, MyFrame::OnThreadCompletion)
END_EVENT_TABLE()
- DEFINE_EVENT_TYPE(wxEVT_COMMAND_MYTHREAD_COMPLETED)
- DEFINE_EVENT_TYPE(wxEVT_COMMAND_MYTHREAD_UPDATE)
+ wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent)
+ wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
void MyFrame::DoStartThread()
{
{
// ... do a bit of work...
- wxQueueEvent(m_pHandler, new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_UPDATE));
+ wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_MYTHREAD_UPDATE));
}
// signal the event handler that this thread is going to be destroyed
// NOTE: here we assume that using the m_pHandler pointer is safe,
// (in this case this is assured by the MyFrame destructor)
- wxQueueEvent(m_pHandler, new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_COMPLETED));
+ wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_MYTHREAD_COMPLETED));
return (wxThread::ExitCode)0; // success
}
m_pHandler->m_pThread = NULL;
}
- void MyFrame::OnThreadCompletion(wxCommandEvent&)
+ void MyFrame::OnThreadCompletion(wxThreadEvent&)
{
wxMessageOutputDebug().Printf("MYFRAME: MyThread exited!\n");
}
- void MyFrame::OnThreadUpdate(wxCommandEvent&)
+ void MyFrame::OnThreadUpdate(wxThreadEvent&)
{
wxMessageOutputDebug().Printf("MYFRAME: MyThread update...\n");
}