Passing arguments to function writing a GUI

Hi, i’m trying to write a GUI to draw a histogram and then rebin it.

I don’t know how to pass arguments to the functions i use when i connect them with buttons.

it’s a modified version of the example i found on the user guide

TGTextButton *draw =new TGTextButton(hframe,"&Draw"); draw->Connect("Clicked()","Rebin",this,"DoDraw(string cosa)");

where DoDraw is

[code]void Rebin::DoDraw(string cosa)
{
int PE=0;
cout<<cosa<<endl;

TTree *oldtree =(TTree*)myfile->Get(cosa.c_str());
oldtree->SetBranchAddress("PEtotpmt1",&PE);

int nent =oldtree->GetEntries();

//*****************************************************************************
TH1F *primo =new TH1F(“pmt1”,“pmt1”,nent,0,nent);
for(int g=0; g<nent;g++)
{
oldtree->GetEntry(g);
primo->Fill(PE);
}
TCanvas *canvas2 =new TCanvas();
primo->Draw();
canvas2->Update();
}
[/code]

i get

root [1] prova("PE_totali")
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:
Error: class,struct,union or type stringcosa not defined  (tmpfile):1:

i attach the tar file (a directory named AmirGUI)

compile with “.L Rebin.cc+”, run with “prova(“PE_totali”)”

Thank you

Hi,

  1. My guess is that you want to call DoDraw with different arguments any time your button ‘draw’ is clicked. If yes, then it is better to connect the Clicked signal to another signal method, (for example ‘StringSet’ ) with one argument containing the string you are expected in your DoDraw. And you connect the new signal StringSet with the slot DoDraw.

  2. If you want to call DoDraw any time the button ‘draw’ is clicked with the same string argument - just do:TGTextButton *draw =new TGTextButton(hframe,"&Draw"); draw->Connect("Clicked()","Rebin",this,"DoDraw(=MyString)");

For more details you can see the examples at:
root.cern.ch/root/HowtoSignalSlot.html
root.cern.ch/root/html/examples/exec3.C.html

Cheers, Ilka

Sorry i forgot to attach the files

Thank you Ilka.

for now i’m trying the second option. i’m trying to pass the string “PE_totali” from the “main” void function down to the DoDraw function.

i tryed

draw->Connect("Clicked()","Rebin",this,"DoDraw(=cosa)");

but when i run the script i get:

root [1] prova("PE_totali") Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: Error: Symbol cosa is not defined in current scope (tmpfile):1: *** Interpreter error recovered *** Error: class,struct,union or type (unknown) not defined (tmpfile):1: *** Interpreter error recovered *** root [2]

i think the problem is in my C++ knowledge, but i don’t know where

Amir
AmirGUI.tar.gz (683 KB)

Hi Amir,

Please try with: draw->Connect("Clicked()","Rebin",this,"DoDraw(=PE_totali)");having DoDraw(const char *cosa).

Cheers, Ilka

Hi, i’ve tried but now i get:

root [2] prova() Error in <TQObject>: slot Rebin::DoDraw( PE_totali) does not exist Error in <TQObject>: slot Rebin::DoRebin( PE_totali) does not exist root [3]

i attach the files to reproduce te problem
AmirGUI.tar.gz (683 KB)

Hi Amir,

I made an error in my previous post, sorry. The code: draw->Connect("Clicked()","Rebin",this,"DoDraw(=PE_totali)");should bedraw->Connect("Clicked()","Rebin",this,"DoDraw(=\"PE_totali\")"); because of the string parameter. I made some changes in your macro - please see the attached file and run it via root [0] .x myRebin.C++ It works with the root file provided by you.
Cheers, Ilka
myRebin.C (3.91 KB)

thank you very much Ilka! now it runs perfectly.

it seems in this case that ROOT doesn’t like the string variables since if i modify “const char*” to “string” the program segfaults.

i’ll complicate the things a little more now, but the first step is done. thank you!

Amir

Hi Folks,

I had two slightly different related questions. I am trying to associate different buttons with different histograms and trying to to draw them when a user clicks the appropriate button.

Question 1) I see that one can associate the button “test2” to the function DoDraw() and of course DoDraw() will then draw the histogram (this is being done trivially changing the MainFrame class in statusBar.C here : root.cern.ch/root/html/tutorials … Bar.C.html )

TGTextButton *test2 = new TGTextButton(hframe, “&test2”);
test2->Connect(“Clicked()”, “MyMainFrame”, this, “DoDraw()”);
hframe->AddFrame(test2, new TGLayoutHints(kLHintsCenterX, 5, 5, 3, 4));

However what about when one has several histograms and one wants to “set” a different one for DoDraw() to plot ? Is there a way to pass DoDraw() a TH1F* argument ?

Question 2) I realize this can also be done using the histogram itself like so:

TGTextButton *test2 = new TGTextButton(hframe, “&test2”);

test2->Connect(“Clicked()”, “TH1F”, myhistogram, “Draw()”);

ie using the Draw() function of the TH1F itself, however there is no way to update the canvas in this approach which is done within DoDraw().

I would be really grateful if someone could show me a simple example of a a few buttons which plot different stored histograms when clicked.

many thanks
Farrukh

Hi Farrukh,

Well, there are several options. Here is an example (modified statusBar.C macro) passing a “const char *” as argument: statusBar.C (4.61 KB)
Cheers, Bertrand.

Dear Bertrand

thanks very much for the trouble you took to do this. However, this DoDraw(const char* xx) is still drawing something that is present within the function -> ie thats where the graph is generated.

I was wondering how to pass DoDraw a histogram external to it, and once it has it it should simply draw it using
the histograms draw method for example:

DoDraw(TH1F * histo) {

histo->Draw();

}

Is there anyway of doing the above ?

Thank you again !

Farrukh

OK, then you can use:

And connect with (for example):

draw_graph->Connect("Clicked()", "MyMainFrame", this, TString::Format("DoDraw(=0x%0lx)",(ULong_t)gr));
Cheers, Bertrand.

Dear Bertrand,

once again thank you very much. One more question then, where is the histogram pointer being passed to DoDraw() ?

Is (ULong_t)gr = TH1F* ? Is this the pointer to the histogram ? Just trying to understand what the histogram pointer is

Sorry for the continuous questions !

-Farrukh

[quote=“bellenot”]OK, then you can use:

And connect with (for example):

draw_graph->Connect("Clicked()", "MyMainFrame", this, TString::Format("DoDraw(=0x%0lx)",(ULong_t)gr));
Cheers, Bertrand.[/quote]

[quote=“FarrukhAzfar”]Is (ULong_t)gr = TH1F* ? Is this the pointer to the histogram ? Just trying to understand what the histogram pointer is[/quote]Well, in this case it is the TGraph *gr that has been moved from the DoDraw() method to the constructor of MyMainFrame, but since the argument of DoDraw(TObject *o) is a pointer to TObject(as you can see), you can pass a pointer to any object inheriting from TObject…

Cheers, Bertrand.

Dear Bertrand,

thanks very much. I was curious about the conversion you are doing:

draw_graph->Connect(“Clicked()”, “MyMainFrame”, this,
TString::Format(“DoDraw(=0x%0lx)”,(ULong_t)gr));

is this a standard conversion of casting a pointer as a long int to a string ? What is the 0x%0lx ?
Is this method robust ? Or will it change from platform to platform ?

many thanks
Farrukh

[quote=“bellenot”][quote=“FarrukhAzfar”]Is (ULong_t)gr = TH1F* ? Is this the pointer to the histogram ? Just trying to understand what the histogram pointer is[/quote]Well, in this case it is the TGraph *gr that has been moved from the DoDraw() method to the constructor of MyMainFrame, but since the argument of DoDraw(TObject *o) is a pointer to TObject(as you can see), you can pass a pointer to any object inheriting from TObject…

Cheers, Bertrand.[/quote]

Hi Farrukh,

[quote=“FarrukhAzfar”]is this a standard conversion of casting a pointer as a long int to a string ?[/quote]It is specific to ROOT (using the interpreter)

[quote=“FarrukhAzfar”]What is the 0x%0lx ?[/quote]Simply hexadecimal formatting, like in printf() (it should be 0x%lx, BTW)

[quote=“FarrukhAzfar”]Is this method robust ? Or will it change from platform to platform ?[/quote]It is absolutely robust, and used in several places in ROOT itself

Cheers, Bertrand.

Thanks !!

Farrukh

Robustness of “DoDraw(0x%0lx)”,(ULong_t)gr)" seems to have something worth clarifying:

  1. Does ROOT (interpreter) guarantee that pointer type → ULong_t won’t truncate? Definition of Ulong_t in documentation can’t be relied on because it’s wrong already (e.g on Windows sizeof(ULong_t) == 4 instead of 8 ).
  2. Is the format specifier 0x%0lx OK in interpreter? Asking because it is not reliable e.g. in MSVC 64 bit
uintptr_t ptr = (uintptr(1) << 32);
printf("0x%0lx", ptr);

will print 0x0 instead of 0x100000000.

I am trying a mixed approach, but it fails. Is there another syntaxis, or is it just not possible?

mySlider->Connect("PositionChanged(Int_t)","MyClass",this,"MyFunction(Int_t,=kTRUE)");
Error in <TQObject::CheckConnectArgs>: slot MyClass::MyFunction( kTRUE) does not exist

where MyFunction takes two arguments, one Int_t and a Bool_t

Thanks.

I’m currently facing the same problem, I’d like to pass an additional argument to a call that depends on the status of a button

    TGCheckButton *caloHbutton = new TGCheckButton(hitGroup, "Calo hits");
    caloHbutton->SetOn();
    caloHbutton->Connect("Toggled(Bool_t)", "EDApplication", thisApp, "SetDisplayDetector(= \"Calo\",Int_t )");
    hitGroup->AddFrame(caloHbutton, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));

where the second argument of the SetDisplayDetector module should be linked to the toggle status of the button and I could then in a following stage programmatically specify the string (since in general I won’t know how many of these buttons I will have, it depends on the content of a list)

Well, you can check the button status with TGCheckButton::IsDown() or TGCheckButton::IsOn()
Or is it not good enough?