Fixed size of TGButtonGroup

Dear ROOTers,

I’ve been working on a GUI uses ROOT widgets. Now I am making a small TGHButtonGroup with two TGCheckButtons inside. I create this in a very simple manner, by using a small array fAButton[] of (the two) buttons checkbuttons.

[code]fButtonGroup = new TGHButtonGroup(fHorizontalFrame,“TestGroup”);
fAButton[0] = new TGCheckButton(fButtonGroup, new TGHotString(“Button 1”), 0);
fAButton[0]->Connect(“Clicked()”,“My_Class”,this,“Function1()”);
fAButton[1] = new TGCheckButton(fButtonGroup, new TGHotString(“Button 2”), 1);
fAButton[1]->Connect(“Clicked()”,“My_Class”,this,“Function2()”);

fButtonGroup->Show();
fHorizontalFrame->AddFrame(fButtonGroup,new TGLayoutHints(kLHintsExpandY|kLHintsLeft|kLHintsTop,5,5,5,5));
[/code]

Now I’ve added the fButtonGroup to my horizontal frame. And this horizontal frame is added to the main frame of my GUI. Here comes the problem: for some reason, every time I select one of the checkbuttons and resize my GUI window, my second checkbutton fAButton[1] gets “squeezed” somehow behind my frame. I made a screenshot of is (see attachment). Does anyone know how to fix this?

Hi,

Sorry, but I don’t see the problem, at least with this code:

#include <TApplication.h>
#include <TGClient.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TGLayout.h>
#include <TGButtonGroup.h>

class MyButtonTest : public TGMainFrame {

private:
   TGTextButton        *fExit;         // Exit text button
   TGHButtonGroup      *fButtonGroup;  // Button group
   TGCheckButton       *fAButton[2];   // Check buttons
   
public:
   MyButtonTest(const TGWindow *p, UInt_t w, UInt_t h);
   virtual ~MyButtonTest();

   void DoExit();
   void Function1() {}
   void Function2() {}

   ClassDef(MyButtonTest, 0)
};
                          
MyButtonTest::MyButtonTest(const TGWindow *p, UInt_t w, UInt_t h) 
   : TGMainFrame(p, w, h)   
{
   SetCleanup(kDeepCleanup);
   
   Connect("CloseWindow()", "MyButtonTest", this, "DoExit()");
   DontCallClose();

   TGHorizontalFrame *fHorizontalFrame = new TGHorizontalFrame(this, 70, 100);

   fButtonGroup = new TGHButtonGroup(fHorizontalFrame, "TestGroup");
   fAButton[0] = new TGCheckButton(fButtonGroup, new TGHotString("Button 1"), 0);
   fAButton[0]->Connect("Clicked()","MyButtonTest", this, "Function1()");
   fAButton[1] = new TGCheckButton(fButtonGroup, new TGHotString("Button 2"), 1);
   fAButton[1]->Connect("Clicked()","MyButtonTest", this, "Function2()");
   fButtonGroup->Show();
   fHorizontalFrame->AddFrame(fButtonGroup, new TGLayoutHints(kLHintsExpandY | 
                              kLHintsLeft | kLHintsTop, 5, 5, 5, 5));

   AddFrame(fHorizontalFrame);

   TGHorizontalFrame *fHL3 = new TGHorizontalFrame(this, 70, 100, kFixedWidth);
   fExit = new TGTextButton(fHL3, "&Exit", -1);
   fExit->Connect("Clicked()", "MyButtonTest", this, "DoExit()");
   fHL3->AddFrame(fExit, new TGLayoutHints(kLHintsExpandX));
   AddFrame(fHL3, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 5, 5, 5, 5));

   SetWindowName("My Button Group");
   MapSubwindows();
   Resize(GetDefaultSize());
   MapWindow();

};

MyButtonTest::~MyButtonTest()
{
   // Destructor.
   Cleanup();
}

void MyButtonTest::DoExit()
{
   // Exit this application via the Exit button or Window Manager.

   gApplication->Terminate();   // to exit and close the ROOT session   
}

void buttonGroup() 
{
   new MyButtonTest(gClient->GetRoot(),100,100);
}

If this doesn’t work for you, please specify which version of ROOT and which platform (OS/compiler).
If this macro works for you, but not your code, then I would ask you to provide a working macro demonstrating the problem (the few lines you provided are not sufficient)

Cheers, Bertrand.

Thank you for responding so quickly. The macro you sent me worked, but my problem still remains. My class is as follows.

#include <TApplication.h>
#include <TGClient.h>
#include <TGButton.h>
#include <TGStatusBar.h>
#include <TGFrame.h>
#include <TGLayout.h>
#include <TGWindow.h>
#include <TGLabel.h>
#include <TString.h>
#include <TGButtonGroup.h>
#include <TGComboBox.h>
#include <TArrayI.h>
#include <TGTextView.h>
#include <Riostream.h>
#include <TList.h>

// needed for the canvas
#include <TCanvas.h>
#include <TF1.h>
#include <TRootEmbeddedCanvas.h>

// needed for the tabs
#include <TGTab.h>
#include <RQ_OBJECT.h>

// needed for file dialog
#include <TGInputDialog.h>
#include <TGMsgBox.h>

#include "SPDMonitoringContainer.h"

// GLOBAL VARIABLES FOR EASY ADJUSTMENTS
const int NBs = 34;                  // # buttons
const int NBg = 5;                   // # button groups
const int NCv = 7;                   // # canvases
const int NTb = 7;                   // # tabs

enum {kDDL=20, kNHS=6, kNRadio=26};  // # equipments, # half staves, #radio buttons

// TWO REMARKS
// 1) #(BUTTON NAMES) SHOULD EQUAL #(HISTOGRAM TYPES)
// 2) PLEASE MAKE SURE THE FUNCTION DrawContainerHist STILL CALLS THE RIGHT HISTOGRAMS

class SPDMonitoringContainer;

//=======================================
class GUI:public TGMainFrame{
//=======================================


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



  // WIDGET HANDLING
  void CreateFrames();
  void CreateButtons();
  void CreateDrawButtons();
  void CreateTabs();
  void BuildGUI();

  void DoExit();

  // USER INPUT
  void SelectEq();  
  void SelectHs();

  void DrawHist();

  enum {kStart=kNRadio+1,kMissingFo,kNoisyFo,kFoYield,kLastFo};
  enum {kMissingHits=kLastFo,kNoisyHits,kHitsYield,kLast}; // BUttonID
  enum {kDataFormat=kLast, kErrorList,kHitMultiplicity,kFinal};
  enum {kAllHs = kDDL+kNHS, kAllEq, kRatio = 46};
  
private:

  // GENERAL
  TGCompositeFrame    *fCom1;        // main frame
  TObject             *fContainer;   // data container

  // DETECTOR PARTS SELECTION (LEFT, UP)
  TGCompositeFrame    *fCom3;        // left frame
  TGHorizontalFrame   *fHor1;        // upper left frame, equipment buttons
  TGHorizontalFrame   *fHor2;        // middle left frame, half stave buttons
  TGHorizontalFrame   *fHor3;        // middle left frame, select all buttons
  
  TGButtonGroup       *fButtons[NBg];// button groups
  TGButton            *fAButton[NBs];// buttons, (kDDL + kNHS + 1(DrawAllHs) + 3(FastOr) + 3(Hits))

  TGVButtonGroup      *fFastOrHistogramDraw; // lower tab buttons

  // HISTOGRAM BUTTONS (LEFT, DOWN)
  TGTab               *fTabType;     // pointer to the choice tabs
  TGCompositeFrame    *fCom4;        // specific histograms buttons frame (horizontal)
  TGCompositeFrame    *fCom5;        // generic histograms buttons frame (horizontal)

  TGCompositeFrame    *fFastOrGroup; // button group, FastOr (vertical)
  TGCompositeFrame    *fHitsGroup;   // button group, Hits (vertical)


  // FLAGS
  Short_t             fCurrentEq;    // stores selected equipment
  Short_t             fCurrentHs;    // stores selected half stave
  Short_t             fCurrentBt;    // stores selected button
  Short_t             fCurrentErrorType;    // stores selected button]
  
  Bool_t	      fDrawAllHs;
  Bool_t              fDrawAllEq;
  

  TArrayI             fTabInfo;       // stores user button selections

  TString fButtonName[9]; 

  ClassDef(GUI, 1)

}; //GUI:public TGMainFrame

And my macro is as follows.

[code]
#include <GUI.h>
#include “AliITSRawStreamSPD.h”
#include “AliITSRawStreamSPDErrorLog.h”

//=========================================================================================
GUI::GUI(const TGWindow *p, UInt_t w, UInt_t h):TGMainFrame(p,w,h){
//=========================================================================================
// Sets up the environment for the main frame.
//=========================================================================================
// button names for histogram types ID = { kDDL+kNHS,…,kDDL+kNHS+ #histogram types }
fButtonName[0]= “Dummy 0”;
fButtonName[1]= “Dummy 1”;
fButtonName[2]= “Dummy 2”;
fButtonName[3]= “Dummy 3”;
fButtonName[4]= “Dummy 4”;
fButtonName[5]= “Dummy 5”;
fButtonName[6]= “Dummy 6”;
fButtonName[7]= “Dummy 7”;
fButtonName[8]= “Dummy 8”;

fTabInfo.Set(NTb);
for(int i = 0; i < NTb; i++) fTabInfo.SetAt(-1,i);

// HISTOGRAM SELECTION VARIABLES
fCurrentEq = -1;
fCurrentHs = -1;
fCurrentBt = -1;
fDrawAllEq = kFALSE;
fDrawAllHs = kFALSE;

// SET UP MAIN FRAME
SetCleanup(kDeepCleanup);
Connect(“CloseWindow()”, “GUI”, this, “DoExit()”);
DontCallClose();

// CREATE AND BUILD GUI
CreateFrames();
CreateButtons();
CreateTabs();
BuildGUI();

// STANDARD WINDOW MAPPING
SetWindowName(“AMORE GUI - Preliminary version”);
MapSubwindows();
Resize(GetDefaultSize());
MapWindow();

}; // GUI:GUI

//==================================
GUI::~GUI(){
//==================================
// Cleans up widgets.
//==================================
Cleanup();
} //GUI::~GUI

//=============================
void GUI::DoExit(){
//=============================
// Closes the application.
//=============================

gApplication->Terminate(0);
} // GUI::DoExit

//===================================
void GUI::CreateFrames(){
//===================================
// Creates basic frames.
//===================================
// MAIN FRAME
Int_t width1 = 200;

fCom1 = new TGCompositeFrame(this, 1000, 1000, kHorizontalFrame);

// LEFT FRAMES
fCom3 = new TGCompositeFrame(fCom1,width1,200, kVerticalFrame);
fHor1 = new TGHorizontalFrame(fCom3,width1,200);
fHor2 = new TGHorizontalFrame(fCom3,width1,200);
fHor3 = new TGHorizontalFrame(fCom3,width1,200);

} // GUI::CreateFrames

//====================================
void GUI::CreateButtons(){
//====================================
// Creates button widgets.
//====================================
// EQUIPMENT BUTTONS (LEFT TOP)
fButtons[0] = new TGVButtonGroup(fHor1," SIDE A");
fButtons[1] = new TGVButtonGroup(fHor1," SIDE C");

for(int eq = 0; eq < 0.5kDDL; eq++ )
{
fAButton[eq] = new TGRadioButton(fButtons[0],new TGHotString(Form(“Eq %i”,eq)),eq);
fAButton[eq] ->Connect(“Clicked()”,“GUI”,this,“SelectEq()”);
fAButton[eq+(int)(kDDL
0.5)] = new TGRadioButton(fButtons[1],new TGHotString(Form(“Eq %i”,eq+(int)(kDDL0.5))),eq+(int)(kDDL0.5));
fAButton[eq+(int)(kDDL*0.5)] ->Connect(“Clicked()”,“GUI”,this,“SelectEq()”);
} // for

// HALF STAVE BUTTONS (LEFT MIDDLE)
fButtons[2] = new TGVButtonGroup(fHor2,“Inner HS”);
fButtons[3] = new TGVButtonGroup(fHor2,“Outer HS”);

for(int hs = 0; hs < kNHS; hs++)
{
if ( hs < 2 )
{
fAButton[hs+kDDL] = new TGRadioButton(fButtons[2],new TGHotString(Form(“HS %i”,hs)),hs+kDDL);
fAButton[hs+kDDL] ->Connect(“Clicked()”,“GUI”,this,“SelectHs()”);
} // if
else
{
fAButton[hs+kDDL] = new TGRadioButton(fButtons[3],new TGHotString(Form(“HS %i”,hs)),hs+kDDL);
fAButton[hs+kDDL] ->Connect(“Clicked()”,“GUI”,this,“SelectHs()”);
} // else
} // for

fButtons[4] = new TGHButtonGroup(fHor3,“Select ALL”);
fButtons[4] ->Resize(100,20);

fAButton[kAllHs] = new TGCheckButton(fButtons[4], new TGHotString(“All HS”), kAllHs);
fAButton[kAllHs] ->Connect(“Clicked()”,“GUI”,this,“SelectHs()”);
fAButton[kAllEq] = new TGCheckButton(fButtons[4], new TGHotString(“All Eq”), kAllEq);
fAButton[kAllEq] ->Connect(“Clicked()”,“GUI”,this,“SelectEq()”);
fAButton[kRatio] = new TGCheckButton(fButtons[4], new TGHotString(“Ratio on off”), kRatio);

fButtons[0]->Show();
fButtons[1]->Show();
fButtons[2]->Show();
fButtons[3]->Show();
fButtons[4]->Show();

TGLayoutHints *layout = new TGLayoutHints(kLHintsExpandY|kLHintsLeft|kLHintsTop,5,5,5,5);

fHor1 ->AddFrame(fButtons[0],layout);
fHor1 ->AddFrame(fButtons[1],layout);
fHor2 ->AddFrame(fButtons[2],layout);
fHor2 ->AddFrame(fButtons[3],layout);
fHor3 ->AddFrame(fButtons[4],layout);

} // GUI::CreateButtons

//=================================
void GUI::CreateTabs(){
//=================================
// Creates tab widgets.
//=================================
// TYPE TABS
fTabType = new TGTab(fCom3,150,300);
TGCompositeFrame *tf;

// SPECIFIC HISTOGRAMS
tf = fTabType->AddTab(“Specific histograms”);
Int_t parts[] = {45, 45};
TGStatusBar *fStatusBar = new TGStatusBar(tf, 50, 10, kVerticalFrame);
fStatusBar ->SetParts(parts, 2);
fStatusBar ->Draw3DCorner(kFALSE);
fStatusBar ->AddText(“Fast Or”,0);
fStatusBar ->AddText(“Hits”,1);
tf ->AddFrame(fStatusBar, new TGLayoutHints(kLHintsExpandX, 0, 0, 10, 0));
fCom4 = new TGCompositeFrame(tf,100,100,kVerticalFrame);
tf ->AddFrame(fCom4);

// GENERIC HISTOGRAMS
tf = fTabType->AddTab(“Generic histograms”);
fCom5 = new TGCompositeFrame(tf,100,100,kHorizontalFrame);
tf ->AddFrame(fCom5);

// DRAW BUTTONS (LEFT BOTTOM) - FASTOR
CreateDrawButtons();

} // GUI::CreateTabs

//========================================
void GUI::CreateDrawButtons(){
//========================================
// Creates buttons that draw the selected histogram.
//========================================

TGCompositeFrame *upperGroup = new TGCompositeFrame(fCom4,60,20,kHorizontalFrame);

// fFastOrGroup = new TGCompositeFrame(fCom4,60,20,kVerticalFrame);
fFastOrGroup = new TGCompositeFrame(upperGroup,60,20,kVerticalFrame);
fAButton[kMissingFo] = new TGTextButton(fFastOrGroup,(const char*)(fButtonName[kMissingFo-kStart-1].Data()),kMissingFo);
fAButton[kNoisyFo] = new TGTextButton(fFastOrGroup,(const char*)(fButtonName[kNoisyFo-kStart-1].Data()),kNoisyFo);
fAButton[kFoYield] = new TGTextButton(fFastOrGroup,(const char*)(fButtonName[kFoYield-kStart-1].Data()),kFoYield);

//fHitsGroup = new TGCompositeFrame(fCom4,60,20,kVerticalFrame);
fHitsGroup = new TGCompositeFrame(upperGroup,60,20,kVerticalFrame);
fAButton[kMissingHits] = new TGTextButton(fHitsGroup,(const char*)(fButtonName[kMissingHits-kStart-1].Data()),kMissingHits);
fAButton[kNoisyHits] = new TGTextButton(fHitsGroup,(const char*)(fButtonName[kNoisyHits-kStart-1].Data()),kNoisyHits);
fAButton[kHitsYield] = new TGTextButton(fHitsGroup,(const char*)(fButtonName[kHitsYield-kStart-1].Data()),kHitsYield);

for(int btnID = kStart+1 ; btnID < kLast ; btnID++)
{
if(fAButton[btnID])
{
fAButton[btnID] ->Connect(“Clicked()”,“GUI”,this,“DrawHist()”);

  if(btnID<kLastFo) 
    fFastOrGroup  ->AddFrame(fAButton[btnID],new TGLayoutHints(kLHintsExpandX,5,5,0,0)); 
  else
    fHitsGroup    ->AddFrame(fAButton[btnID],new TGLayoutHints(kLHintsExpandX,5,5,0,0)); 
} // if
else printf("no button with ID %i \n",btnID);

} // for

upperGroup ->AddFrame(fFastOrGroup);
upperGroup ->AddFrame(fHitsGroup);

// GENERAL HISTOGRAMS
TGCompositeFrame *dataFormatGroup = new TGCompositeFrame(fCom4,60,20,kVerticalFrame);
fAButton[kDataFormat] = new TGTextButton(dataFormatGroup,“Data Format”,kLast);
fAButton[kDataFormat] ->Connect(“Clicked()”,“GUI”,this,“DrawHist()”);
dataFormatGroup->AddFrame(fAButton[kDataFormat],new TGLayoutHints(kLHintsExpandX,5,5,0,0));

fCom4 ->AddFrame(upperGroup,new TGLayoutHints(kLHintsTop,5, 0, 5, 5));
fCom4 ->AddFrame(dataFormatGroup,new TGLayoutHints(kLHintsBottom,5, 0, 20, 5));

TGCompositeFrame *genericGroup = new TGCompositeFrame(fCom5,60,20,kVerticalFrame);

fAButton[kHitMultiplicity] = new TGTextButton(genericGroup,“Hit Multiplicity”,kHitMultiplicity);
fAButton[kHitMultiplicity] ->Connect(“Clicked()”,“GUI”,this,“DrawHist()”);
genericGroup ->AddFrame(fAButton[kHitMultiplicity],new TGLayoutHints(kLHintsExpandX,5,5,0,0));
fCom5 ->AddFrame(genericGroup,new TGLayoutHints(kLHintsTop,5, 0, 5, 5));

} // GUI::CreateDrawButtons

//===============================
void GUI::BuildGUI(){
//===============================
// Puts all frames together.
//===============================

// LEFT SIDE
TGLayoutHints *layout = new TGLayoutHints(kLHintsCenterX|kLHintsCenterY|kLHintsLeft|kLHintsTop,0,0,0,0);
fCom3 ->AddFrame(fHor1,layout);
fCom3 ->AddFrame(fHor2,layout);
fCom3 ->AddFrame(fHor3,layout);
fCom3 ->AddFrame(fTabType,layout);
fCom1 ->AddFrame(fCom3,new TGLayoutHints(kLHintsLeft|kLHintsTop|kFixedSize,0,0,0,0));

AddFrame(fCom1, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY|kLHintsTop,0,0,0,0));
} // GUI::BuildGUI

//===============================
void GUI::SelectEq(){
//===============================
// Deals with selected equipment.
//===============================

// FIND SELECTED BUTTON AND ROW
TGButton *btn = (TGButton *) gTQSender;
Int_t Eq = btn->WidgetId(); // selected button/equipment

// DESELECT THE OTHER BUTTON IF DIFFERENT AND STORE SELECTION
if( fCurrentEq != Eq )
{
fAButton[fCurrentEq]->SetState(kButtonUp,kFALSE);
fCurrentEq = Eq;
} // if

cout << "SELECT!!! fEq = " << Eq << endl;

if(Eq < kDDL + 1)
fDrawAllEq = kFALSE;
else
fDrawAllEq = kTRUE;

cout << "SELECT!!! fDrawAllEq = " << fDrawAllEq << endl;

} // GUI::SelectEq

//===============================
void GUI::SelectHs(){
//===============================
// Deals with selected half stave.
//===============================

// FIND SELECTED BUTTON AND ROW
TGButton *btn = (TGButton *) gTQSender;
Int_t Hs = btn->WidgetId() - kDDL; // selected button/half stave

cout << "idButton = " << Hs << endl;

// DESELECT THE OTHER BUTTON IF DIFFERENT
if( fCurrentHs != Hs )
{
fAButton[fCurrentHs+kDDL]->SetState(kButtonUp,kFALSE);
fCurrentHs = Hs;
} // if

if(Hs < kNHS)
fDrawAllHs = kFALSE;
else
fDrawAllHs = kTRUE;

} // GUI::SelectHs[/code]

Eventually I solved this problem by just putting the buttons directly in my main frame, without using a button group.

I would like to mention here that I also fixed some other problems in my macro by “playing around” with the order of definitions of TObjects. I am not sure why this is important, but it seems the order matters if you want a stable ROOT macro.

Hi Marco,

I have no problem with your code and svn trunk verion of ROOT, after fixing the following error:
Array index out of range fAButton[kRatio] -> [46] valid upto fAButton[33]

Cheers, Bertrand.

Hi Marco,

After playing a bit with your code, I managed to reproduce the problem and located its origin.
You have to make sure the array index is valid before using it, like this:

  // DESELECT THE OTHER BUTTON IF DIFFERENT AND STORE SELECTION
  if( fCurrentEq != Eq )
  {
    if (fCurrentEq != -1) fAButton[fCurrentEq]->SetState(kButtonUp,kFALSE);
    fCurrentEq = Eq;
  } // if
...
  // DESELECT THE OTHER BUTTON IF DIFFERENT
  if( fCurrentHs != Hs )
  {
    if (fCurrentHs != -1) fAButton[fCurrentHs+kDDL]->SetState(kButtonUp,kFALSE);
    fCurrentHs = Hs;
  } // if

(as fCurrentEq and fCurrentHs are initialized at -1)

Cheers, Bertrand.

Thank you!