6

我的设置如下所示:

Main Window
  |- QHBoxLayout
       |- Some Widgets
       |- QScrollArea
       |    |- QHBoxLayout
       |         |- QGridLayout
       |              |- Widgets dynamically loaded in at runtime
       |         |- QVBoxLayout
       |- Some Widgets

添加小部件后,我希望滚动区域完全向下滚动。我这样做是:

this->ui->gridLayout_table->addWidget(/*Widget*/); // this works perfectly nice
this->ui->gridLayout_table->addWidget(/*Widget*/); // this also works perfectly nice
this->ui->scrollArea->verticalScrollBar()->setValue(this->ui->scrollArea->verticalScrollBar()->maximum());

在最后一个命令中,它滚动到最大值减去新添加的小部件的高度。有没有办法在滚动之前刷新更改?

在此先感谢卢卡斯

4

6 回答 6

8

该方法的 Python 版本rangeChanged

scroll_area = QtGui.QScrollArea()
scroll_bar = scroll_area.verticalScrollBar()
scroll_bar.rangeChanged.connect(lambda: scroll_bar.setValue(scroll_bar.maximum()))

通过将该rangeChanged方法连接到向下滚动,它确保每次范围发生变化时,滚动条都会向下滚动到最大值。

资源

于 2017-02-15T17:23:34.273 回答
3

我有同样的问题。我找到了一种解决方法,它也可能对您有用。

在将小部件添加到滚动区域后立即使用时,使用scrollBar->setValue(scrollBar->maximum());不起作用。滚动条的最大值还没有更新。

但是,如果您有一个按钮,用户必须单击该按钮才能将滚动条的位置调整到最大值,则它确实有效。似乎滚动区域仅异步(通过信号)通知其滚动条。所以我只是在我的小部件中添加了一个隐藏按钮pb_AdjustScrollBar并模拟点击,animateClick(int)在将小部件添加到滚动区域后使用该方法。一旦clicked(bool)收到AdjustScrollBar按钮的信号,我就会触发scrollBar使用最大位置:

scrollBarPtr->triggerAction(QAbstractSlider::SliderToMaximum);

注意:animateClick超时必须设置为 100 毫秒(默认)。将超时时间缩短很多会导致scrollBar不更新到其实际最大值。但是我猜无论如何,100 毫秒对于用户交互来说已经足够快了。

我仍然很想知道,如何以更智能的方式解决这个问题。

于 2014-06-01T10:16:26.083 回答
2

一种解决方法是使用垂直滚动条的 rangeChanged(int,int) 信号。

#include <QWidget>
#include <QBoxLayout>
#include <QScrollArea>
#include <QScrollBar>

class myClass
{
    Q_OBJECT
public:
    myClass();
private:
    QScrollArea *scrollArea;
    int scrollBarMax = 0;
private slots:
    void scrollToBottom(int min, int max);
};

myClass::myClass()
{
    QVBoxLayout *myLayout = new QVBoxLayout;
    QWidget *myWidget = new QWidget;
    myWidget->setLayout(myLayout);
    scrollArea = new QScrollArea;
    scrollArea->setWidget(myWidget);
    scrollArea->setWidgetResizeable(true);

    QObject::connect(scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(scrollToBottom(int,int)));
}

void myClass::scrollToBottom(int min, int max)
{
    (void) min;
    if (max > scrollBarMax) scrollArea->verticalScrollBar()->setValue(max);
    scrollBarMax = max;
}
于 2017-02-03T20:23:58.173 回答
1

我找到了方法。添加小部件后: scroll->widget()->resize(scroll->widget()->sizeHint()); qApp->processEvents();

于 2015-08-05T11:26:46.790 回答
0

嗯,我没有答案,同样的问题。但是,我可以提供一个小的复制示例:

#include <QtGui>

class TestWidget : public QWidget
{
    Q_OBJECT

public:
    TestWidget(QWidget * parent = 0);

private slots:
    void addButton();

private:
    QScrollArea * scrollArea;
    QWidget * contents;
    QVBoxLayout * contentsLayout;
};

TestWidget::TestWidget(QWidget * parent)
    : QWidget(parent)
{
    QVBoxLayout * layout = new QVBoxLayout(this);
    scrollArea = new QScrollArea(this);
    layout->addWidget(scrollArea);

    contents = new QWidget(this);
    scrollArea->setWidget(contents);
    contents->resize(300,400);
    scrollArea->setWidgetResizable(true);

    contentsLayout = new QVBoxLayout(contents);
    for (int i = 0; i < 10; ++i)
    {
        QPushButton * button = new QPushButton(QString("button %1").arg(i), this);
        connect(button, SIGNAL(clicked()), this, SLOT(addButton()));
        contentsLayout->addWidget(button);
    }

}

void TestWidget::addButton()
{
    QPushButton * button = new QPushButton("button", this);
    connect(button, SIGNAL(clicked()), this, SLOT(addButton()));
    contentsLayout->addWidget(button);
    QScrollBar * scrollBar = scrollArea->verticalScrollBar();
    scrollBar->setValue(scrollBar->maximum());
}

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    TestWidget widget;
    widget.show();

    app.setQuitOnLastWindowClosed(true);

    return app.exec();
}

#include "main.moc"

Qt 4.8 和 5.2 都会出现此问题(需要对示例进行少量修改)。

于 2013-11-29T22:29:51.540 回答
0

遇到了同样的问题,手册是这样说的:

"In such cases, setting the layout's size constraint property to one which provides 
constraints on the minimum and/or maximum size of the layout (e.g., 
QLayout::SetMinAndMaxSize) will cause the size of the scroll area to be updated 
whenever the contents of the layout changes."

在我的情况下,QScrollArea 的内容大小是通过setMinimumSizeQScrollArea 的小部件的方法改变的,所以我只是添加了ui->scroll_area->widget()->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);它,它开始正常工作。

重要提示:在调整 QScrollArea 小部件的大小后,您应该在自定义事件处理程序中更改 QScrollBar 的值。简单的例子:

bool MyCustomClassWithScrollArea::event(QEvent * event)
{
    switch (event->type())
    {
        case MyCustomScrollToEndEvent::ScrollToEndEventType:
        {
            ui->scroll_area->verticalScrollBar()->setValue( ui->scroll_area->verticalScrollBar()->maximum() ); //scrolls to the end
            return true;
        }
    }

    return QWidget::event(event);
}
于 2019-02-01T07:49:01.667 回答