[SOLVED] QScrollArea: Vertical scroll only.
-
Hello,
I'm trying to use a QScrollArea where only the vertical scrollbar is in use.
I've set setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
But that simply makes the internal widgets clip on the right side of the screen.
What I've done so far is ovride the resizeEvent and set:
widget()->setMinimumWidth(event->size().width())This does the trick a lot of the time... but if the internal widgets needs a size greater then what the resize event is giving then the internal widgets start drawing on top of each other.
Does anyone have any ideas of how to resolve this?
-
Try to disable the horizontal scroll and enable the vertical scroll if needed usi the following methods of "QAbstractScrollArea":http://doc.qt.nokia.com/4.8-snapshot/qabstractscrollarea.html#verticalScrollBarPolicy-prop
@
QAbstractScrollArea::setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff )
QAbstractScrollArea::setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded)
@ -
Sigh...
In my original message I have already mentioned that I did exactly that already... but that is not enough.
What I want:
The QScrollArea should scroll vertically (as it does normally).
Horizontally it should behave exactly like a QWidget
-meaning internal widgets resize to fit it's available space
-also it is not allowed to resize smaller then the internal widgets permit. -
Found a solution! simply look for resize events for the scrollAreaWithContents widgets and set the scrollArea's minimum width to the scrollAreaWithContents minimumSizeHint().with():
@VerticalScrollArea::VerticalScrollArea(QWidget *parent)
: QScrollArea(parent)
{
setWidgetResizable(true);
setFrameStyle(QFrame::NoFrame);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_scrollAreaWidgetContents = new QWidget(this);
m_scrollAreaWidgetContents->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
QVBoxLayout *baseLayout = new QVBoxLayout(m_scrollAreaWidgetContents);
setWidget(m_scrollAreaWidgetContents);
m_scrollAreaWidgetContents->installEventFilter(this);
}bool VerticalScrollArea::eventFilter(QObject *o, QEvent *e)
{
if(o == m_scrollAreaWidgetContents && e->type() == QEvent::Resize)
setMinimumWidth(m_scrollAreaWidgetContents->minimumSizeHint().width() + verticalScrollBar()->width());return false;
}@ -
Hello,
I'm fairly new to Qt and I would like to know how I implement the VerticalScrollArea class to correct the problem?
-
[quote author="mstone1959" date="1389726822"]Hello,
I'm fairly new to Qt and I would like to know how I implement the VerticalScrollArea class to correct the problem?[/quote]
You will want to create a new class "VerticalScrollArea" derived off of QScrollArea.
header:
@#ifndef VERTICALSCROLLAREA_H
#define VERTICALSCROLLAREA_H#include <QScrollArea>
class VerticalScrollArea : public QScrollArea
{
Q_OBJECT
public:
explicit VerticalScrollArea(QWidget *parent = 0);virtual bool eventFilter(QObject *o, QEvent *e);
};
#endif // VERTICALSCROLLAREA_H@
Implementation:
@#include <QEvent>
#include <QScrollBar>#include "verticalscrollarea.h"
VerticalScrollArea::VerticalScrollArea(QWidget *parent) :
QScrollArea(parent)
{
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
}bool VerticalScrollArea::eventFilter(QObject *o, QEvent *e)
{
// This works because QScrollArea::setWidget installs an eventFilter on the widget
if(o && o == widget() && e->type() == QEvent::Resize)
setMinimumWidth(widget()->minimumSizeHint().width() + verticalScrollBar()->width());return QScrollArea::eventFilter(o, e);
}
@ -
[quote author="galinette" date="1360135272"]Thanks for the solution!
By the way, this is close to be a bug. A QScrollArea with horizontal bars switched off should set its minimum width by considering the minimum width of the contents widget, no?[/quote]
I don't think so. I think setting the horizontal scroll bar to off should simply not show a horizontal scroll bar (but that doesn't mean the area can't be scrolled, e.g. with touch and drag). Changing the width of the scroll area should be a separate step if the developer so desires.
-
Although old, this topic saved me time. So here are my two cents here. I change the constructor to this to support one-finger scrolling on Android (didn't try for iOS yet):
CVScrollArea::CVScrollArea(QWidget *parent) : QScrollArea(parent) { setWidgetResizable(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // One-finger swipe/scroll while default in Qt is 3-fingers! QScroller::grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture); // No scroll bar for Android (and probably iOS) #ifndef Q_OS_ANDROID this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); #else this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); #endif }
-
Hello from 2022.
Used all my google-fu to find this answer. Thank you!
I confirm that there is still no standard QVerticalScroll, you have to implement it yourself with overriding eventFilter.p.s.
...but the eventFilter() get a lot of calls from everythin (mouse, activation, resize etc)
I suggest to override resizeEvent(). Here is my approach:HEADER:
protected: void resizeEvent(QResizeEvent *);
SOURCE:
void ClassName::resizeEvent(QResizeEvent* event) { setMinimumWidth(widget()->minimumSizeHint().width() + verticalScrollBar()->width()); QScrollArea::resizeEvent(event); }
-
Every couple of years this comes up...
Certainly setMinimumWidth() is key - it needs to fit the size of the scrolled widget().
In my derived class I actually connected a slot to the horizontal scroll bar, which changes if the widget() changes width
connect( horizontalScrollBar(), &QAbstractSlider::rangeChanged, this, &CVerticalScrollArea::ResetMinWidth );
then I calculate the minumum width bearing in mind the frame width. I do the same for the minimumSizeHint too (although maybe this is not required).
QSize CVerticalScrollArea::minimumSizeHint() const { QSize MinSize( QScrollArea::minimumSizeHint() ); const QWidget * pWidget( widget() ); if( pWidget ) { const int FrameWidth( 2 * frameWidth() ); const int TotalWidth( pWidget->minimumSizeHint().rwidth() + FrameWidth ); if( TotalWidth > MinSize.width() ) MinSize.setWidth( TotalWidth ); } return MinSize; }