Re: Event driven code

From: Fons Rademakers (Fons.Rademakers@cern.ch)
Date: Tue Jun 02 1998 - 16:08:51 MEST


Hi Rutger,

   it seems you are complicating things a lot. Let see how you could
implement what you want. First, you want your interface to react to
user generated GUI events and you also want to check periodically to
see if some displays need to be updated. The best way to do that is
to use the standard TApplication::Run() method, which will take care
of all GUI events and to add some timers to periodically check the
different displays. The timers could be simple synchronous timers
(i.e. they will be handled when there are no GUI events as opposed
to asynchronous timers that will generate a hard interrupt). The timer
could look like this:

class OUpdateTimer : public TTimer {
private:
   TList  *fDisplays;
public:
   OUpdateTimer(Long_t ms) : TTimer(ms, kTRUE) { fDisplays = 0; }
   void AddDisplay(TObject *obj) {
     if (!fDisplays) fDisplays = new TList;
     fDisplays->Add(obj);
   }   
   Bool_t Notify();
};

Bool_t OUpdateTimer::Notify()
{
   if (fDisplays) {
      TIter next(fDisplays);
      TObject *obj;
      while ((obj = next())) {
         if (obj->InheritsFrom(TCanvas::Class())) {
            ((TCanvas *)obj)->Update();
         } else if (obj->InheritsFrom(TGFrame::Class())) {
            // forward message to frame's central message handler
            // mess id and subid can be anything in the range
            // kC_MSGMAX < id <= 255 and 1 <= subid <= 255
            ((TGFrame *)obj)->SendMessage(obj, MK_MSG(100, 1), 0, 0);
            // or, much more efficient, call directly member function
            // of your known TGFrame derived class:
            // ((OMyFrame *)obj)->Update();
         }
      }
   }
   Reset();        // reset timer
   return kFALSE;
}

So this timer keeps track of all TCanvases and TGFrames that is need to be
checked periodically. Use it as follows:

TTimer *gUpdateTimer;

int main()
{
   ...  
   gUpdateTimer = new OUpdateTimer(500);   // check every 500 milliseconds
   gSystem->AddTimer(gUpdateTimer);
   ...
   theApp->Run();

   return 0;
}

And where ever you create a canvas or frame that needs monitoring:

   ...
   gUpdateTimer->AddDisplay(canvas);
   ...


Hope this helps.

Cheers, Fons.

Rutger van der Eijk wrote:
> 
> Hi rooters,
> 
> After some struggeling on how to set the framework for a online monitoring
> system (LHCb Outer Tracker testbeam), I have come to the conclusion that I
> should make it event-driven. First I had a sort of run loop updating all
> the displays and histograms and then a seperate call to look for GUI
> events. Now I want a run loop also to be a sort of event, with each
> loop called by a specialed timer class.
> 
> I have the following idea, but I'm not sure if this is the appropriate way
> to use the GUI classes, or that it's already implemented in another way in
> ROOT. So please give comments/advise.
> 
> The idea is to make a Timer class (OTGMsgTimer) which generates a message
> and send this message to some controlling object. The framework provided
> by ROOT suggests the following; The TTimer should be a sort of TGWidget
> (to know where to send the message to, and to have an id of the timer).
> Because I want to use the TGFrame::SendMessage(...) functionmember it
> should also be a TGFrame. And ofcourse it will be a TTimer.
> 
> The OTGMsgTimer::Notify() functionmember would look something like this:
> 
> ----------
> Bool_t OTMsgTimer::Notify() {
>   // Notify when OTMsgTimer times out. The OTMsgTimer checks for GUI
> events
>   //
> 
>   SendMessage(fMsgWindow, MK_MSG(kC_???, k??_???), fWidgetId,
>               (Long_t) fUserData);
>   Reset();
> 
>   return TTimer::Notify();
> }
> ----------
> 
> So in the above mentioned monitoring code I would have the OTMsgTimer send
> a message to a controlling object (OTRunController) which performs a run
> loop when it recieves the message.
> 
> The problems I encounter:
> - I nead new message type (EWidgetMessageTypes in TGWdiget)
>         - I could implement this by using kC_MSGMAX.
> - OTGMsgTimer will be a TGFrame (to use SendMessage(...) which it surrely
> is not. (The X,Y position of a timer?)
> - or more general: I will use a graphics interface to implement event
> driven code. Is this the way I should use it, or is a reason not to?
> 
> Bye, Rutger van der Eijk
> 
> p.s. I am still waiting on a reply on my roottalk message of last
> thursday.

-- 
Org:    CERN, European Laboratory for Particle Physics.
Mail:   1211 Geneve 23, Switzerland          Phone: +41 22 7679248
E-Mail: Fons.Rademakers@cern.ch              Fax:   +41 22 7677910



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:33 MET