首页 > 解决方案 > qt中设置setWidgetResizable为true后,滚动区自定义小部件无法上下滚动

问题描述

使用 QScrollArea 时遇到问题。主要是,我想在滚动区域中添加一个自定义小部件以达到:

  1. 如果小部件的大小大于父级(scroll) ,则滚动小部件
  2. 自定义小部件可以自动调整其大小以填充所有空间,scroll如果它小于scroll

但我失败了。设置setWidgetResizable为 true 可以调整小部件的大小,但不能滚动。否则,滚动小部件不能调整大小。

我正在使用 qt-5.15.x。这是最小的示例,如果我注释掉行,我可以滚动它scroll->setWidgetResizable(true);

自定义小部件.h

#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H

#include <QWidget>
#include <QSize>
#include <QResizeEvent>

class CustomWidget : public QWidget
{
  Q_OBJECT
public:
  explicit CustomWidget(QWidget *parent = nullptr);
  ~CustomWidget()=default;
protected:
  void paintEvent(QPaintEvent *e);
  void resizeEvent(QResizeEvent *e);
  QSize sizeHint() const override;

private:
  QVector<QRectF> _rects;
  QSize _size;
};

#endif // CUSTOMWIDGET_H

customwidget.cpp

#include "customwidget.h"
#include <QPainter>

CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
  _size = QSize(120, 200);
  for(int i = 0; i < 10; i++)
  {
    QRectF rect(QPointF(10, 60*i+2),QSize(100, 50));
    _rects.push_back(rect);
  }
}

void CustomWidget::paintEvent(QPaintEvent *e)
{
  QPainter painter(this);

  // background
  painter.setBrush(QColor(130,130,130));
  painter.drawRect(QRectF(QPointF(0,0), _size));

  // items
  for(int i = 0; i < 10; i++)
  {
    painter.setBrush(QColor(43,43,43));
    painter.drawRect(_rects[i]);
    painter.setPen(QColor(255,255,255));
    painter.drawText(_rects[i], QString("ITEM %1").arg(QString::number(i)));
    }
}

void CustomWidget::resizeEvent(QResizeEvent *e)
{
  _size = e->size();
}

QSize CustomWidget::sizeHint() const
{
  int rows = _rects.size();
  int height = rows * 60+2;

  height = std::max(height, parentWidget()->height());
  int width = 120;

  return QSize(width, height);
}

添加主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();

private:
  Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QScrollArea>
#include "customwidget.h"
#include <QVBoxLayout>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setGeometry(0,0,300,200);

  QVBoxLayout *layout = new QVBoxLayout(centralWidget());
  layout->setContentsMargins(0,0,0,0);

  CustomWidget *cw = new CustomWidget();
  QScrollArea *scroll = new QScrollArea(this);
  scroll->setWidgetResizable(true);
  scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  scroll->setStyleSheet("QScrollArea{background:rgb(0,0,0);border:none;}");
  scroll->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  scroll->setWidget(cw);

  layout->addWidget(scroll);
}

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

标签: c++qt

解决方案


一种可能的解决方案是将 sizePolicy 设置为最小值:

CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
    _size = QSize(120, 200);
    for(int i = 0; i < 10; i++)
    {
        QRectF rect(QPointF(10, 60*i+2),QSize(100, 50));
        _rects.push_back(rect);
    }
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}

推荐阅读