Clickable ROOT histograms in QT

I’m not sure if this is the proper place to ask this, but is there an easy way to make a click-able root canvas in QT with the ROOT QT classes?

Specifically I’d like to present the user with a TH2 COLZ type histogram and have each bin in the plot be click-able.

Thanks.

[quote=“jtchil0”]I’m not sure if this is the proper place to ask this, but is there an easy way to make a click-able root canvas in QT with the ROOT QT classes?

Specifically I’d like to present the user with a TH2 COLZ type histogram and have each bin in the plot be click-able.
.[/quote]Can you elaborate a little bit more? Why did you mark your question as Qt-related? TCanvas is TCanvas. Any “drawable” TObject can be rendered by TCanvas and it can be “clickable”. This ROOT feature is independent of the low level graphical layer (for example Qt)
See root.cern.ch/phpBB2/viewtopic.php?t=8448 also.

Well, I’m writing a QT plugin for the OHP framework in the ATLAS Point 1 monitoring setup.

I would like to present the user with a 2D histogram where he/she can click on a pixel and this causes other actions, such as opening another window with another, more detailed histogram.

Does that make my intentions more clear?

So I’m writing in QT and I would create a canvas in the window to display a 2D histogram and then I would need to know what bin was clicked by the user so I can cause other things to happen.

Thanks for the help.

see example in $ROOTSYS/tutorials/hist/DynamicSlice.C

Rene

Thank you Rene.

This looks very promising.

[quote=“jtchil0”]I would like to present the user with a 2D histogram where he/she can click on a pixel and this causes other actions, such as opening another window with another, more detailed histogram.

Does that make my intentions more clear?[/quote]Yes, it does. Thank you.

Normally, when people speak about Qt they want to use the Qt signal /slot communication ( root.cern.ch/root/html/TQtWidget … escription

I maintain the collection of the “HelloWorld”-level working examples to show how the Qt signals /slots and other Qt features can be used with ROOT applications. The fresh version can be installed from the CVS as described: root.bnl.gov/QtRoot/How2Install4 … complement . Each example is rather short and I strongly recommend to install and try each (it should take 10-15 mins at most)

Meantime, I’ve converted the Rene’s “$ROOTSYS/tutorials/hist/DynamicSlice.C” example to the full-fledged HelloClick stand alone Qt application. I’ve attached the working Qt project below and included it into my collection of the simple examples. (so it can be installed with all other examples )
HelloClick.tar.gz (3.53 KB)


[quote=“jtchil0”]I’m not sure if this is the proper place to ask this, but is there an easy way to make a click-able root canvas in QT with the ROOT QT classes?[/quote]The good place for such questions is lists.bnl.gov/mailman/listinfo/qt-root-l

For a start, I was trying to create a simple widget that just displays a TH2 histogram from a file. I’ve included the class.

I am using QT 3.3.8 and ROOT 5.22.00a (all on AFS).

I get the following compilation errors:
In file included from …/ohpPlugins/rateHistoMapWidget.h:15,
from …/src/rateHistoMapWidget.cpp:1:
/afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00a/slc4_ia32_gcc34/root/include/TQtWidget.h: In member function int TQtWidgetBuffer::Height() const': /afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00a/slc4_ia32_gcc34/root/include/TQtWidget.h:89: error: 'class QPaintDevice' has no member named 'height' /afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00a/slc4_ia32_gcc34/root/include/TQtWidget.h: In member functionint TQtWidgetBuffer::Width() const’:
/afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00a/slc4_ia32_gcc34/root/include/TQtWidget.h:90: error: ‘class QPaintDevice’ has no member named ‘width’
gmake[3]: *** […/i686-slc4-gcc34-opt/rateHistoMapWidget.o] Error 1

This appears to be a version problem since QPaintDevice in QT4.3 does have a width and height. Is there anything I can do? I am required to use QT3.3 since that is what they are using at Point 1 for some of the ATLAS monitoring software. (They plan to upgrade, but haven’t yet. I’m starting to wonder if it will happen at all).

Any suggestions? Perhaps an older version of ROOT?

Cheers,
Taylor
rateHistoMapWidget.cpp (1.01 KB)
rateHistoMapWidget.h (1.45 KB)

[quote=“jtchil0”] . . . I am using QT 3.3.8 and ROOT 5.22.00a (all on AFS).
. . . [/quote]Excuse me. The support for Qt 3.x was disconnected ( by "CERN decision " ) since ROOT 5.20 and the Qt3-related codes was removed from the ROOT (and QtRoot) distributions. Can you use Qt 4.x ?

[quote=“jtchil0”]I am using QT 3.3.8 and ROOT 5.22.00a (all on AFS).
[/quote]Please, see the topic: “Which version of Qt the ROOT releases are built against of” root.cern.ch/phpBB2/viewtopic.ph … highlight=
The page twiki.cern.ch/twiki/bin/view/SP … #Externals
says, [quote]ROOT 5.22a from LCG 56 is built against of Qt 4.4.2. [/quote]

[code]Proposed nex LCG Configuration LCG 56
. . .
Foreseen release date

~ Beginning of February
. . .
Externals
Package old version new version Motivation
. . .
qt 3.3.8 4.4.2 move to qt4 series
. . .

LCG/AA Projects
Project Version Short description
. . .
ROOT 5.22.00a feature release
. . . [/code]
Another page:
lcgsoft.cern.ch/index.py?page=cf … ew&cfg=55a
says,

[quote=“jtchil0”]
. . .
This appears to be a version problem since QPaintDevice in QT4.3 does have a width and height. Is there anything I can do? I am required to use QT3.3 since that is what they are using at Point 1 for some of the ATLAS monitoring software. (They plan to upgrade, but haven’t yet. I’m starting to wonder if it will happen at all).

Any suggestions? Perhaps an older version of ROOT?
. . .
[/quote]Well, you can use the disconnected version of QtRoot to install it against of the modern version of ROOT. You can try to use the older version of ROOT too.
Either approach may work for a while
However, with either approach you should anticipate the “support” problem. It would be not simple to help you as soon as you find the bug (or “feature” / “side effect”, you name it ) on either side (ROOT / QtROOT). In addition the Qt3 support is to be disconnected by Nokia (former TrollTech ) company soon.

The best thing to do is to migrate from Qt3 to Qt4 (or at least to semi-automatically to QT3_SUPPORT) .

Sooner / later, you will be forced to move. You are postponing this step. Mean time the volume of the code you will have to change IS GROWING, making the future migration more and more painful and complex.

I have some experience with such process. I did write Qt3-based QtRoot and Qt3-based STAR Online applications too. They were converted to Qt4. but . . . this theme is out of scope of this thread.

[quote=“jtchil0”]For a start, I was trying to create a simple widget that just displays a TH2 histogram from a file.
. . . [/quote]I’ve downloaded your attachment. It has many hidden problems
For example, you create the new object with “TFile *file = new TFile(…)” but you never delete it.
There is no reason to use

m_canvasWidget->GetCanvas()->cd();one should use

m_canvasWidget->cd();instead if any, etc

Excuse me, I have to repeat, I strongly recommend to install and try each “Hello” example, [quote=“fine”]Normally, when people speak about Qt they want to use the Qt signal /slot communication ( root.cern.ch/root/html/TQtWidget … escription

I maintain the collection of the “HelloWorld”-level working examples to show how the Qt signals /slots and other Qt features can be used with ROOT applications. The fresh version can be installed from the CVS as described: root.bnl.gov/QtRoot/How2Install4 … complement . Each example is rather short and I strongly recommend to install and try each (it should take 10-15 mins at most) [/quote]
Please, study the HelloClick example and look up the examples posted with root.cern.ch/phpBB2/viewtopic.ph … ilebrowser . It had shown the “Clickable ROOT histograms in QT” . The topic is 1.5 year old.

Thanks for the help.

I agree that we should be moving to QT4 (in fact most of ATLAS has done so). I originally wrote my plugin for the ATLAS Online Histogram Presenter in QT4 only to find that this group has not yet upgrade to the new QT version. Unfortunately, I’m not a member of this working group and cannot make decisions for them, but can only utilize the functionality they provide.

I had a look at your HelloClick program and I am going to use it as a guide. However, for QT I prefer to code everything myself instead of using the qt designer. That way I control ALL parts of my code instead of needing these .ui files which I can’t read or understand.

That is why I started with a simple program. If I can present a histogram in QT, that is a good first step, then I can start adding additional click-ability.

As far as messiness, I was being sloppy while testing, but I would clean this up before making it a production version.

Anyway, I’ve got a lot of version issues to work out before I can continue.

[quote=“jtchil0”]… Unfortunately, I’m not a member of this working group and cannot make decisions for them, but can only utilize the functionality they provide.[/quote]Can I help :unamused: ? [quote=“jtchil0”]I had a look at your HelloClick program and I am going to use it as a guide. [/quote]Ok, Do not hesitate asking me any further questions or an extra ‘Hello’-example. Do not be shy. As soon as you made some good simple code, please send it out to share with the other QtROOT users.[quote=“jtchil0”]However, for QT I prefer to code everything myself instead of using the qt designer.
[/quote]I do not see anything wrong with such approach. However, I do not think any method you were advised to learn from that and the other examples might have been different if I would not use “designer”.
I supposed the “designer” is an innocent piece of the software. It is just a tool.
Yes, the hammer is the bad tool because it doesn’t make a nice haircut, does it? :unamused:
The purpose of the “designer” is out of the scope of this discussion (search doc.qtsoftware.com/4.5/designer- … ormat.html

[quote=“jtchil0”]That is why I started with a simple program. [/quote]Well the main problem of your simple program is the Qt version you tried to use vs. the Qt version the ROOT was compiled against of.
This problem had been discussed many times on this list (For example, root.cern.ch/phpBB2/viewtopic.php?t=7920 )

[quote=“jtchil0”]… I had a look at your HelloClick program and I am going to use it as a guide. However, for QT I prefer to code everything myself instead of using the qt designer. That way I control ALL parts of my code instead of needing these .ui files which I can’t read or understand. …
[/quote]Please, find another version of the HelloClick example

[code]- It doesn’t use any designer. There is no “ui” file anymore

  • It is Qt3/Qt4 compliant. [/code]The example can be built against of Qt3 as well as against of Qt4 with no change of the code. (One still has to re-compile it against of each Qt/Root version). I think you should write your plugin this way to avoid any future Qt4-related correction.
    HelloClick.Qt3Qt4.tar.gz (3.26 KB)

I’m just now getting a moment to come back to this. I’ve written a test program using your QT DynamicSlices example, but I cannot get my plot to appear in the window.

It is just a slimmed down version that does nothing but reads a TProfile from a file and displays it in the TQtWidget Canvas.

Can you identify my problem?

I’ve included the source and the histogram file.

Thanks,
Taylor
testWidget.tar (30 KB)

[quote=“jtchil0”]Can you identify my problem?[/quote] Well, your code contains many :open_mouth: fatal problems.
The net effect of your code is to be the empty QFrame followed by the code crash.
I did

tar -xvf testWidget.tar cd testWidget qmake makeand got:testWidget.cpp: In constructor `TestWidget::TestWidget(QWidget*, const char*)': testWidget.cpp:5: error: no matching function for call to `QFrame::QFrame(QWidget*&, const char*&)' ../../../../4.5.2/qt-x11-opensource-src-4.5.2/include/QtGui/../../src/gui/widgets/qframe.h:140: note: candidates are: QFrame::QFrame(const QFrame&) ../../../../4.5.2/qt-x11-opensource-src-4.5.2/include/QtGui/../../src/gui/widgets/qframe.h:137: note: QFrame::QFrame(QFramePrivate&, QWidget*, Qt::WindowFlags) ../../../../4.5.2/qt-x11-opensource-src-4.5.2/include/QtGui/../../src/gui/widgets/qframe.h:68: note: QFrame::QFrame(QWidget*, Qt::WindowFlags) . . . testWidgetApp.cxx: In function `int main(int, char**)': testWidgetApp.cxx:14: error: 'class QApplication' has no member named 'setMainWidget' . . . Then, your code contains the clause:

[code] TFile file(“06100000.root”,“READ”);
TList* keyList = file.GetListOfKeys();
TKey* key = (TKey*)keyList->At(0);

TProfile* prof = (TProfile*)key->ReadObj();[/code]Since the object “prof” is owned by TFile “06100000.root” ROOT is to delete it as soon as TFile object is destroyed. In your particular case, as soon as the code leaves your widget “ctor”.
Next problem, your file has no TProfile object at all. It contains TCanvas “c1” instead. root [0] TFile f("06100000.root") root [1] .ls TFile** 06100000.root TFile* 06100000.root KEY: TCanvas c1;1 c1 and your ctor names the embedded TCanvas to be “c1” too. As result, as soon as you class ctor “reads” ROOT file, your brand-new embedded TCanvas is to be destroyed immediately because it bears the same name, “c1”. [quote=“jtchil0”]… that does nothing but reads a TProfile from a file and displays it in the TQtWidget Canvas[/quote]In the other words, by the time your code leaves TestWidget::TestWidget class ctor its vital components, the
"embedded TCanvas" and the "TProfile " object are died.[quote=“jtchil0”]… cannot get my plot to appear in the window. [/quote]I am wondering if you see what you your code should do . The net effect of your code is to be the empty QFrame followed by the code crash.

May I suggest you to [ul] 1. Fix the compilation errors.
2. Give your canvas some reasonable name. For example, use your second parameter. Avoid using the names the ROOT uses for its internal TCanvas / TPad.
3. Break TFile / TObject relationship using SetDirectory(0) method.
4. Do not save the TCanvas into your ROOT file. It provides no gain but confusion. Save the real object directly, in your particular case “TProfile”
???[/ul]

Yes, correct on all counts. I was being stupid about my variable’s scope. Also I didn’t realize I had saved the canvas and not the profile. Now it seems to be working. Though, there is a strange behavior with the right click menu, the menu seems to stick around even if I click elsewhere on the canvas. Is there some reason for this?

Thanks for all the help!
Taylor

[quote=“jtchil0”] there is a strange behavior with the right click menu,[/quote]See root.cern.ch/phpBB2/viewtopic.php?p=37962#37962

OK, another clarification to my situation.

So I’m developing a plugin for a QT3 based ATLAS monitoring program called Online Histogram Presenter(OHP). I was suppose to be updated to QT4 a long time ago, but has not been done yet and probably will not happen before beam so I’m stuck using QT3.

From what I can tell they have recompiled your QTROOT classes (from ROOT v5.18 or less) with the ATLAS online software (which is using ROOT v5.22) so they can continue using QT3. The problem now is…

I was able to get my simple program working with just showing a histogram in a QT window using your TQtWidget class (per your HelloClick example). However, they have not included the TQtWidget in their list of classes. So I only have access to the following classes:

TQApplication
TQCanvasImp
TQCanvasMenu
TQRootCanvas
TQRootDialog
TQRootGuiFactory
TQRootWindow

In my plugin, I just want to have an independent window popup and display a histogram. I’ve tried this code and it doesn’t seem to work:

====
frame = new QFrame();
frame->resize(400,435);

qrootCanvas = new TQRootCanvas(frame,“qrootCanvas”);
qrootCanvas->SetName(“canvas”);
qrootCanvas->SetTitle(“Plot Canvas”);

static struct needgraph { needgraph() { TApplication::NeedGraphicsLibs(); gApplication->initializeGraphics();} } needgraph;

TFile file(“file.root”,“READ”);
TList* list = file.GetListOfKeys();
TKey* key = (TKey*)list->At(0);

TH2S* temp= (TH2S*)key->ReadObj();

histogram = new TH2S(*temp);
histogram->SetDirectory(0);

TCanvas* canvas = qrootCanvas->getCanvas();
canvas->GetListOfPrimitives()->Add(histogram,“colz”);
canvas->Modified();

frame->show();

With this I do get the frame window showing up, but no histogram inside.

I tried essentially doing what you did with the TQtWidget, but instead just using the TQRootCanvas class. Is this not a good method? Perhaps I need to do something else.

Can you guide me to the correct method?

Thanks as always,
Taylor