Search code examples
qtqgraphicsviewqscrollarea

QScrollArea not respecting contentMargins setting


QScrollArea, for some reason, is ignoring the contentMargins setting when I set QGraphicsView as its widget. Looking at the snippet below, can someone please tell if I'm doing something wrong or it could be a bug in the SDK?

Snippet 1 (works perfect):

QWidget *appWindow = new QWidget;

QScrollArea *sa = new QScrollArea(appWindow);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setContentMargins(50, 50, 50, 50);

QWidget *widgetToScroll = new QWidget(sa);
widgetToScroll->resize(5000, 5000);
sa->setWidget(widgetToScroll);

QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
appWindowLayout->addWidget(sa);
appWindow->setLayout(appWindowLayout);

appWindow->show();

Snippet 2 (It's like setContentMargins() call is ignored completely):

QWidget *appWindow = new QWidget;

QScrollArea *sa = new QScrollArea(appWindow);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setContentMargins(50, 50, 50, 50);

QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(sa), sa);
widgetToScroll->setAlignment(Qt::AlignLeft | Qt::AlignTop);
widgetToScroll->resize(5000, 5000);
sa->setWidget(widgetToScroll);

QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
appWindowLayout->addWidget(sa);
appWindow->setLayout(appWindowLayout);

appWindow->show();

Thanks.


Solution

  • It looks like you are confusing the structure of how to nest a QGraphicsView and a QGraphicsScene. (Maybe it was just a typo?)

        QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(sa), sa);
    

    should be changed to

        QGraphicsView *widgetToScroll = new QGraphicsView(new QGraphicsScene(), sa);
    

    or

        QGraphicsView *widgetToScroll = new QGraphicsView();
        sa->setWidget(widgetToScroll);
    

    When you add a QWidget to a layout, you change the widget's parent. When you set a widget (or QGraphicsView) to a QScrollArea, you change that widget's parent. See Object Trees & Ownership for more information. So if you wanted to set up your QGraphicsView inside a QScrollArea your code would look like this:

        QWidget *appWindow = new QWidget;
    
        QScrollArea *sa = new QScrollArea(); // No need to specify a parent here if
                                             // you add it to a layout later
        sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
        sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
        sa->setContentsMargins(50, 50, 50, 50);
    
        QGraphicsView *widgetToScroll = new QGraphicsView();
        widgetToScroll->setAlignment(Qt::AlignLeft | Qt::AlignTop);
        widgetToScroll->resize(5000, 5000);
        sa->setWidget(widgetToScroll); // This sets the parent for widgetToScroll
    
        QVBoxLayout *appWindowLayout = new QVBoxLayout();
        appWindowLayout->addWidget(sa); // This sets the parent for sa
        appWindow->setLayout(appWindowLayout); // This sets the parent for appWindowLayout
    
        appWindow->show();
    

    As a side note...

    When using QGraphicsViews with a QGraphicsScene, instead of setting the margins using a QScrollArea's setContentsMargins, I use the QGraphicsView automatic scrolling and just set the scene rect to have a larger margin that the size of my content like so:

        QWidget *appWindow = new QWidget;
    
        QGraphicsView *widgetToScroll = new QGraphicsView();
        QGraphicsScene *scene = new QGraphicsScene();
        scene->addRect(0,0, 5000, 5000);
    
        widgetToScroll->setSceneRect(-50,-50, 5050, 5050);
        widgetToScroll->setScene(scene);
    
        QVBoxLayout *appWindowLayout = new QVBoxLayout(appWindow);
        appWindowLayout->addWidget(widgetToScroll);
    
        appWindow->setLayout(appWindowLayout);
        appWindow->show();
    

    The QGraphicsView includes quite a bit more than just automatic scrolling when needed. You can resize everything inside of it and quite a bit more. It is great for 2D layouts, interactions and animations. See Qt's Graphics View Framework at http://doc.qt.io/qt-5/graphicsview.html for more information.

    Here is more information that may be useful when using margins and paddings: The Box Model used by QStyleSheets.