Precisely position TGDoubleHSlider in frame

Hello,

I am trying to carefully position a TGDoubleHSlider in a GUI I am making so that it correctly spans the width of the axis displayed in the TCanvas shown above.

I create a containing horizontal frame, and have determined the spacing to the left and the right of the slider that I need, and the width of the slider, in pixels. But my efforts to use a TGLayoutHints doesn’t seem to be working. I tried:

hframe->AddFrame(slider, new TGLayoutHints(kLHintsCenterX,leftSpace,rightSpace,0,0));

But the slider always sits against the left hand edge of the frame (the containing frame, hframe, spans the whole width of the main frame, it was just added to the main frame in a standard way).

I have been able to do

slider->SetW(sliderWidth);

and the slider does appear the correct width, it’s just stuck against the left edge.

How can I create some specific amount of whitespace to the left of the slider widget?

Thanks!
Will

Hi,

First of all, if you position the slider below your canvas, you should probably use a vertical frame as container…
Then, if you still cannot solve your issue, could you provide a short running macro showing what you’re trying to do, so we can make it working the way you want.

Cheers, Bertrand.

I assume I would only need a verticle frame if the canvas and the slider are in the same frame, but I’ve so far just been adding the canvas to the main frame and then making a horizontal frame to add to the main frame, which seems to automatically get placed below the canvas.

Anyway, here’s an example of what I am trying to do. I want to be able to update the position and size of the slider when a certain method is called, hence why I have split things up…

#include <TGClient.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>
#include <TGDoubleSlider.h>
#include <TGFrame.h>


class MyMainFrame {
   RQ_OBJECT("MyMainFrame")
private:
   TGMainFrame *fMain;
   TRootEmbeddedCanvas *fEcanvas;
   TGDoubleHSlider* integralSlider;
   TGLayoutHints* sliderLayout;
public:
   MyMainFrame();
   virtual ~MyMainFrame();

   void DoDraw();
};

MyMainFrame::MyMainFrame() {
   const TGWindow *p = gClient->GetRoot();
   fMain = new TGMainFrame(p,515,200,kFixedWidth);

   fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,515,500);
   fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY,0,0,0,0));
   TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,515,10);

   integralSlider = new TGDoubleHSlider(hframe,100,kDoubleScaleNo,0);
   integralSlider->SetRange(0,1);integralSlider->SetPosition(0.25,0.75);

   sliderLayout = new TGLayoutHints(kLHintsCenterX,100,100,3,4);

   hframe->AddFrame(integralSlider,sliderLayout);
   fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX,0,0,0,0));

   fMain->SetWindowName("My frame");
   fMain->MapSubwindows();
   fMain->Resize(fMain->GetDefaultSize());
   fMain->MapWindow();
}

MyMainFrame::~MyMainFrame() {
   fMain->Cleanup();delete fMain;
}

MyMainFrame::DoDraw() {
   //draw a dummy histogram 
   TH1D* myHist = new TH1D("myHist","myHist",10,0,10);

   fEcanvas->GetCanvas()->SetRightMargin(0.5);
   fEcanvas->GetCanvas()->cd();

   myHist->Draw();

   double canvasWidth = fEcanvas->GetCanvas()->GetWw();
   double slideFactor = 1.;
   double slideLeftFactor = 0.;
   slideLeftFactor = fEcanvas->GetCanvas()->GetLeftMargin();
   slideFactor = 1. - fEcanvas->GetCanvas()->GetLeftMargin() - fEcanvas->GetCanvas()->GetRightMargin();

   sliderLayout->SetPadLeft(canvasWidth*slideLeftFactor);
   sliderLayout->SetPadRight(canvasWidth*(1.-slideFactor-slideLeftFactor));

   integralSlider->SetWidth(canvasWidth*slideFactor);

}

void guiExample() {
   MyMainFrame* f = new MyMainFrame();

   f->DoDraw();
}

Hi Will,

Could you try using kLHintsExpandX with the frame and the slider? (specifying the left and right margins should work)

Cheers, Bertrand.

Doesn’t seem to have worked. The slider does change its size (but not straight away, I have to click on the window???). But the slider position refuses to shift… it’s all dependent on the Left padding, but no matter what I change this to, it remains at wherever it is I placed it first.

Thanks,
Will

Hi Will,

Could you try the code below and let me know?

[code]#include <TGClient.h>
#include <TRootEmbeddedCanvas.h>
#include <RQ_OBJECT.h>
#include <TGDoubleSlider.h>
#include <TGFrame.h>

class MyMainFrame {
RQ_OBJECT(“MyMainFrame”)
private:
TGMainFrame fMain;
TRootEmbeddedCanvas fEcanvas;
TGDoubleHSlider
integralSlider;
TGLayoutHints
sliderLayout;
TH1D* myHist;
public:
MyMainFrame();
virtual ~MyMainFrame();

void DoDraw();
};

MyMainFrame::MyMainFrame() : myHist(0) {
const TGWindow *p = gClient->GetRoot();
fMain = new TGMainFrame(p,515,200,kFixedWidth);

fEcanvas = new TRootEmbeddedCanvas(“Ecanvas”,fMain,515,500);
fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY,0,0,0,0));
TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,515,10);

integralSlider = new TGDoubleHSlider(hframe,100,kDoubleScaleNo,0);
integralSlider->SetRange(0,1);
integralSlider->SetPosition(0.25,0.75);

sliderLayout = new TGLayoutHints(kLHintsExpandX,100,100,3,4);

hframe->AddFrame(integralSlider,sliderLayout);
fMain->AddFrame(hframe, new TGLayoutHints(kLHintsExpandX,0,0,0,0));

fMain->Connect(“ProcessedConfigure(Event_t*)”, “MyMainFrame”, this, “DoDraw()”);

fMain->SetWindowName(“My frame”);
fMain->MapSubwindows();
fMain->Resize(fMain->GetDefaultSize());
fMain->MapWindow();
}

MyMainFrame::~MyMainFrame() {
fMain->Cleanup();delete fMain;
}

void MyMainFrame::DoDraw() {
//draw a dummy histogram

if (!myHist)
myHist = new TH1D(“myHist”,“myHist”,10,0,10);

fEcanvas->GetCanvas()->SetRightMargin(0.5);
fEcanvas->GetCanvas()->cd();

myHist->Draw();

double canvasWidth = fEcanvas->GetCanvas()->GetWw();
double slideFactor = 1.;
double slideLeftFactor = 0.;
slideLeftFactor = fEcanvas->GetCanvas()->GetLeftMargin();
slideFactor = 1. - fEcanvas->GetCanvas()->GetLeftMargin() - fEcanvas->GetCanvas()->GetRightMargin();

sliderLayout->SetPadLeft(canvasWidthslideLeftFactor);
sliderLayout->SetPadRight(canvasWidth
(1.-slideFactor-slideLeftFactor));

integralSlider->SetWidth(canvasWidth*slideFactor);
fMain->Layout();
}

void guiExample() {
MyMainFrame* f = new MyMainFrame();
f->DoDraw();
}
[/code]
Cheers, Bertrand.

Aha. This seems to be working for me now thanks!

So the two things you changed were:

a call to fMain->Layout(); - I assume this tells the frame to “refresh” its layout, yes?

a Connect to ProcessedConfigure… what is this for? When is it triggered?

Thanks!

[quote=“will_cern”]a call to fMain->Layout(); - I assume this tells the frame to “refresh” its layout, yes?[/quote]Yes, it tells the main frame to recompute its layout (rearrange sub-frames)

[quote=“will_cern”]a Connect to ProcessedConfigure… what is this for? When is it triggered?[/quote]It is triggered when the size of the (main) frame changed, so connecting to this signal allows to recalculate the margins and then re-apply the layout.

Cheers, Bertrand.