Right Way to Refresh GUI application & Crash

Root/Support:

I wonder if you can help me? I’ve adopted code from someone that worked on Root 5.0028b. Here is something he did which I do not like.

  1. He took the root 5.0028b prebuilt .libs/dlls and created an application.
  2. Unfortunately, he took TGMsgBox.cxx from the root source and modified the following method (1 of many) and then made TGMsgBox.cxx part of the VS2008 solution.
    //______________________________________________________________________________
    Bool_t TGMsgBox::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
    {

    Some_CompanyRelatedCalls();

    DeleteWindow();

    return kTRUE;
    }

The problem I have with this approach. He never bothered to rebuild the Root source code with these changes but instead made the root code part of the application and still linked with libcore.lib. Makes my head spin.

The 2nd problem is that in the many function calls in the Some_CompanyRelatedCalls(); logic he put ProcessEvent(envent) calls in certain areas with the intention of refreshing the GUI.

The problem is that he put lots of similar calls throughout the different functions/logic like below:
gSystem->ProcessEvents(); //causes screen to be updated
gSystem->Sleep(50); //wait 50 milliseconds between polls
His goal was to refresh the overall GUI screen!!!

I believe this may be causing a crash problem related to race conditions. Perhaps some of the events raised may not be associated with a valid object because ProcessMessage() events may still be unprocessed by the time ProcessMessage calls DeleteWindow().

Am I right?

What would be the best way - considering the current coding issue - to refresh the GUI without doing a gSystem->ProcessEvents() followed by a gSystem->Sleep(50)?

What problems do you see with what the prior code did with modifying TGMsgBox.cxx, making it part of the VS 2008 solution, but still linking and using the ROOT prebuilt libcore.lib/and DLLs that don’t have the TGMsgBox.cxx changes?

Thank you,
Angel

Hi Angel,

gSystem->ProcessEvents() is needed to process GUI events, like for example in for (or while) loops. Otherwise, the events are processed by the application itself (no need to add gSystem->ProcessEvents())
Then, I’m not sure I understand what you’re trying to do. Use a modified version of ROOT, or use a non-modified one. Don’t mix, it cannot work.

Cheers, Bertrand.

Hi Bertrand,

My problem is that root’s ProcessMessage() is call a bunch of our routines which ProcessEvents() is one off.

The gSystem->ProcesssEvents() are not within a loop.

Is gSystem->ProcessEvents() needed or not needed? Was not sure what you meant.

Thank you,
Angel

Hi Angel,

Well, it depends on what you do. It is usually not needed, the main event loop (in TApplication::Run()) should be sufficient.

Cheers, Bertrand.

Here is a better clarificstion.

Tgmsgbox::ProcessMessage()
{

// Other coder modified this code and added function calls that access specialized Hardware.
// Some of these functions call the following multiple times (No for()/while() loops)
// gSystem->ProcessEvent()
// gSystem->Sleep(100)
//
// After return from our multiple functions that call gSystem0->ProcessEvent()/Sleep(100)
we return to ProcessMessage().

Because of this, we could be in ProcessMessage() a long time. I don’t like this. The purpose of the message handlers is to be in/out as quickly as possible.

Again, can you explain further what you meant in your initial response?

Bertrand,

Can you elaborate/specify when and when it would not be needed?

Based on comments in the code, the coder said it was to update the GUI in the background. However, there were no GUI related api calls before or after the call to gSystem->ProcessEvent(). Just a bunch of HW related calls which delayed the about of time we spent in the TGMsgBox::ProcessMessage() event handler.

What is the correct way to force a refresh of the GUI?
Everywhere the code put gSystem->ProcessEvent(); gSystem->Sleep(100), I put:

MapSubwindows();
Layout();
DoRedraw();

Is the above a good way to force a GUI refresh?

As I said, it is needed in loops, to force event handling. Or when you want to force event processing in a particular moment (it could force GUI update, but this alone could not be sufficient).

[quote=“aortiz@stgen.com”]What is the correct way to force a refresh of the GUI?
Everywhere the code put gSystem->ProcessEvent(); gSystem->Sleep(100), I put:

MapSubwindows();
Layout();
DoRedraw();

Is the above a good way to force a GUI refresh?[/quote]
Yes, if you changed the layout of your GUI. But if you change a widget’s content (or attribute), you should use:

   gClient->NeedRedraw(yourWidget);

And “gSystem->Sleep(100)” is most probably not needed…