Qt流式布局QFlowLayout与QScrollArea相结合问题

问题:

Qt的流式布局QFlowLayout在QScrollArea中,默认以1列多行的排列方式撑开QScrollArea控件,导致我们将QScrollArea控件缩放的时候verticalScrollBar的显示出现问题。

现象:
在这里插入图片描述

解决方案:

在父窗体的resizeEvent中更新QScrollArea的滚动条

核心代码

void Widget::resizeEvent(QResizeEvent *e)
{
    // 更新QScrollArea滚动条
    updateScrollBar();
}

void Widget::updateScrollBar()
{
    if (!m_layout->isEmpty() && m_layout->lastItem())
    {
        QWidget *lastWidget = m_layout->lastItem()->widget();
        ui->scrollAreaWidgetContents->setFixedHeight(lastWidget->y() + lastWidget->height());
    }
}

演示程序全部代码-头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QResizeEvent>
#include "qwhflowlayout.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

    // 更新QScrollArea滚动条
    void updateScrollBar();

protected:
    // 流式布局在没有该事件支持时,会默认将parentWidget高度设置为一列情况下的高度
    // 此时若使用QScrollArea来滚动流式布局中的内容时,会出现垂直滚动条下拉区域过多造成空白区域显示的情况
    // 为了解决该问题,使用resizeEvent事件,控制parentWidget的高度
    void resizeEvent(QResizeEvent *e);

private:
    Ui::Widget *ui;
    QWHFlowLayout *m_layout;
};

#endif // WIDGET_H

演示程序全部代码-cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 设置流式布局
    m_layout = new QWHFlowLayout(ui->scrollAreaWidgetContents);
    // 为流式布局添加控件,此处应QPushButton简单演示
    m_layout->addWidget(new QPushButton("aaa"));
    m_layout->addWidget(new QPushButton("bbb"));
    m_layout->addWidget(new QPushButton("ccc"));
    m_layout->addWidget(new QPushButton("ddd"));
    m_layout->addWidget(new QPushButton("eee"));
    m_layout->addWidget(new QPushButton("fff"));
    m_layout->addWidget(new QPushButton("ggg"));
    m_layout->addWidget(new QPushButton("aaa"));
    m_layout->addWidget(new QPushButton("bbb"));
    m_layout->addWidget(new QPushButton("ccc"));
    m_layout->addWidget(new QPushButton("ddd"));
    m_layout->addWidget(new QPushButton("eee"));
    m_layout->addWidget(new QPushButton("fff"));
    m_layout->addWidget(new QPushButton("ggg"));
    m_layout->addWidget(new QPushButton("aaa"));
    m_layout->addWidget(new QPushButton("bbb"));
    m_layout->addWidget(new QPushButton("ccc"));
    m_layout->addWidget(new QPushButton("ddd"));
    m_layout->addWidget(new QPushButton("eee"));
    m_layout->addWidget(new QPushButton("fff"));
    m_layout->addWidget(new QPushButton("ggg"));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::resizeEvent(QResizeEvent *e)
{
    // 更新QScrollArea滚动条
    updateScrollBar();
}

void Widget::updateScrollBar()
{
    if (!m_layout->isEmpty() && m_layout->lastItem())
    {
        QWidget *lastWidget = m_layout->lastItem()->widget();
        ui->scrollAreaWidgetContents->setFixedHeight(lastWidget->y() + lastWidget->height());
    }
}

注:
1、流式布局QFlowLayout的代码Qt文档中搜索Flow Layout Example即可找到代码!
2、可能还会遇到流式布局的其他问题,只需要注意父窗体的show()函数、父窗体被添加布局、和在外部调用父窗体的updateScrollBar()函数相结合即可解决。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用Qt的事件过滤器来实现鼠标滑动。 首先,将QScrollArea设置为可滚动: ```cpp QScrollArea *scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); ``` 然后,在构造函数中安装事件过滤器: ```cpp scrollArea->viewport()->installEventFilter(this); ``` 接下来,重写事件过滤器函数: ```cpp bool YourClassName::eventFilter(QObject *obj, QEvent *event) { if (obj == scrollArea->viewport() && event->type() == QEvent::Wheel) { // 鼠标滚轮事件 QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event); int delta = wheelEvent->delta(); int scrollBarValue = scrollArea->verticalScrollBar()->value(); scrollArea->verticalScrollBar()->setValue(scrollBarValue - delta); return true; } return false; } ``` 在这个事件过滤器函数中,我们捕获QScrollArea的视口(viewport)的鼠标滚轮事件,并获取滚动的距离delta,计算出当前滚动条的值,然后设置滚动条的值为当前值减去delta。 最后,在类的头文件中声明事件过滤器函数: ```cpp protected: bool eventFilter(QObject *obj, QEvent *event) override; ``` 完整示例代码: ```cpp #include <QtWidgets> class Widget : public QWidget { public: Widget(QWidget *parent = nullptr) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); QScrollArea *scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); QWidget *widget = new QWidget(scrollArea); QVBoxLayout *widgetLayout = new QVBoxLayout(widget); for (int i = 0; i < 100; ++i) { QLabel *label = new QLabel(QString("Label %1").arg(i + 1), widget); widgetLayout->addWidget(label); } widget->setLayout(widgetLayout); scrollArea->setWidget(widget); layout->addWidget(scrollArea); scrollArea->viewport()->installEventFilter(this); } protected: bool eventFilter(QObject *obj, QEvent *event) override { QScrollArea *scrollArea = qobject_cast<QScrollArea*>(obj); if (scrollArea && event->type() == QEvent::Wheel) { QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event); int delta = wheelEvent->delta(); int scrollBarValue = scrollArea->verticalScrollBar()->value(); scrollArea->verticalScrollBar()->setValue(scrollBarValue - delta); return true; } return false; } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮生卍流年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值