TCanvas update hangs the application

[code]void Tab1::readData(){
h1profile->Reset();
std::cout<<“in datareading locking…”<<mutex<<std::endl;
QMutexLocker locker(mutex);
for (std::vector::iterator event=events->begin(); event!=events->end(); ++event){
for (int window=0; window<16; ++window){
for(std::vector::iterator n=(*event).moduleBRIC.wireBRIC[window].begin(); n!=(*event).moduleBRIC.wireBRIC[window].end(); ++n) h1profile->Fill(*n);
};
};

 RootCanvasTAB1->cd();

std::cout<<“cd, ready to draw!”<<std::endl;
h1profile->Draw();
std::cout<<“updating”<<std::endl;
RootCanvasTAB1->Update();
std::cout<<“in datareading finished”<<std::endl;
};[/code]

Two times it works perfectly, but third time I get in console only:
in datareading locking…0x94d8570
cd, ready to draw!
updating
Then application is not responding… What shall I do to fix?
QT4.5 Linux

Why do you insist with this non standard version?
Use the stable well debugged/supported/standard ROOT without QT.

Rene

[quote=“avaava”]… Then application is not responding… What shall I do to fix?
QT4.5 Linux…[/quote]It is hard to say.There might be many reasons for your troubles.
To assist one should be able to reproduce your issue. However, I suspect the problem is not Qt-related.

The presence of QMutexLocker locker(mutex); suggests that your application is multi-threaded and ROOT is not thread–safe C++ library. One needs to see the bigger picture. To understand your issue better I need to know whether you can reproduce this problem with Qt 4.4.x ? Can you reproduce this problem with last version of QtRoot from BNL CVS HEAD ? (see root.bnl.gov/QtRoot/How2Install4 … complement. BNL CVS HEAD contains some Qt 4.5 related corrections to be propagated to CERN yet)

However, I still think the problem is not Qt related. It is caused by misuse of TObject::Draw method.
It was explained many times (please search ROOT Website) that the name of the method is confusing. The method does not draw anything at all and it MUST not be used as such. Please, see ROOT tutorials “hsimple. C” to understand that the method Draw must be invoked at once per object / TCanvas combination to ATTACH the object to the TCanvas. Calling it for several times especially within the multithreaded environment you are asking for the hard to trace side effects.

I’ve modified your method to make is safer. This is a MUST correction. However, it doesnot eliminate the major obstacle, namely, you still have to take in account that the ROOT is not thread-safe,
and to be robust the miltithreaded application should use GUI from one dedicated GUI thread only.

void Tab1::readData(){ static int attached = 0; if (!attached) { attached = 1; // Do not "cd() / Draw() // Use safer version: RootCanvasTAB1->GetListOfPrimitives()->Add(h1profile); RootCanvasTAB1->Modified(); } h1profile->Reset(); std::cout<<"in datareading locking..."<<mutex<<std::endl; QMutexLocker locker(mutex); for (std::vector<EVENT>::iterator event=events->begin(); event!=events->end(); ++event){ for (int window=0; window<16; ++window){ for(std::vector<int>::iterator n=(*event).moduleBRIC.wireBRIC[window].begin(); n!=(*event).moduleBRIC.wireBRIC[window].end(); ++n) h1profile->Fill(*n); } } }If you need to update your TCanvas use doc.trolltech.com/4.5/threads.ht … ss-threads ). May be you need something like this (It is hard to advise without the “bigger” picture)void Tab1::readData(){ static int attached = 0; if (!attached) { attached = 1; // Do not "cd() / Draw() // Use safer version: RootCanvasTAB1->GetListOfPrimitives()->Add(h1profile); RootCanvasTAB1->Modified(); connect(this,SIGNAL(DataReady()), TQtWidget::Canvas(RootCanvasTAB1),SLOT(Refresh())); } h1profile->Reset(); { std::cout<<"in datareading locking..."<<mutex<<std::endl; QMutexLocker locker(mutex); for (std::vector<EVENT>::iterator event=events->begin(); event!=events->end(); ++event){ for (int window=0; window<16; ++window){ for(std::vector<int>::iterator n=(*event).moduleBRIC.wireBRIC[window].begin(); n!=(*event).moduleBRIC.wireBRIC[window].end(); ++n) h1profile->Fill(*n); } } } emit DataReady(); }

Thanks! It works perfectly, but I have several tabs on form and readData() is the slot, which I use to know that new data available. When there is only one tab all works, but if 2 I have the old problem…

[quote=“avaava”]… It works perfectly, … there is only one tab all works, but if 2 I have the old problem…[/quote]If you applied my piece of the code “as is” then this is the expected :exclamation: outcome. I did not see your code. Therefore I did show you the idea . I did not provide you a complete solution…

I am keeping guessing :unamused: that there is some method in your “Tab1” class to instantiate your “h1profile” member. That looks like h1profile = new TProfile ( . . . )
If my guess is correct then I would advise you to change that place to be like

if (!h1profile) { h1profile = new TProfile ( . . . ); RootCanvasTAB1->GetListOfPrimitives()->Add(h1profile); connect(this,SIGNAL(DataReady()), TQtWidget::Canvas(RootCanvasTAB1),SLOT(Refresh())); } and replace the clause static int attached = 0; if (!attached) { attached = 1; // Do not "cd() / Draw() // Use safer version: RootCanvasTAB1->GetListOfPrimitives()->Add(h1profile); RootCanvasTAB1->Modified(); } with

RootCanvasTAB1->Modified(); I.e. your readData method should look like this:[code]void Tab1::readData()
{
h1profile->Reset();
{
std::cout<<“in datareading locking…”<<mutex<<std::endl;
QMutexLocker locker(mutex);
for (std::vector::iterator event=events->begin(); event!=events->end(); ++event){
for (int window=0; window<16; ++window){
for(std::vector::iterator n=(*event).moduleBRIC.wireBRIC[window].begin();
n!=(*event).moduleBRIC.wireBRIC[window].end(); ++n) h1profile->Fill(*n);
}
}
} // relase locker first. then emit the Qt SIGNAL
RootCanvasTAB1->Modified();
if (isVisible()) {
// pay your attention that this is a waste of resource
// to call TQtWidget::Refresh slot if the widget is not visible.
// You should find the better place to check the tab visibility though.
// It is just here to remind you

     emit DataReady(); 

}
}[/code]

Thank you! I changed (*TH1F)->Draw() method to (*TPad)->GetListOfPrimitives()->Add() and everything works! I don’t know how and why, but it does. Thank you!