TGListBox inside TGCanvas causes scrollbars


ROOT Version: 6.16/00
Platform: Ubuntu 18.04
Compiler: gcc 7.3.0


TGListBox widget placed inside a TGCanvas container with kLHintsExpandX and or kLHintsExpandY does not scale down when resizing the window (only scales up). This causes TGCanvas to show scrollbars. Here is a minimal example that demonstrates the problem: https://gist.github.com/petrstepanov/551a286cf6d15d808d0105b6b161f4be

P.S.: other widgets (tried TGLabel and TGCompositeFrame) with kLHintsExpandX kLHintsExpandY layout hints scale correctly inside TGCanvas.

canvas-issue-2

Hi,

The purpose of the TGCanvas is precisely to have scrollbars. Why do you need a TGCanvas if you don’t want them? You can simply use this code:

   TGCompositeFrame* container = new TGCompositeFrame(this, 10, 10, kOwnBackground);
   container->SetBackgroundColor(TColor::Number2Pixel(kGray+1));
   AddFrame(container, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 10, 10, 10, 10));

Or did I miss something?

Cheers, Bertrand.

Hi Bertrand. indeed TGCanvas is designed to have scrollable content inside of it. Scrollbars should appear when width or height of the canvas is less than the width/height of the child content inside it.

But if child widget’s dimensions are less or equal to the TGCanvas, scrollbars should never appear. In the example above child widget is expanded inside the Canvas container. So its width and height always equal to parent’s container. So scrollbars should never show up. Indeed, when scaling window up everything works as intended. But when scaling it down, child contents does not shrink back. Problem occurs if child widget is TGListBox. I recorded screencast that demonstrates the problem. Here is the link: https://mega.nz/#!8YlkWAbS!FdQhyaxVN5zhOoQqqm1F84HGpy9Kixy5C01xaddNe3Y

Yes, I understood your issue. I can provide a solution, but I was wondering why you need a TGCanvas…

In particular, my problem is following. I’m using TGListBox as one of the child widgets inside a TGShutter. TGShutter utilizes TGCanvas to scroll content inside its TGShutterItem’s. So same issue is observed here (see screencast https://mega.nz/#!gM92nQjD!MYHckfUINl_mMdTYE98dfZl5DuZ_SRMGZpwagK0a6TI). The original Gist example just narrows the problem down to a minimal piece of code.

OK, I see, there is no easy solution, but using signal/slots to resize the TGListBox when the TGCanvas gets resized could be one possible workaround

For example:

#include <TGClient.h>
#include <TGCanvas.h>
#include <TGListBox.h>
#include <TGFrame.h>

class MyMainFrame : public TGMainFrame {
protected:

   TGListBox* listBox;

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

   void    HandleConfigure(Event_t *event);

   ClassDef(MyMainFrame, 0)
};

MyMainFrame::MyMainFrame(const TGWindow *p, UInt_t w, UInt_t h) : TGMainFrame(p, w, h) {
   // Create canvas with white background
   TGCanvas* canvas = new TGCanvas(this);
   TGCompositeFrame* container = new TGCompositeFrame(canvas->GetViewPort(), 10, 10, kOwnBackground);
   container->SetBackgroundColor(TColor::Number2Pixel(kGray+1));
   canvas->SetContainer(container);
   AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 10, 10, 10, 10));
   canvas->GetViewPort()->Connect("ProcessedConfigure(Event_t*)", "MyMainFrame", this, "HandleConfigure(Event_t*)");

   // Add child ListBox (breaks layout - scrollbars appear when decreasing window size)
   listBox = new TGListBox(container);
   container->AddFrame(listBox, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY, 20, 20, 20, 20));

   SetWindowName("TGCanvas issue");
   SetWMSizeHints(300, 300, 1000, 1000, 1, 1);
   MapSubwindows();
   Resize(GetDefaultSize());
   MapWindow();
}

//______________________________________________________________________________
void MyMainFrame::HandleConfigure(Event_t *event)
{
   // This event is generated when the frame is resized.
   listBox->Resize(event->fWidth-40, event->fHeight-40); // size - layout margins
   Layout();
}

MyMainFrame::~MyMainFrame(){
   Cleanup();
}

void canvasResize(){
   new MyMainFrame(gClient->GetRoot(), 300, 300);
}
1 Like

Thanks for pointing out the workaround. Do you think its reasonable to repost the issue to Jira? From my perspective this should work correctly “out of the box”.

You’re welcome, and no, it would be useless to open a Jira ticket because it’s a conceptual issue, and it cannot be solved in any reasonable way…

This is a little frustrating of course. Especially when implementing conventional MVC/MVP patterns to design the UI. Child widget can be a part of on View, that has no clue about the parent View at all. Then implementing this signal/slot workarounds is considered sort of a hack.

At the same time I totally understand that it can require a lot of efforts to fix “conceptual issues” like this. Thanks for your help Bertrand!

1 Like

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