Control the relative size of widgets in GUI


ROOT Version: 6.20/04
Platform: Fedora 31
Compiler: gcc version 9.3.1 20200317 (Red Hat 9.3.1-1) (GCC)


Dear co-rooters,

I am trying to build a simple GUI in which the 3 quarters of the window will be occupied by a canvas and the one quarter will be button and user input values.

To do that I decided to divide a main TGMainFrame in two TGVerticalFrames, left and right. The right one will contain the TRootEmbeddedCanvas whereas the left one will be composed of TGGroupFrames , each on of those will have TGNumberEntry and TGTextButtons for user interaction with the GUI.

One of the problems that I am facing is that I cannot seem to be able to specify the dimensions of the widgets. Whatever I do, even using Resize() or kFitWidth | kFitHeight, the widget always take up the full dimensions that are provided to them i.e. 50% of the window’s width for the 2 TGVerticalFrames, 25% of the window’s height for the TGGroupFrames in the left frame etc, as shown in the following picture.

Imgur

Is there a way to specify the space each widget will take?

Thanks in advnace!

The code to reproduce what I am getting is the following.

#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include "TGNumberEntry.h"
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>

class MainFrame {
   RQ_OBJECT("MainFrame")
private:
   TGMainFrame         *fr_main;
   TRootEmbeddedCanvas *emb_canvas;
   TGGroupFrame *fr_runs, *fr_events, *fr_saves;
   TGNumberEntry *entry_runs, *entry_events;
   TGTextButton *but_runs_next, *but_runs_previous;
   TGTextButton *but_events_next, *but_events_previous;
   TGTextButton *but_save_ascii, *but_save_histo, *but_save_canvas;
   TGTextButton *but_exit, *but_draw;
public:
   MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
   virtual ~MainFrame();
   void draw();
};

MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height) {

    TGFont *ufont = gClient->GetFont("-*-helvetica-bold-r-*-*-34-*-*-*-*-*-*-*");
    ULong_t ucolor;
    TGGC   *uGC;

   // Create a main frame
   fr_main = new TGMainFrame(p, width, height, kMainFrame     |
                                               kRaisedFrame   | 
                                               kOwnBackground | 
                                               kLHintsExpandX | 
                                               kLHintsExpandY | 
                                               kHorizontalFrame
                            );
   
   //---- Left Frame - for buttons and user values
   TGVerticalFrame *fr_left  = new TGVerticalFrame(fr_main, 0.25*width, height, kChildFrame, kCyan); 
   
   // The 1st grouped frame - runs
   TGGroupFrame *fr_runs = new TGGroupFrame(fr_left, "Run", kVerticalFrame, uGC->GetGC(), ufont->GetFontStruct() );
   TGNumberEntry *box_run = new TGNumberEntry(fr_runs, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_runs->AddFrame(box_run, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_runs, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));

   
   // The 2nd grouped frame - events
   TGGroupFrame *fr_event = new TGGroupFrame(fr_left, "Event", kVerticalFrame, uGC->GetGC(), ufont->GetFontStruct() );
   TGNumberEntry *box_event = new TGNumberEntry(fr_event, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_event->AddFrame(box_event, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_event, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
   
   // The 3rd grouped frame - Drawing the signal
   TGGroupFrame *fr_draw = new TGGroupFrame(fr_left, "Draw", kHorizontalFrame, uGC->GetGC(), ufont->GetFontStruct() );
   TGTextButton *but_draw_histo = new TGTextButton(fr_draw,"&Histo");
   TGTextButton *but_draw_line = new TGTextButton(fr_draw,"&Line");
   TGTextButton *but_draw_line_points = new TGTextButton(fr_draw,"&Line - Points");
   fr_draw->AddFrame(but_draw_histo, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line_points, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_draw, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
   
   
    // Test button to see the structure
   TGTextButton *draw = new TGTextButton(fr_left,"&Draw");
   draw->Connect("Clicked()", "MainFrame", this, "draw()");
   fr_left->AddFrame(draw, new TGLayoutHints(kLHintsCenterX, 100, 100, 100, 100) );                                            
   fr_main->AddFrame(fr_left , new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
   
   
   //---- Right frame - for the canvas
   TGVerticalFrame *fr_right = new TGVerticalFrame(fr_main, 0.75*width, height, kChildFrame, kRed);
   emb_canvas = new TRootEmbeddedCanvas("canvas", fr_right, 130, 180);
   fr_right->AddFrame(emb_canvas, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
   
   fr_main->AddFrame(fr_right , new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,10));

    // Set a name to the main frame
   fr_main->SetWindowName("Signal viewer");
   
   // Map all subwindows of main frame
   fr_main->MapSubwindows();
   
   // Initialize the layout algorithm
   fr_main->Resize(fr_main->GetDefaultSize());
   
   // Map main frame
   fr_main->MapWindow();

}

void MainFrame::draw() {
   // 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
   fr_main->Cleanup();
   delete fr_main;
}

void test_beta() {
   // Popup the GUI...
   new MainFrame(gClient->GetRoot(), 500, 500);
}

First, your code is over-complicated, and crash on Windows… But the first thing I can tell is that if you use kLHintsExpandX everywhere, the widgets will share the full width. So using this:

fr_main->AddFrame(fr_left , new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 10,10,10,10));

Will already change the behaviour…

Here is an example with your code, slightly modified:

#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TGNumberEntry.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>

class MainFrame : public TGMainFrame {
private:
   TRootEmbeddedCanvas *emb_canvas;
   TGGroupFrame *fr_runs, *fr_events, *fr_saves;
   TGNumberEntry *entry_runs, *entry_events;
   TGTextButton *but_runs_next, *but_runs_previous;
   TGTextButton *but_events_next, *but_events_previous;
   TGTextButton *but_save_ascii, *but_save_histo, *but_save_canvas;
   TGTextButton *but_exit, *but_draw;
public:
   MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
   virtual ~MainFrame();
   void draw();
};

MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height) :
   TGMainFrame(p, width, height, kMainFrame|kHorizontalFrame)
{
   //---- Left Frame - for buttons and user values
   TGVerticalFrame *fr_left  = new TGVerticalFrame(this, 0.25*width, height, kChildFrame, kCyan); 
   
   // The 1st grouped frame - runs
   TGGroupFrame *fr_runs = new TGGroupFrame(fr_left, "Run", kVerticalFrame);
   TGNumberEntry *box_run = new TGNumberEntry(fr_runs, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_runs->AddFrame(box_run, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_runs, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));

   
   // The 2nd grouped frame - events
   TGGroupFrame *fr_event = new TGGroupFrame(fr_left, "Event", kVerticalFrame);
   TGNumberEntry *box_event = new TGNumberEntry(fr_event, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_event->AddFrame(box_event, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_event, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // The 3rd grouped frame - Drawing the signal
   TGGroupFrame *fr_draw = new TGGroupFrame(fr_left, "Draw", kHorizontalFrame);
   TGTextButton *but_draw_histo = new TGTextButton(fr_draw,"&Histo");
   TGTextButton *but_draw_line = new TGTextButton(fr_draw,"&Line");
   TGTextButton *but_draw_line_points = new TGTextButton(fr_draw,"&Line - Points");
   fr_draw->AddFrame(but_draw_histo, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line_points, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_draw, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   
    // Test button to see the structure
   TGTextButton *draw = new TGTextButton(fr_left,"&Draw");
   draw->Connect("Clicked()", "MainFrame", this, "draw()");
   fr_left->AddFrame(draw, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 10, 10, 10, 10) );                                            
   AddFrame(fr_left , new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 10,10,10,10));
   
   
   //---- Right frame - for the canvas
   TGVerticalFrame *fr_right = new TGVerticalFrame(this, 0.75*width, height, kChildFrame, kRed);
   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("Signal viewer");
   
   // Map all subwindows of main frame
   MapSubwindows();
   Layout();
   
   // Initialize the layout algorithm
   Resize(GetDefaultSize());
   
   // Map main frame
   MapWindow();

}

void MainFrame::draw() {
   // 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 test_beta() {
   // Popup the GUI...
   new MainFrame(gClient->GetRoot(), 800, 500);
}

Thank you very much for your reply!
Indeed adding kLHintsLeft | kLHintsExpandY improves things but still I cannot control the dimensions; they are somehow automatically calculated.

Imgur

Try with the code I sent, and then, just play with the parameters…

Ha ha ha
I was replying without noticing your reply!
Thank you very much!
I’ll have a look!

Something is strange.
I’m changing the width for instance of the left and right frames to 0.6 and 0.4 width of the window I’m still not able to control the width

Imgur

This is valid only once (at construction time). If you want to dynamically control the size, you have to react on the Resize event. I’ll take a look tomorrow

Oh I see.
Thank you very much for your time and help!

Try this (quick attempt):

#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TGNumberEntry.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>

class MainFrame : public TGMainFrame {
private:
   TRootEmbeddedCanvas *emb_canvas;
   TGVerticalFrame *fr_left;
   TGGroupFrame *fr_runs, *fr_events, *fr_saves;
   TGNumberEntry *entry_runs, *entry_events;
   TGTextButton *but_runs_next, *but_runs_previous;
   TGTextButton *but_events_next, *but_events_previous;
   TGTextButton *but_save_ascii, *but_save_histo, *but_save_canvas;
   TGTextButton *but_exit, *but_draw;
public:
   MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
   Bool_t HandleConfigureNotify(Event_t *);
   virtual ~MainFrame();
   void draw();
};

MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height) :
   TGMainFrame(p, width, height, kMainFrame|kHorizontalFrame)
{
   //---- Left Frame - for buttons and user values
   fr_left  = new TGVerticalFrame(this, 0.25*width, height, kChildFrame|kFixedSize, kCyan); 
   
   // The 1st grouped frame - runs
   fr_runs = new TGGroupFrame(fr_left, "Run", kVerticalFrame);
   TGNumberEntry *box_run = new TGNumberEntry(fr_runs, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_runs->AddFrame(box_run, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_runs, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));

   
   // The 2nd grouped frame - events
   TGGroupFrame *fr_event = new TGGroupFrame(fr_left, "Event", kVerticalFrame);
   TGNumberEntry *box_event = new TGNumberEntry(fr_event, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_event->AddFrame(box_event, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_event, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   // The 3rd grouped frame - Drawing the signal
   TGGroupFrame *fr_draw = new TGGroupFrame(fr_left, "Draw", kHorizontalFrame);
   TGTextButton *but_draw_histo = new TGTextButton(fr_draw,"&Histo");
   TGTextButton *but_draw_line = new TGTextButton(fr_draw,"&Line");
   TGTextButton *but_draw_line_points = new TGTextButton(fr_draw,"&Line - Points");
   fr_draw->AddFrame(but_draw_histo, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line_points, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_draw, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
   
   
    // Test button to see the structure
   TGTextButton *draw = new TGTextButton(fr_left,"&Draw");
   draw->Connect("Clicked()", "MainFrame", this, "draw()");
   fr_left->AddFrame(draw, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 10, 10, 10, 10) );                                            
   AddFrame(fr_left , new TGLayoutHints(kLHintsLeft | kLHintsTop, 10,10,10,10));
   
   
   //---- Right frame - for the canvas
   TGVerticalFrame *fr_right = new TGVerticalFrame(this, 0.75*width, height, kChildFrame, kRed);
   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("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_left->Resize(0.25*w, h);
   fr_left->Layout();
   return TGMainFrame::HandleConfigureNotify(event);
}

void MainFrame::draw() {
   // 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 test_beta() {
   // Popup the GUI...
   new MainFrame(gClient->GetRoot(), 800, 500);
}
1 Like

Wow!
It seems that it’s working!
I’ll try it extensively and I’ll accept is a solution!
Thank you so much!!

The good thing is that I believe I understand how the resizing works: You should explicitly Resize"() any structure that needs to be done so as you did

fr_runs->Resize(0.25*w, 0.2*h);
fr_runs->Layout();
   
fr_events->Resize(0.25*w, 0.2*h);
fr_events->Layout();
   
fr_draw->Resize(0.25*w, 0.2*h);
fr_draw->Layout();
   
fr_save->Resize(0.25*w, 0.2*h);
fr_save->Layout();
   
fr_left->Resize(0.25*w, h);
fr_left->Layout();

Now however I have another issue: When trying to change the attributes of the widgets, I get a break segmentation violation. for instance changing the font of the title of a TGGroupFrame or a TGTextButton by doing test->SetFont(60); produces this stack of errors

===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x000014db91fe0eda in waitpid () from /lib64/libc.so.6
#1  0x000014db91f5c757 in do_system () from /lib64/libc.so.6
#2  0x000014db9275f065 in TUnixSystem::StackTrace() () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#3  0x000014db9275c5dc in TUnixSystem::DispatchSignals(ESignals) () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#4  <signal handler called>
#5  0x000014db8180c4a4 in XftCharIndex () from /lib64/libXft.so.2
#6  0x000014db81807421 in XftDrawString8 () from /lib64/libXft.so.2
#7  0x000014db8c459666 in TGX11TTF::DrawString(unsigned long, unsigned long, int, int, char const*, int) () from /home/astamato/Utilities/ROOT/build/lib/libGX11TTF.so
#8  0x000014db824b218a in TGFont::DrawChars(unsigned long, unsigned long, char const*, int, int, int) const () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#9  0x000014db824b23b2 in TGTextLayout::DrawText(unsigned long, unsigned long, int, int, int, int) const () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#10 0x000014db82464787 in TGTextButton::DoRedraw() () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#11 0x000014db8247fec7 in TGClient::DoRedraw() () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#12 0x000014db82480d90 in TGClient::ProcessOneEvent() () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#13 0x000014db82480e0b in TGClient::HandleInput() () from /home/astamato/Utilities/ROOT/build/lib/libGui.so
#14 0x000014db9275ce98 in TUnixSystem::DispatchOneEvent(bool) () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#15 0x000014db9268f794 in TSystem::InnerLoop() () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#16 0x000014db9268e5bf in TSystem::Run() () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#17 0x000014db9262e20f in TApplication::Run(bool) () from /home/astamato/Utilities/ROOT/build/lib/libCore.so
#18 0x000014db929c41ac in TRint::Run(bool) () from /home/astamato/Utilities/ROOT/build/lib/libRint.so
#19 0x000000000040110a in main ()
===========================================================

Any idea? I can also create a new thread so things will be kept neat and tidy.

The above error was produced with the following code

#include <TGClient.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TRandom.h>
#include <TGButton.h>
#include <TGFrame.h>
#include <TGNumberEntry.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>

class MainFrame : public TGMainFrame {
private:
   TRootEmbeddedCanvas *emb_canvas;
   TGVerticalFrame *fr_left;
   TGGroupFrame *fr_runs, *fr_events, *fr_draw, *fr_save;
public:
   MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
   Bool_t HandleConfigureNotify(Event_t *);
   virtual ~MainFrame();
   void draw();
};

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

    //TGFont *ufont = gClient->GetFont("-*-helvetica-bold-r-*-*-34-*-*-*-*-*-*-*");
    //TGGC   *uGC;

   //---- Left Frame - for buttons and user values
   fr_left  = new TGVerticalFrame(this, 0.3*width, height, kChildFrame|kFixedSize, kCyan); 
   
   // The 1st grouped frame - runs
   fr_runs = new TGGroupFrame(fr_left, "Run", kChildFrame | kVerticalFrame|kFixedSize);
   TGNumberEntry *box_run = new TGNumberEntry(fr_runs, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_runs->AddFrame(box_run, new TGLayoutHints(kLHintsLeft | kLHintsTop, 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);
   TGNumberEntry *box_event = new TGNumberEntry(fr_events, (Double_t) 0, 10, -1, (TGNumberFormat::EStyle) 5);
   fr_events->AddFrame(box_event, new TGLayoutHints(kLHintsLeft | kLHintsTop, 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);
   TGTextButton *but_draw_histo = new TGTextButton(fr_draw,"&Histo");
   TGTextButton *but_draw_line = new TGTextButton(fr_draw,"&Line");
   TGTextButton *but_draw_line_points = new TGTextButton(fr_draw,"&Line - Points");
   fr_draw->AddFrame(but_draw_histo, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_draw->AddFrame(but_draw_line_points, new TGLayoutHints(kLHintsLeft | kLHintsTop, 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);
   TGTextButton *but_save_histo = new TGTextButton(fr_save,"&Histo");
   TGTextButton *but_save_canvas = new TGTextButton(fr_save,"&Canvas");
   TGTextButton *but_save_ascii = new TGTextButton(fr_save,"&Ascii");
   fr_save->AddFrame(but_save_histo, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_save->AddFrame(but_save_canvas, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_save->AddFrame(but_save_ascii, new TGLayoutHints(kLHintsLeft | kLHintsTop, 2, 2, 2, 2) );
   fr_left->AddFrame(fr_save, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
  
   // Test button to see the structure
   TGTextButton *test = new TGTextButton(fr_left,"&Test");
   test->Connect("Clicked()", "MainFrame", this, "draw()");
   //test->SetFont(60);//<----- Here's where it crashes
   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)");
   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, kRed);
   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("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.2*h);
   fr_runs->Layout();
   
   fr_events->Resize(0.25*w, 0.2*h);
   fr_events->Layout();
   
   fr_draw->Resize(0.25*w, 0.2*h);
   fr_draw->Layout();
   
   fr_save->Resize(0.25*w, 0.2*h);
   fr_save->Layout();
   
   fr_left->Resize(0.25*w, h);
   fr_left->Layout();
   
   return TGMainFrame::HandleConfigureNotify(event);
}

void MainFrame::draw() {
   // 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 test_forum() {
   // Popup the GUI...
   new MainFrame(gClient->GetRoot(), 800, 500);
}

First, you don’t need to set the fixed size for all widgets/frames inside fr_left, you can keep their automatic layout, only the parent frame needs to be manually adjusted. The solution I sent should be sufficient (or did I miss something?). I.e. this is enough for resizing the frame and the fr_left->Layout() call automatically adjust the child frames/widgets, if you remove their kFixedSize flag:

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));

   if ((event->fWidth != fWidth) || (event->fHeight != fHeight)) {
      UInt_t w = event->fWidth-20;
      UInt_t h = event->fHeight-20;
      fr_left->Resize(0.3*w, h);
      fr_left->Layout();
   }
   return TGMainFrame::HandleConfigureNotify(event);
}

If it doesn’t, please let me know…

Please take a look at the TGTextButton::SetFont() methods. So either something like:

   const TGFont *font = gClient->GetFont("-*-helvetica-bold-r-*-*-34-*-*-*-*-*-*-*");
   FontStruct_t buttonFont = font->GetFontStruct();
   test->SetFont(buttonFont);

or even simpler:

   test->SetFont("-*-helvetica-bold-r-*-*-34-*-*-*-*-*-*-*");

Thank you very much for your help!
Changing the fonts works!

Concerning the first part, say I want to change the height of each TGGroupFrame so that it occupies 20% of the screen’s height. How to do that? I tried adding these two lines for each TGGroupFrame in the Bool_t MainFrame::HandleConfigureNotify(Event_t *event) function.

fr_events->Resize(0.25*w, 0.2*h);
fr_events->Layout();

It works but I don’t know if this is the more efficient way to do it.

OK, right, if you need to control the size of every widget, then it makes sense…

Oh that’s great!!
I wish there was a way to specify the dimensions in the constructor unless there is and I’m not aware of it.

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