Is it possible with QScrollArea behave like a wheel?
-
I created a custom scroll area by using QScrollArea which is working quite nice. It is possible to scroll the content by wishing with a finger on a touch display or dragging with the mouse on a desktop. The scroll area has no visible scrollbars. This is what I want.
But I can not scroll over the top or bottom item or the left or right item inside. Is it possible to make a scroll area that behaves like a wheel so that I can turn it around and around? If so, how?
Another question is about the scrolling. Is it possible to implement smooth scrolling? I mean when I call the function QScrollBar::setSliderPosition() or QScrollArea::ensureWidgetVisible() that it scrolls slowly to the wanted position and not suddenly, like it does currently?A.T.
-
I have a few questions, and I think answering them would clarify a lot about what you need:
-
Do you mean infinite horizontal and vertical scrolling?
-
What widget are you using inside your scroll area?
-
Wouldn't it be better if you made a separate topic for your second question? I think the first one is a big task on its own, so let's focus on it first.
Possibly related sources:
-
-
@Abderrahmene_Rayene :
Yes, I mean infinite scrolling.
If you look at the screen shot above, then one of the time elements consist of a QWidget (I call this an item) and this QWidget contains 1 or more QLabel. So in this example the QWidget has 9 QLabel childs. On the left side the background is one, each time part (11, AM, 00, 30) is one and each of the lines on the right of the time is a QLabel. To be later able to identify them on a mouse click, each element has a distinct name. So far so well.
Each of this "items" is placed on another QWidget. This parent Qwidget is as large as all the "items" together. So the QScrollArea has this main QWidget, which has the "items" as childs.QScrollArea::setParent(mParent); QScrollArea::setFixedSize(mWidth, mHeight); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Set a transparent background QPalette palette(this->palette()); palette.setColor(QPalette::Window, QColor(Qt::transparent)); setPalette(palette); mMain = new QWidget(this); // QWidget *mMain; mMain->move(0, 0); mMain->setContentsMargins(0, 0, 0, 0); setFixedSize(mWidth, mHeight); setWidget(mMain); mHLayout = new QHBoxLayout(mMain); // QHBoxLayout *mHLayout; mHLayout->setSpacing(0); mHLayout->setContentsMargins(0, 0, 0, 0);
The above code is a shortened excerpt of the initialization of my class called TQScrollArea.
class TQScrollArea : public QScrollArea { Q_OBJECT public: TQScrollArea(); TQScrollArea(QWidget *parent); TQScrollArea(QWidget *parent, int w, int h, bool vertical = false); TQScrollArea(QWidget *parent, const QSize& size, bool vertical = false); ~TQScrollArea(); [...]
Doing it this way, I found no way for infinite scrolling.
A.T.
-
@TheoSys I have an idea that might work for you or at lease inspire you.
If you scroll down: remove the top item in your layout and insert it at the end.
If you scroll up: remove the bottom item in your layout and insert it at the beginning.
But only if you scroll as much as an object's height.
I implemented this using a custom QScrollArea and 9 buttons from 0 to 9, and overrode the
scrollArea
'swheelEvent
to achieve infinite scrolling.Here's the code with some "documentation"
//This function overrides the one of QScrollArea class in your subclass of it void TQScrollArea::wheelEvent(QWheelEvent *e) { //get scrollArea's widget QWidget *widget = this->widget(); //get scrollArea's widget's layout QVBoxLayout *layout = this->findChild<QVBoxLayout *>("layout",Qt::FindChildrenRecursively); //This is for when we move mouse wheel forward if(e->angleDelta().y()>0) { //get one of your layout's objects to use its height later on QPushButton *b = this->findChild<QPushButton *>("button9",Qt::FindChildrenRecursively); //This next if block is just to enable me to scroll with the mouse wheel since there are no scrollbars if(widget->visibleRegion().boundingRect().y()-10>=0) this->viewport()->scroll(0,10); //This if statement detects if we have scrolled as much as an object's height //so if you're not going to use a wheel event, you can use the same idea in a drag or mousemove event //use your scrollArea's widget's visible region y coordinate to detect how much it moved if(widget->visibleRegion().boundingRect().y()-10<=b->height()) { //If true then we remove the the last item in layout auto whatisthis = layout->itemAt(layout->count()-1); layout->removeItem(layout->itemAt(layout->count()-1)); //then insert it at the beginning layout->insertItem(0,whatisthis); } } //This is for when we move mouse wheel backwards if(e->angleDelta().y()<0) { //Here we do the same except we remove the first item and insert it at the end of the layout QPushButton *b = this->findChild<QPushButton *>("button1",Qt::FindChildrenRecursively); if(widget->visibleRegion().boundingRect().y()+10<=layout->geometry().height()-b->height()*7.8) { this->viewport()->scroll(0,-10); } if(widget->visibleRegion().boundingRect().y()+10<=b->height()) { auto whatisthis = layout->itemAt(0); layout->removeItem(layout->itemAt(0)); layout->insertItem(layout->count(),whatisthis); } } //et voila, this creates the infinite scrolling effect, it's not perfect or organized, but it does the trick //and you have to adjut it to your use case, because this is just an example to demonstrate my idea }
This is how it looks like:
This not exactly your case because I don't know how exactly you're scrolling so I went with mouse wheel, but I think you just need to adapt it to yours.
If you have any questions don't hesitate to ask, my workarounds are confusing.
-
@Abderrahmene_Rayene :
Thank you for your answer. I understood how you did it and this is indeed a way I can implement it. But it shows also that there is no infinite scroll build in into Qt. I hoped to not have to implement it myself but hope dies last.A.T.
-
-
@TheoSys What if this feature gets suggested?
Although the only way that I found to do that is by using the bug report system.
But then I suspect it would be shut down as "user can implement this themselves".