Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] How to place widgets in margins of a QSrollArea (or QAbstractScrollArea)?

[SOLVED] How to place widgets in margins of a QSrollArea (or QAbstractScrollArea)?

Scheduled Pinned Locked Moved General and Desktop
9 Posts 3 Posters 6.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    gkroeger
    wrote on last edited by
    #1

    This is probably simple, but I am stumped. I need to place rulers in the top and bottom margins of a scroll area. I have no problem with the top margin, but I cannot figure out how to get a widget placed in the bottom margin. I have tried using both QGridLayout and QVBoxLayout, but the bottom ruler end up near the middle of the ScrollArea viewport, not in the bottom margin?

    Here is some sample code:

    @
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    scrollArea = new ScrollAreaWithRulers(this);
    setCentralWidget(scrollArea);
    canvas = new Canvas();
    scrollArea->setWidget(canvas);
    scrollArea->addRulers();
    }@

    and:

    @#include "rulerscrollarea.h"

    ScrollAreaWithRulers::ScrollAreaWithRulers(QWidget *parent) :
    QScrollArea(parent)
    {
    setViewportMargins(0,30,0,30);
    topRuler = new Ruler();
    bottomRuler = new Ruler();
    }

    void ScrollAreaWithRulers::addRulers(){

    QVBoxLayout *layout = new QVBoxLayout();
    
    layout->addWidget(topRuler);
    layout->addWidget(viewport());
    layout->addWidget(bottomRuler);
    //layout->setRowStretch(1,1);
    
    setLayout(layout);
    

    }
    @

    The documentation for QAbstractScrollArea implies that this should be easier when it says:

    bq. Sets the margins around the scrolling area to left, top, right and bottom. This is useful for applications such as spreadsheets with "locked" rows and columns. The marginal space is is left blank; put widgets in the unused area.

    So, what is the right way to "put widgets in the unused area"? I am missing something obvious here.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      You have to position them manually and use the scroll area's resizeEvent()/scrollContentsBy() to adjust the placement as required. Take a look at the Code Editor Example, specifically CodeEditor::resizeEvent().
      http://qt-project.org/doc/qt-4.8/widgets-codeeditor.html

      1 Reply Last reply
      0
      • G Offline
        G Offline
        gkroeger
        wrote on last edited by
        #3

        @ChrisW67

        Thanks for the example to look at... I had pretty much arrived at the conclusion that I would have to do it manually by looking at the code for QTableView... but the CodeEditor example is easier to parse!

        Glenn

        1 Reply Last reply
        0
        • G Offline
          G Offline
          gkroeger
          wrote on last edited by
          #4

          Ok, in trying to follow the example of the "code editor" demo, I am now stumped by the refusal of a widget in the margin to move in response to its "scroll" method. Thinking that the problem might be with my ruler widget, I substituted a simple QLabel widget with the same result. The code is as follows:

          @#include "rulerscrollarea.h"

          RulerScrollArea::RulerScrollArea(QWidget *parent) :
          QScrollArea(parent)
          {
          setViewportMargins(80,30,0,0);
          //topRuler = new Ruler(this);
          label = new QLabel("Hello World",this);
          }

          void RulerScrollArea::scrollContentsBy(int dx, int dy){
          label->scroll(dx,0);
          QScrollArea::scrollContentsBy(dx,dy);
          std::cerr << "we're scrolling along \n";
          }

          void RulerScrollArea::resizeEvent(QResizeEvent *evt){
          QScrollArea::resizeEvent(evt);
          }
          @

          If I replace "scroll" with "move", the widget moves! This code works:

          @#include "rulerscrollarea.h"

          RulerScrollArea::RulerScrollArea(QWidget *parent) :
          QScrollArea(parent)
          {
          setViewportMargins(80,30,0,0);
          //topRuler = new Ruler(this);
          label = new QLabel("Hello World",this);
          rulerX = 0;
          }

          void RulerScrollArea::scrollContentsBy(int dx, int dy){
          //label->scroll(dx,0);
          rulerX += dx;
          label->move(rulerX,0);
          QScrollArea::scrollContentsBy(dx,dy);
          std::cerr << "we're scrolling along \n";
          }

          void RulerScrollArea::resizeEvent(QResizeEvent *evt){
          QScrollArea::resizeEvent(evt);
          }
          @

          So why won't these widgets respond to a scroll request?

          1 Reply Last reply
          0
          • A Offline
            A Offline
            alexisdm
            wrote on last edited by
            #5

            [quote author="ChrisW67" date="1353999614"]You have to position them manually[/quote]You can actually use a QLayout, because QScrollArea isn't using any. You have to specify the alignment to the addWidget function:
            @QVBoxLayout *layout = new QVBoxLayout(this);
            // to remove any margin around the layout
            layout->setContentsMargins(QMargins());
            layout->addWidget(topRuler, 0, Qt::AlignTop);
            layout->addWidget(bottomRuler, 0, Qt::AlignBottom);
            @
            I guess you wouldn't have to handle the resize event any more, only the scrolling.

            1 Reply Last reply
            0
            • G Offline
              G Offline
              gkroeger
              wrote on last edited by
              #6

              @alexisdm:

              Thanks... that does indeed fix the top and bottom... but the scroll method still doesn't move the widgets. I have to use the move method? Very puzzling. I can work around it with move, but would love to know why the scroll method works in the code editor example, but not here. BTW, I have tried it on both Windows and Mac OS with same results.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                alexisdm
                wrote on last edited by
                #7

                QWidget::scroll doesn't move the widget (although it might move the child widgets, I think), it allows you to optimize the painting of a widget that displays a scrollable content by copying the already painted part to the new position, and calling the paintEvent function only for the part that was just made visible by the scrolling.

                I wasn't sure of that so I wrote a simple example code to test it:
                @class Ruler : public QWidget
                {
                public:
                explicit Ruler(QWidget *parent = 0) : QWidget(parent)
                {
                // Without the following line QWidget would draw a background first
                // And redraw the whole widget each time it scrolls
                setAttribute(Qt::WA_OpaquePaintEvent);
                setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
                }

                QSize sizeHint() const {
                    return QSize(30, 30);
                }
                
                void paintEvent(QPaintEvent *evt)
                {
                    QPainter painter(this);
                    painter.fillRect(evt->rect(), QColor(qrand()%5, qrand()%5, qrand()%5));    
                }
                

                };
                @

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  gkroeger
                  wrote on last edited by
                  #8

                  Aha.. that makes sense... the documentation of the scroll method is clearly not robust! I will propose an improvement in the documentation.

                  Thanks Alexis!

                  Glenn

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    gkroeger
                    wrote on last edited by
                    #9

                    I have solved all of my problems by directly placing widgets in the scroll frame rather than trying to use layouts... works great

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved