Compilation of statusBar.C as standalone code

Dear ROOTers,

In order to implement a stand alone code which is able to handle the mouse and keyboard events, I thought I could try to compile and run the gui example statusBar.C.

Prior to any changes, I tested successfully the code on the root prompt as :

.x statusBar.C

I tried to modified the code according to the recommendations in the following post. But I still did not manage to compile the code successfully with a command-line solution and a CMakeList.txt solution:

$ g++ -std=c++14 statusBar.cxx `root-config --glibs --cflags` -o statusBar
/tmp/cccT5439.o: In function `MyMainFrame::IsA() const':
statusBar.cxx:(.text._ZNK11MyMainFrame3IsAEv[_ZNK11MyMainFrame3IsAEv]+0xd): undefined reference to `MyMainFrame::Class()'
/tmp/cccT5439.o: In function `MyMainFrame::ShowMembers(TMemberInspector&) const':
statusBar.cxx:(.text._ZNK11MyMainFrame11ShowMembersER16TMemberInspector[_ZNK11MyMainFrame11ShowMembersER16TMemberInspector]+0x11): undefined reference to `MyMainFrame::Class()'
/tmp/cccT5439.o:(.rodata._ZTV11MyMainFrame[_ZTV11MyMainFrame]+0x1d8): undefined reference to `MyMainFrame::Streamer(TBuffer&)'
/tmp/cccT5439.o:(.rodata._ZTV11MyMainFrame[_ZTV11MyMainFrame]+0x600): undefined reference to `non-virtual thunk to MyMainFrame::Streamer(TBuffer&)'
collect2: error: ld returned 1 exit status

and with CMakeLists.txt (3.8 KB) giving the error:

-- Project: statusBar
-- Compiling with -std=c++14
-- Installation of ROOT found: ----> root-6.10.08
-- ROOT_VERSION >= 6.0     YES
-- Configuring done
-- Generating done
-- Build files have been written to: /home/sotty/Experiments/IS608/root/macros/StatusBar/build
Scanning dependencies of target statusBar
[ 50%] Building CXX object CMakeFiles/statusBar.dir/statusBar.cxx.o
[100%] Linking CXX executable statusBar
CMakeFiles/statusBar.dir/statusBar.cxx.o: In function `MyMainFrame::MyMainFrame(TGWindow const*, unsigned int, unsigned int)':
statusBar.cxx:(.text+0x627): undefined reference to `TGMainFrame::TGMainFrame(TGWindow const*, unsigned int, unsigned int, unsigned int)'
statusBar.cxx:(.text+0x65a): undefined reference to `TGFrame::GetDefaultFrameBackground()'
statusBar.cxx:(.text+0x698): undefined reference to `TRootEmbeddedCanvas::TRootEmbeddedCanvas(char const*, TGWindow const*, unsigned int, unsigned int, unsigned int, unsigned long)'
statusBar.cxx:(.text+0x710): undefined reference to `TRootEmbeddedCanvas::AdoptCanvas(TCanvas*)'
statusBar.cxx:(.text+0x78f): undefined reference to `TGCompositeFrame::AddFrame(TGFrame*, TGLayoutHints*)'
statusBar.cxx:(.text+0x7b0): undefined reference to `TGFrame::GetDefaultFrameBackground()'
statusBar.cxx:(.text+0x7e5): undefined reference to `TGStatusBar::TGStatusBar(TGWindow const*, unsigned int, unsigned int, unsigned int, unsigned long)'
statusBar.cxx:(.text+0x897): undefined reference to `TGCompositeFrame::AddFrame(TGFrame*, TGLayoutHints*)'
statusBar.cxx:(.text+0x89c): undefined reference to `TGFrame::GetDefaultFrameBackground()'
statusBar.cxx:(.text+0x8da): undefined reference to `TGButton::GetDefaultGC()'
statusBar.cxx:(.text+0x8e2): undefined reference to `TGGC::operator()() const'
statusBar.cxx:(.text+0x8ea): undefined reference to `TGTextButton::GetDefaultFontStruct()'
statusBar.cxx:(.text+0x921): undefined reference to `TGTextButton::TGTextButton(TGWindow const*, char const*, int, unsigned long, unsigned long, unsigned int)'
...

Here you can find the CMakeList.txt and statusBar.cxx (modified):
statusBar.cxx (6.0 KB)
CMakeLists.txt (3.8 KB)

Any comments or ideas are very welcome.

Cheers,
Christophe

Hi,

Here is how to create a standalone executable with your code:

  • Create a header file (statusBar.h):
#include "TGFrame.h"

class TRootEmbeddedCanvas;
class TGStatusBar;

class MyMainFrame : public TGMainFrame {

private:
   TRootEmbeddedCanvas  *fEcan;
   TGStatusBar          *fStatusBar;

public:
   MyMainFrame(const TGWindow *p, UInt_t w, UInt_t h);
   virtual ~MyMainFrame();
   void DoExit();
   void DoDraw();
   void SetStatusText(const char *txt, Int_t pi);
   void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected);

   ClassDef(MyMainFrame, 0)
};
  • A linkdef.h file:
#ifdef __CINT__

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

#pragma link C++ class MyMainFrame+;

#endif
  • Now your statusBar.cxx:
/// \file
/// \ingroup tutorial_gui
/// This macro gives an example of how to create a status bar related to an embedded canvas that shows the info of the selected object,
/// exactly as the status bar of any canvas window.
/// To run it do either:
/// ~~~
/// .x statusBar.C
/// .x statusBar.C++
/// ~~~
///
/// \macro_code
///
/// \author Ilka Antcheva   1/12/2006

// rootcint -f dict.cxx -c statusbar.h linkdef.h
// cl -nologo -MDd -GR -EHsc box.cxx boxDict.cxx -I %ROOTSYS%\include /link -LIBPATH:%ROOTSYS%\lib libCore.lib libCint.lib libGpad.lib libHist.lib

#include "statusBar.h"
#include "TApplication.h"
#include "TGButton.h"
#include "TGStatusBar.h"
#include "TRootEmbeddedCanvas.h"
#include "TCanvas.h"
#include "TGraph.h"
#include "TAxis.h"
#include "TFrame.h"

void MyMainFrame::DoDraw()
{
   // Draw something in the canvas

   Printf("Slot DoDraw()");

   TCanvas *c1 = fEcan->GetCanvas();
   c1->SetFillColor(42);
   c1->SetGrid();
   const Int_t n = 20;
   Double_t x[n], y[n];
   for (Int_t i=0;i<n;i++) {
     x[i] = i*0.1;
     y[i] = 10*sin(x[i]+0.2);
     printf(" i %i %f %f \n",i,x[i],y[i]);
   }
   TGraph *gr = new TGraph(n,x,y);
   gr->SetLineColor(2);
   gr->SetLineWidth(4);
   gr->SetMarkerColor(4);
   gr->SetMarkerStyle(21);
   gr->SetTitle("a simple graph");
   gr->GetXaxis()->SetTitle("X title");
   gr->GetYaxis()->SetTitle("Y title");
   gr->Draw("ACP");

   // TCanvas::Update() draws the frame, after which it can be changed
   c1->Update();
   c1->GetFrame()->SetFillColor(21);
   c1->GetFrame()->SetBorderSize(12);
   c1->Modified();
   c1->Update();
}

void MyMainFrame::DoExit()
{
   printf("Exit application...");
   gApplication->Terminate(0);
}

void MyMainFrame::SetStatusText(const char *txt, Int_t pi)
{
   // Set text in status bar.
   fStatusBar->SetText(txt,pi);
}

void MyMainFrame::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
{
//  Writes the event status in the status bar parts

   const char *text0, *text1, *text3;
   char text2[50];
   text0 = selected->GetTitle();
   SetStatusText(text0,0);
   text1 = selected->GetName();
   SetStatusText(text1,1);
   if (event == kKeyPress)
      sprintf(text2, "%c", (char) px);
   else
      sprintf(text2, "%d,%d", px, py);
   SetStatusText(text2,2);
   text3 = selected->GetObjectInfo(px,py);
   SetStatusText(text3,3);
}

MyMainFrame::MyMainFrame(const TGWindow *p, UInt_t w, UInt_t h) :
   TGMainFrame(p, w, h)
{
   // Create the embedded canvas
   fEcan = new TRootEmbeddedCanvas(0,this,500,400);
   Int_t wid = fEcan->GetCanvasWindowId();
   TCanvas *myc = new TCanvas("MyCanvas", 10,10,wid);
   fEcan->AdoptCanvas(myc);
   myc->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)","MyMainFrame",this,
               "EventInfo(Int_t,Int_t,Int_t,TObject*)");

   AddFrame(fEcan, new TGLayoutHints(kLHintsTop | kLHintsLeft |
                                     kLHintsExpandX  | kLHintsExpandY,0,0,1,1));
   // status bar
   Int_t parts[] = {45, 15, 10, 30};
   fStatusBar = new TGStatusBar(this, 50, 10, kVerticalFrame);
   fStatusBar->SetParts(parts, 4);
   fStatusBar->Draw3DCorner(kFALSE);
   AddFrame(fStatusBar, new TGLayoutHints(kLHintsExpandX, 0, 0, 10, 0));

   // Create a horizontal frame containing two buttons
   TGHorizontalFrame *hframe = new TGHorizontalFrame(this, 200, 40);

   TGTextButton *draw = new TGTextButton(hframe, "&Draw");
   draw->Connect("Clicked()", "MyMainFrame", this, "DoDraw()");
   hframe->AddFrame(draw, new TGLayoutHints(kLHintsCenterX, 5, 5, 3, 4));
   TGTextButton *exit = new TGTextButton(hframe, "&Exit ");
   exit->Connect("Pressed()", "MyMainFrame", this, "DoExit()");
   hframe->AddFrame(exit, new TGLayoutHints(kLHintsCenterX, 5, 5, 3, 4));

   AddFrame(hframe, new TGLayoutHints(kLHintsCenterX, 2, 2, 2, 2));

   // Set a name to the main frame
   SetWindowName("Embedded Canvas Status Info");
   MapSubwindows();

   // Initialize the layout algorithm via Resize()
   Resize(GetDefaultSize());

   // Map main frame
   MapWindow();
}

MyMainFrame::~MyMainFrame()
{
   // Clean up main frame...
   Cleanup();
   delete fEcan;
}

/*void statusBar()
{
   // Popup the GUI...
   new MyMainFrame(gClient->GetRoot(), 200, 200);
}
*/

int main(int argc, char *argv[])
{
   TApplication theApp("App", &argc, argv);
   // Popup the GUI...
   new MyMainFrame(gClient->GetRoot(),200,200);
   theApp.Run();
   return 0;
}

And finally, to create your executable, just do:

rootcling -f statusBarDict.cxx -c statusBar.h linkdef.h
g++ -std=c++14 statusBar.cxx statusBarDict.cxx `root-config --glibs --cflags` -o statusBar

Cheers, Bertrand.

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