Custom Browser using GUI

Hi all,

I am creating a small root application using GUI. I added a file browser but I don’t know how to use it very well.

So questions

  1. How to use the DoubleClick method in order to expand the file ? (which is a list of histos)
  2. How to draw one of the histos within the file in a specified canvas ?

Here is a part of my code

[code]MainFrame::MainFrame(const TGWindow *p,UInt_t w,UInt_t h)
{
// Create a main frame
fMain = new TGMainFrame(p,w,h);

TString dirname=“C:\Soleil\Mars2013\Hf\”;
TString name = “FluoHf.root”;
TString outputpath = dirname+name;
TFile *file = new TFile(outputpath.Data(),“UPDATE”); //just a test to add a file to the browser

//Create File Browser
fBrowser = new TGFileBrowser(gClient->GetRoot(),(TBrowser *)0x, 200, 500);
fBrowser->Add(file);

fMain->AddFrame(fBrowser);
}[/code]

Thanks

Hi,

[quote=“Bruno”]1) How to use the DoubleClick method in order to expand the file ? (which is a list of histos)[/quote]You can use (connect to) the signals emitted by the list tree, and then you will have to populate the list tree yourself. See the TGListTree documentation for the list of available signals.

[quote=“Bruno”]2) How to draw one of the histos within the file in a specified canvas ?[/quote]You can use drag and drop (see for example tutorials/gui/drag_and_drop.C), or in your “double click” slot function (e.g. by calling your_target_canvas->cd(); selected_histo->Draw()).
If you still have problems, post a running piece of code showing what you’re doing and where are your problems.

Cheers, Bertrand.

Hi Bellenot, thanks for your answers.

I have still one problem. When I open a root file, I would like to load all histos in the ListTree automatically. I have created a File menu and an open case within a switch structure. The idea is to loop overs the keys and add histos. But root crashed at this time.

The whole code:

[code]#include “TGMenu.h”
#include “TGCanvas.h”

class MainFrame {
RQ_OBJECT(“MainFrame”)
private:
TGMainFrame *fMain;

TGMenuBar *fMenuBar;
TGPopupMenu *fMenuFile;

TGListTree  *fListTree;    // left list tree
TGListTreeItem  *fBaseLTI;     // base (root) list tree item


TGHorizontalFrame *fH0;

TGVerticalFrame *fV0;
TGVerticalFrame *fV1;
TGVerticalFrame *fV2;

TRootEmbeddedCanvas *fRawCanvas;
TRootEmbeddedCanvas *fCalibratedCanvas;
TRootEmbeddedCanvas *fFitCanvas;

public:
MainFrame(const TGWindow *p,UInt_t w,UInt_t h);
virtual ~MainFrame();

void HandleMenu(Int_t);
void FindPeak();
void Fit();
void Calibration();

};

enum EMyMessageTypes {
M_FILE_OPEN,M_FILE_EXIT
};

MainFrame::MainFrame(const TGWindow *p,UInt_t w,UInt_t h)
{

// Create a main frame
fMain = new TGMainFrame(p,w,h);

fMenuBar = new TGMenuBar(fMain, 35, 50, kHorizontalFrame);

fMenuFile = new TGPopupMenu(gClient->GetRoot());
fMenuFile->AddEntry(" &Open…\tCtrl+O", M_FILE_OPEN);
fMenuFile->AddEntry(" &Exit\tAlt+f4", M_FILE_EXIT);

fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,0, 4, 0, 0));

fMain->AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));

fH0 = new TGHorizontalFrame(fMain,1024,768);
fV0 = new TGVerticalFrame(fH0,200,500);

TGCanvas *canvas = new TGCanvas(fV0, 200, 500);
fListTree = new TGListTree(canvas, kHorizontalFrame);

fListTree->Associate(fV0);
fBaseLTI = fListTree->AddItem(0, “Test”);

fMenuFile->Connect(“Activated(Int_t)”, “MainFrame”,fMain,“HandleMenu(Int_t)”);

fV0->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

fV1 = new TGVerticalFrame(fH0,800,700);
fRawCanvas = new TRootEmbeddedCanvas(“RawCanvas”, fV1, 900, 350);
fCalibratedCanvas = new TRootEmbeddedCanvas(“CalibratedCanvas”, fV1, 900, 350);

fV1->AddFrame(fRawCanvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));
fV1->AddFrame(fCalibratedCanvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

fV2 = new TGVerticalFrame(fH0,350,700);
fFitCanvas = new TRootEmbeddedCanvas(“FitCanvas”, fV2, 350, 350);
fV2->AddFrame(fFitCanvas,new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

//Peaks
TGTextButton *peaks = new TGTextButton(fV2,"&Find Peaks");
peaks->Connect(“Clicked()”,“fV2”,fV2,“FindPeak()”);
fV2->AddFrame(peaks, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

//Fit
TGTextButton *fit = new TGTextButton(fV2,"&Fit");
fit->Connect(“Clicked()”,“fV2”,fV2,“Fit()”);
fV2->AddFrame(fit, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

//Calibrate
TGTextButton *calibrate = new TGTextButton(fV2,"&Calibration");
calibrate->Connect(“Clicked()”,“fv2”,fV2,“Calibration()”);
fV2->AddFrame(calibrate, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

fH0->AddFrame(fV0);
fH0->AddFrame(fV1);
fH0->AddFrame(fV2);

fMain->AddFrame(fH0,new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

fMain->SetWindowName(“Energy Calibrator v1.0”);
// Map all subwindows of main frame
fMain->MapSubwindows();
// Initialize the layout algorithm
fMain->Resize(fMain->GetDefaultSize());
// Map main frame
fMain->MapWindow();
}

void MainFrame::HandleMenu(Int_t menu_id)
{
switch (menu_id)
{
case M_FILE_OPEN:

TGFileInfo file_info_;
TGListTreeItem *item;
TH1D *hpx;


const char *filetypes[] = {"ROOT Files", "*.root", 0, 0};
file_info_.fFileTypes = filetypes;
file_info_.fIniDir = StrDup("C:\\Soleil");
TGFileDialog *dialog = new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),kFDOpen, &file_info_);

if( file_info_.fFilename )
TFile *file = new TFile(file_info_.fFilename,"UPDATE");

cout << "'" << file_info_.fFilename << "' selected." << endl;
TDirectory *dir = file->GetDirectory("raw");

TIter next(dir->GetListOfKeys());
TKey *key;
while ((key=(TKey*)next()))  //Loop over keys and add each histo in the ListTree
{
	hpx = (TH1D*)dir->Get(key->GetName());
	item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx); //<-- doesn't work.
}
break;

}
}

void FindPeak(TH1 *h)
{
}

void Fit()
{
}

void Calibration()
{
}

MainFrame::~MainFrame() {
// Clean up used widgets: frames, buttons, layouthints
fMain->Cleanup();
delete fMain;
}

void EnergyCalibration()
{
new MainFrame(gClient->GetRoot(),1024,768);
}[/code]

Hi,

You should make your class inherit from TGMainFrame and remove the RQ_OBJECT(“MainFrame”). It is simpler, and it works (I will investigate why RQ_OBJECT(“MainFrame”) doesn’t work properly).
Here is your code, after a few other minor mods:

[code]#include “TGMenu.h”
#include “TGCanvas.h”

class MainFrame : public TGMainFrame {
private:
TGMenuBar *fMenuBar;
TGPopupMenu *fMenuFile;

TGListTree *fListTree; // left list tree
TGListTreeItem *fBaseLTI; // base (root) list tree item

TGHorizontalFrame *fH0;

TGVerticalFrame *fV0;
TGVerticalFrame *fV1;
TGVerticalFrame *fV2;

TRootEmbeddedCanvas *fRawCanvas;
TRootEmbeddedCanvas *fCalibratedCanvas;
TRootEmbeddedCanvas *fFitCanvas;

public:
MainFrame(const TGWindow *p,UInt_t w,UInt_t h);
virtual ~MainFrame();

void HandleMenu(Int_t);
void FindPeak();
void Fit();
void Calibration();
};

enum EMyMessageTypes {
M_FILE_OPEN,M_FILE_EXIT
};

MainFrame::MainFrame(const TGWindow *p,UInt_t w,UInt_t h) : TGMainFrame(p,w,h)
{
fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);

fMenuFile = new TGPopupMenu(gClient->GetRoot());
fMenuFile->AddEntry(" &Open…\tCtrl+O", M_FILE_OPEN);
fMenuFile->AddEntry(" &Exit\tAlt+f4", M_FILE_EXIT);

fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,0, 4, 0, 0));

AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));

fH0 = new TGHorizontalFrame(this,1024,768);
fV0 = new TGVerticalFrame(fH0,200,500);

TGCanvas *canvas = new TGCanvas(fV0, 200, 500);
fListTree = new TGListTree(canvas, kHorizontalFrame);

fListTree->Associate(fV0);
fBaseLTI = fListTree->AddItem(0, “Test”);

fMenuFile->Connect(“Activated(Int_t)”, “MainFrame”,this,“HandleMenu(Int_t)”);

fV0->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

fV1 = new TGVerticalFrame(fH0,800,700);
fRawCanvas = new TRootEmbeddedCanvas(“RawCanvas”, fV1, 900, 350);
fCalibratedCanvas = new TRootEmbeddedCanvas(“CalibratedCanvas”, fV1, 900, 350);

fV1->AddFrame(fRawCanvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));
fV1->AddFrame(fCalibratedCanvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

fV2 = new TGVerticalFrame(fH0,350,700);
fFitCanvas = new TRootEmbeddedCanvas(“FitCanvas”, fV2, 350, 350);
fV2->AddFrame(fFitCanvas,new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

//Peaks
TGTextButton *peaks = new TGTextButton(fV2,"&Find Peaks");
peaks->Connect(“Clicked()”,“MainFrame”,this,“FindPeak()”);
fV2->AddFrame(peaks, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

//Fit
TGTextButton *fit = new TGTextButton(fV2,"&Fit");
fit->Connect(“Clicked()”,“MainFrame”,this,“Fit()”);
fV2->AddFrame(fit, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

//Calibrate
TGTextButton *calibrate = new TGTextButton(fV2,"&Calibration");
calibrate->Connect(“Clicked()”,“MainFrame”,this,“Calibration()”);
fV2->AddFrame(calibrate, new TGLayoutHints(kLHintsCenterX,5,5,3,4));

fH0->AddFrame(fV0);
fH0->AddFrame(fV1);
fH0->AddFrame(fV2);

AddFrame(fH0,new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5,5,5));

SetWindowName(“Energy Calibrator v1.0”);
// Map all subwindows of main frame
MapSubwindows();
// Initialize the layout algorithm
Resize(GetDefaultSize());
// Map main frame
MapWindow();
}

void MainFrame::HandleMenu(Int_t menu_id)
{
switch (menu_id) {
case M_FILE_OPEN:
{
TGFileInfo file_info_;
TGListTreeItem *item;
TH1 *hpx;

     const char *filetypes[] = {"ROOT Files", "*.root", 0, 0};
     file_info_.fFileTypes = filetypes;
     file_info_.fIniDir = StrDup("C:\\Soleil");
     TGFileDialog *dialog = new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),kFDOpen, &file_info_);

     if ( file_info_.fFilename ) {
        TFile *file = new TFile(file_info_.fFilename,"UPDATE");
        cout << "'" << file_info_.fFilename << "' selected." << endl;
        TDirectory *dir = file->GetDirectory("raw");
        if (!dir) {
           new TGMsgBox(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), 
                        "Error opening directory", 
                        Form("There is no \"raw\" directory in %s", file_info_.fFilename),
                        kMBIconExclamation, kMBOk);
           dir = gDirectory;
        }
        TIter next(dir->GetListOfKeys());
        TKey *key;
        while ((key=(TKey*)next())) { //Loop over keys and add each histo in the ListTree
           hpx = (TH1*)dir->Get(key->GetName());
           if (!hpx) continue;
           const TGPicture *pic = gClient->GetPicture("h1_t.xpm");
           item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic); //<-- should work now.
        }
     }
  }
  break;

}
}

void MainFrame::FindPeak(TH1 *h)
{
}

void MainFrame::Fit()
{
}

void MainFrame::Calibration()
{
}

MainFrame::~MainFrame() {
// Clean up used widgets: frames, buttons, layouthints
Cleanup();
}

void EnergyCalibration()
{
new MainFrame(gClient->GetRoot(),1024,768);
}
[/code]
Cheers, Bertrand.

Great ! Thanks a lot :slight_smile:

You’re welcome! :slight_smile:
And BTW, to enable drag and drop, simply add “item->SetDNDSource(kTRUE);” after adding the item in the list tree, as show below:

item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic); item->SetDNDSource(kTRUE);
Cheers, Bertrand.

A little question again :slight_smile:

I have created this method in order to find peaks in a histo using the TSprectrum Search() method:

void MainFrame::FindPeak() { TCanvas *c = fRawCanvas->GetCanvas(); TIter next(c->GetListOfPrimitives()); TObject *obj; while (obj=(TObject*)next()) { if (obj->IsA()->InheritsFrom("TH1")) //Get the histo in the canvas (the histo name is not known) fRaw = (TH1D*)obj; } TSpectrum *s = new TSpectrum(); Int_t nfound = s->Search(fRaw,2.5,"nobackground"); c->Update(); printf("Found %d candidate peaks to fitn",nfound); }

fRaw is declared in the class.

[code]class MainFrame : public TGMainFrame {
private:

//many other delcarations

TRootEmbeddedCanvas *fRawCanvas;
TRootEmbeddedCanvas *fCalibratedCanvas;
TRootEmbeddedCanvas *fFitCanvas;

TH1D *fRaw;

public:
MainFrame(const TGWindow *p,UInt_t w,UInt_t h);
virtual ~MainFrame();

void HandleMenu(Int_t);
void FindPeak();
void Fit();
void Calibration();
};[/code]

And in the constructor I called fRaw = new TH1D();

But any operations on fRaw create a crash. I do not see very well because, for instance, I can get the canvas within the method FindPeak() withTCanvas *c = fRawCanvas->GetCanvas(); and fRawCanvas is declared like fRaw.

Well, there are several issues in your code… For example:

while (obj=(TObject*)next()) { if (obj->IsA()->InheritsFrom("TH1")) //Get the histo in the canvas (the histo name is not known) fRaw = (TH1D*)obj; }
You can add a break statement once you found the TH1D. And BTW, if you want a TH1D, you should check for TH1D (e.g. a TH2 inherits from TH1 as well…):

while (obj=(TObject*)next()) { if (obj->IsA() == TH1D::Class()) { //Get the histo in the canvas (the histo name is not known) fRaw = (TH1D*)obj; break; } }

Replace this statement in the constructor by fRaw = 0; So then you can check if the object has properly been found:

if (fRaw) { TSpectrum *s = new TSpectrum(); Int_t nfound = s->Search(fRaw,2.5,"nobackground"); c->Update(); printf("Found %d candidate peaks to fitn",nfound); }

[quote=“Bruno”] and fRawCanvas is declared like fRaw.[/quote] Well, pointers should be initialized to 0 and then checked for validity, as shown in the code above. This would prevent random crashes. And BTW, compiling your code with ACLiC should also help debugging it. And as usual, if you still have problems, please send a minimal running piece of code reproducing the issues.

Cheers, Bertrand.

Resurrection ! :slight_smile:

I would like to know how to include a TGFileBrowser in a GUI in order to browse all files available and load root files with directories, subdirectories…

The GUI

I found in TRooBrowser that the TGFileBrowser is included using a plugin command but I don’t understand very well how it works and how to use it.

I found the solution.