Standalone gui - Error in <TQObject::CheckConnectArgs>: slot does not exist


ROOT Version: 6.18/04
Platform: Ubuntu 18.04
Compiler: gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)


Dear co-rooters,

I’m trying to build a standalone gui. My code includes a header file gui.h in which I define a class and the implementation code gui.cxx. I’m also including a header file for the dictionary generation exLinkDef.h.

First I’m running

rootcling -f exDict.cxx -c gui.h exLinkDef.h

to generate the exDict.cxx file and then I’m compiling the code using

g++ -o SignalViewer gui.cxx exDict.cxx `root-config --cflags --glibs`

Eventually I will include this code in another project and I will build it using make. Although everything is run without any error, when running the executable I get the following error for every function that is defined in the .cxx file.

Error in <TQObject::CheckConnectArgs>: slot draw_histo() does not exist

Any idea on what might be the issue?

Thanks a lot in advance!

My code is the following:

gui.h

#ifndef ___GUI_H
#define ___GUI_H

//ROOT Includes
#include "TFile.h"
#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include "TH1F.h"
#include "TPaveText.h"
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TGNumberEntry.h>
#include <TRootEmbeddedCanvas.h>
#include <TApplication.h>
#include <TGClient.h>
#include <RQ_OBJECT.h>
#include "exLinkDef.h"

using namespace std;

class MainFrame : public TGMainFrame {
private:
   TRootEmbeddedCanvas *emb_canvas, *info_canvas;
   TGVerticalFrame *fr_left;
   TGGroupFrame *fr_runs, *fr_events, *fr_draw, *fr_save;
   //TGLabel *label;
   TGNumberEntry *box_run, *box_event;
public:
   MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
   Bool_t HandleConfigureNotify(Event_t *);
   virtual ~MainFrame();
   void draw_histo();
   void draw_line();
   void draw_line_points();
   void display_info();
   void draw_test();
};

#endif

exLinkDef.h

#ifdef CINT

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class MainFrame;

#endif

gui.cxx

#include "gui.h"

MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height):TGMainFrame(p, width, height, kMainFrame|kHorizontalFrame)
{

    FontStruct_t buttonFont = gClient->GetFont("-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*")->GetFontStruct();
    FontStruct_t titleFont = gClient->GetFont("-*-helvetica-bold-r-*-*-28-*-*-*-*-*-*-*")->GetFontStruct();
    //FontStruct_t numberFont = gClient->GetFont("-*-helvetica-bold-r-*-*-28-*-*-*-*-*-*-*")->GetFontStruct();
    //TGGC   *uGC;

   //---- Left Frame - for buttons and user values
   fr_left  = new TGVerticalFrame(this, 0.3*width, height, kChildFrame|kFixedSize); 
   
   // The 1st grouped frame - runs
   fr_runs = new TGGroupFrame(fr_left, "Run", kChildFrame | kVerticalFrame|kFixedSize);
   fr_runs->SetTextFont(titleFont);
   
   box_run = new TGNumberEntry(fr_runs, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   //int run_number = box_run->GetNumber();
   //bool next_run = (fLowerLimit->GetState() == kButtonDown);
   
   fr_runs->AddFrame(box_run, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_runs, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // The 2nd grouped frame - events
   fr_events = new TGGroupFrame(fr_left, "Event", kChildFrame | kVerticalFrame|kFixedSize);
   fr_events->SetTextFont(titleFont);
   
   box_event = new TGNumberEntry(fr_events, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   
   fr_events->AddFrame(box_event, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_events, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // The 3rd grouped frame - Drawing the signal
   fr_draw = new TGGroupFrame(fr_left, "Draw", kChildFrame | kHorizontalFrame|kFixedSize);
   fr_draw->SetTextFont(titleFont);
   
   TGTextButton *but_draw_histo = new TGTextButton(fr_draw, "&Histo");
   but_draw_histo->SetFont(buttonFont);
   but_draw_histo->Connect("Clicked()", "MainFrame", this, "draw_histo()");
   //Connect(myButton, "Pressed()","TH1",hist, "SetMaximum(=123) ");
   //Connect(myButton, "Pressed()","TH1",hist, "Draw(="LEGO")");
   
   TGTextButton *but_draw_line = new TGTextButton(fr_draw,"&Line");
   but_draw_line->SetFont(buttonFont);
   but_draw_line->Connect("Clicked()", "MainFrame", this, "draw_line()");
   
   
   TGTextButton *but_draw_line_points = new TGTextButton(fr_draw,"&Line - Points");
   but_draw_line_points->SetFont(buttonFont);
   but_draw_line_points->Connect("Clicked()", "MainFrame", this, "draw_line_points()");
   
   fr_draw->AddFrame(but_draw_histo, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line_points, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_draw, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // The 4th grouped frame - Saving the signal
   fr_save = new TGGroupFrame(fr_left, "Save", kChildFrame | kHorizontalFrame|kFixedSize);
   fr_save->SetTextFont(titleFont);
   
   TGTextButton *but_save_histo = new TGTextButton(fr_save,"&Histo");
   but_save_histo->SetFont(buttonFont);
   but_save_histo->Connect("Clicked()", "MainFrame", this, "display_info()");
   
   TGTextButton *but_save_canvas = new TGTextButton(fr_save,"&Canvas");
   but_save_canvas->SetFont(buttonFont);
   
   TGTextButton *but_save_ascii = new TGTextButton(fr_save,"&Ascii");
   but_save_ascii->SetFont(buttonFont);
   
   fr_save->AddFrame(but_save_histo, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_save->AddFrame(but_save_canvas, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_save->AddFrame(but_save_ascii, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_save, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // Output panel
   //TGLabel *label = new TGLabel(fr_left, "TEXT");
   //fr_left->AddFrame(label, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   info_canvas = new TRootEmbeddedCanvas("info_canvas", fr_left, 130, 180);
   fr_left->AddFrame(info_canvas, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
  
   // Test button to see the structure
   TGTextButton *test = new TGTextButton(fr_left,"&Test");
   test->Connect("Clicked()", "MainFrame", this, "draw_test()");
   test->SetFont(buttonFont);
   std::cout << test->GetTitle() << std::endl;
   fr_left->AddFrame(test, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 10, 10, 10, 10) );
   
   // Exit button to exit the application
   TGTextButton *exit = new TGTextButton(fr_left, "&Exit", "gApplication->Terminate(0)");
   exit->SetFont(buttonFont);
   fr_left->AddFrame(exit, new TGLayoutHints(kLHintsCenterX, 5, 5, 3, 4) );
                                          
   AddFrame(fr_left , new TGLayoutHints(kLHintsLeft | kLHintsTop, 10,10,10,10));
  
   
   //---- Right frame - for the canvas
   TGVerticalFrame *fr_right = new TGVerticalFrame(this, 0.7*width, height, kChildFrame);
   
   emb_canvas = new TRootEmbeddedCanvas("canvas", fr_right, 130, 180);
   fr_right->AddFrame(emb_canvas, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
   
   AddFrame(fr_right , new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));

    // Set a name to the main frame
   SetWindowName("DICER signal viewer");
   
   // Map all subwindows of main frame
   MapSubwindows();
   Layout();
   
   // Initialize the layout algorithm
   Resize(GetDefaultSize());
   
   // Map main frame
   MapWindow();

}

////////////////////////////////////////////////////////////////////////////////
/// Handles resize events for the mainframe.

Bool_t MainFrame::HandleConfigureNotify(Event_t *event)
{
    // set the size minus the margins set in the LayoutManager:
   // AddFrame(fr_left , new TGLayoutHints(kLHintsLeft | kLHintsTop, 10,10,10,10));
   UInt_t w = event->fWidth-20;
   UInt_t h = event->fHeight-20;
   
   fr_runs->Resize(0.25*w, 0.15*h);
   fr_runs->Layout();
   
   fr_events->Resize(0.25*w, 0.15*h);
   fr_events->Layout();
   
   fr_draw->Resize(0.25*w, 0.15*h);
   fr_draw->Layout();
   
   fr_save->Resize(0.25*w, 0.15*h);
   fr_save->Layout();
   
   info_canvas->Resize(0.25*w, 0.15*h);
   
   //label->Resize(0.25*w, 0.1*h);
   //label->Layout();
   
   fr_left->Resize(0.25*w, h);
   fr_left->Layout();
   
   return TGMainFrame::HandleConfigureNotify(event);
}

void MainFrame::draw_histo() {
   
   const int nBins = 60;
   Stat_t data[nBins] = {  6, 1,10,12, 6,13,23,22,15,21,
   23,26,36,25,27,35,40,44,66,81,
   75,57,48,45,46,41,35,36,53,32,
   40,37,38,31,36,44,42,37,32,32,
   43,44,35,33,33,39,29,41,32,44,
   26,39,29,35,32,21,21,15,25,15};
   
   TH1F *histo = new TH1F("histo", "Demo histo", 60, 0, 3);

   for(int i=0; i < nBins;  ++i)
      histo->SetBinContent(i+1,data[i]);
   
   histo->SetLineWidth(3);
   histo->SetLineColor(kRed);
   histo->SetMarkerStyle(20);
   histo->SetMarkerColor(kBlack);
   
   histo->Draw("histo");
   
   TCanvas *fCanvas = emb_canvas->GetCanvas();
   fCanvas->cd();
   fCanvas->Update();
   
}

void MainFrame::draw_line() {
   
   const int nBins = 60;
   Stat_t data[nBins] = {  6, 1,10,12, 6,13,23,22,15,21,
   23,26,36,25,27,35,40,44,66,81,
   75,57,48,45,46,41,35,36,53,32,
   40,37,38,31,36,44,42,37,32,32,
   43,44,35,33,33,39,29,41,32,44,
   26,39,29,35,32,21,21,15,25,15};
   
   TH1F *histo = new TH1F("histo", "Demo histo", 60, 0, 3);

   int scaling_factor = box_run->GetNumber();
   std::cout << "Scaling factor is : " << scaling_factor << std::endl;

   for(int i=0; i < nBins;  ++i)
      histo->SetBinContent(i+1,scaling_factor*data[i]);
   
   histo->SetLineWidth(3);
   histo->SetLineColor(kRed);
   histo->SetMarkerStyle(20);
   histo->SetMarkerColor(kBlack);
   
   histo->Draw("l");
   
   TCanvas *fCanvas = emb_canvas->GetCanvas();
   fCanvas->cd();
   fCanvas->Update();
   
   //display_info();
   
}

void MainFrame::draw_line_points() {
   
   const int nBins = 60;
   Stat_t data[nBins] = {  6, 1,10,12, 6,13,23,22,15,21,
   23,26,36,25,27,35,40,44,66,81,
   75,57,48,45,46,41,35,36,53,32,
   40,37,38,31,36,44,42,37,32,32,
   43,44,35,33,33,39,29,41,32,44,
   26,39,29,35,32,21,21,15,25,15};
   
   TH1F *histo = new TH1F("histo", "Demo histo", 60, 0, 3);

   for(int i=0; i < nBins;  ++i)
      histo->SetBinContent(i+1,data[i]);
   
   histo->SetLineWidth(3);
   histo->SetLineColor(kRed);
   histo->SetMarkerStyle(20);
   histo->SetMarkerColor(kBlack);
   
   histo->Draw("l p");
   
   TCanvas *fCanvas = emb_canvas->GetCanvas();
   fCanvas->cd();
   fCanvas->Update();
   
}

void MainFrame::display_info() {
   
   int run_number = box_run->GetNumber();
   int event_number = box_event->GetNumber();
   
   TPaveText *text = new TPaveText(.05,.1,.95,.8);
   text->AddText(TString::Format("Plotting run   : %i", run_number));
   text->AddText(TString::Format("         event : %i", event_number));
   
   text->Draw();
   
   
   TCanvas *fCanvas = info_canvas->GetCanvas();
   fCanvas->cd();
   fCanvas->Update();
   
}

void MainFrame::draw_test() {
   // Draws function graphics in randomly chosen interval
   TF1 *f1 = new TF1("f1","sin(x)/x",0,gRandom->Rndm()*10);
   f1->SetLineWidth(3);
   f1->Draw();
   TCanvas *fCanvas = emb_canvas->GetCanvas();
   fCanvas->cd();
   fCanvas->Update();
}

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

void gui() {
   // Popup the gui
   std::cout << "Starting the gui" << std::endl;
   new MainFrame(gClient->GetRoot(), 800, 500);
}

int main(int argc, char **argv) {
   TApplication theApp("App",&argc,argv);
   gui();
   theApp.Run();
   return 0;
}

I’ve noticed that if the exLinkDef.h file contains only the following line

#pragma link C++ class MainFrame;

the executable can run without an issue. However, I’m not sure if this is the solution because when generating the dictionary I get the following warning

Warning in <MainFrame>: The data members of MainFrame will not be stored, because it inherits from TObject but does not have its own ClassDef.

So if I add

ClassDef (MainFrame,1);

to the gui.h the warning disappears and everything is working fine. I’m wondering though it it’s indeed correct or if there’s something sneaky hiding.

The class version is only required for storing objects in a ROOT file, which is not the case for the GUI (just look at the ROOT GUI classes). So it should work with ClassDef(MainFrame,0);

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.