我在QScrollArea中放置自定义小部件时遇到了一些问题。我的自定义小部件在QGridLayout中包含4个标签填充它。现在我想将这个小部件保存在QScrollArea中,并且能够为它添加更多标签,但我希望它们只能在视口中显示4个。
这就是QScrollArea中带有4个标签的widget的样子:
这是添加两个标签后QScrollArea中的小部件,其中红色矩形是视口。
我怎样才能达到这样的效果?
===================================
更新
我最终使用以下代码解决了我的问题。它可能需要一些小间距修复。
#include "QtGuiApplication2.h"
#include "qscrollarea.h"
#include "CustomWidget.h"
QtGuiApplication2::QtGuiApplication2(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QScrollArea * qScrollArea = new QScrollArea();
CustomWidget * customWidget = new CustomWidget(this);
qScrollArea->setWidget(customWidget);
qScrollArea->setWidgetResizable(true);
qScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui.mainLayout->addWidget(qScrollArea, 1, 1, 1, 1);
}
CustomWidget类:
#include "CustomWidget.h"
#include "qlabel.h"
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
labelsNum = 4;
rows = 2;
layout = new QGridLayout();
this->setLayout(layout);
QMargins * margin = new QMargins(10, 10, 10, 10);
layout->setContentsMargins(*margin);
layout->setHorizontalSpacing(5);
layout->setVerticalSpacing(5);
initLabels();
addLabels();
}
CustomWidget::~CustomWidget()
{
}
void CustomWidget::initLabels()
{
int cols = labelsNum / rows;
for (int i = 0; i < labelsNum; i++)
{
CustomLabel * label = new CustomLabel(this);
label->setText(QString::number(i));
label->setFrameShape(QFrame::Box);
labels.append(label);
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
layout->addWidget(labels.at(i * cols + j), i + 1, j + 1, 1, 1);
}
}
}
void CustomWidget::addLabels()
{
int numLabels = labels.size();
for (int i = 0; i < 2; i++)
{
CustomLabel * label = new CustomLabel(this);
label->setText(QString::number(numLabels + i));
label->setFrameShape(QFrame::Box);
labels.append(label);
}
labelsNum += rows;
int cols = labelsNum / rows;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
layout->addWidget(labels.at(i * cols + j), i + 1, j + 1, 1, 1);
}
}
}
void CustomWidget::resizeEvent(QResizeEvent * e)
{
QWidget::resizeEvent(e);
QSize size = viewportSize;
//Substract all the spacing from view size
int horizontalSpacing = ((4 / rows) - 1) * layout->horizontalSpacing();
int verticalSpacing = (rows - 1) * layout->verticalSpacing();
size -= QSize(layout->margin() * 2 + horizontalSpacing, layout->margin() * 2 + verticalSpacing);
size *= 0.5;
for (int i = 0; i < labels.size(); i++)
{
labels.at(i)->resizeEvent(e, size);
}
}
自定义标签:
#include "CustomLabel.h"
CustomLabel::CustomLabel(QWidget *parent): QLabel(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMinimumSize(QSize(50, 50));
}
CustomLabel::~CustomLabel()
{
}
void CustomLabel::resizeEvent(QResizeEvent * e, QSize size)
{
this->setFixedSize(size);
}
答案 0 :(得分:5)
要获得您想要的行为,您必须设置大小,为此我创建了以下继承自QScrollArea
的类,并在内部具有QGridLayout
。对于此类,您必须确定可见行和列的数量以及窗口小部件的固定大小,在您的情况下为QLabel
。
#ifndef HORIZONTALSCROLLAREA_H
#define HORIZONTALSCROLLAREA_H
#include <QGridLayout>
#include <QResizeEvent>
#include <QScrollArea>
#include <QScrollBar>
class HorizontalScrollArea : public QScrollArea
{
QWidget *contentWidget;
QGridLayout *grid;
int nRows;
int nColumns;
public:
HorizontalScrollArea(int rows, int cols, QWidget *parent = Q_NULLPTR)
:QScrollArea(parent), nRows(rows), nColumns(cols)
{
setWidgetResizable(true);
contentWidget = new QWidget(this);
setWidget(contentWidget);
grid = new QGridLayout(contentWidget);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
void addWidget(QWidget *w, int row, int col){
grid->addWidget(w, row, col);
adaptSize();
}
int columnCount() const{
if(grid->count() == 0){
return 0;
}
return grid->columnCount();
}
private:
void adaptSize(){
if(columnCount() >= nColumns ){
int w = 1.0*(width() - grid->horizontalSpacing()*(nColumns+1.6))/nColumns;
int wCorrected = w*columnCount() + grid->horizontalSpacing()*(columnCount()+2);
contentWidget->setFixedWidth(wCorrected);
}
contentWidget->setFixedHeight(viewport()->height());
}
protected:
void resizeEvent(QResizeEvent *event){
QScrollArea::resizeEvent(event);
adaptSize();
}
};
#endif // HORIZONTALSCROLLAREA_H
以下部分是一个例子:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setLayout(new QVBoxLayout);
QPushButton btn("Add", &w);
int nrows = 2;
int ncols = 2;
HorizontalScrollArea scroll(nrows, ncols);
w.layout()->addWidget(&btn);
w.layout()->addWidget(&scroll);
QObject::connect(&btn, &QPushButton::clicked, [&scroll, &nrows](){
int column = scroll.columnCount();
for(int row=0; row < nrows; row++){
QLabel *label = new QLabel(QString("label: %1 %2")
.arg(row)
.arg(column));
label->setFrameShape(QFrame::Box);
label->setAlignment(Qt::AlignCenter);
QColor color(qrand() % 256, qrand() % 256, qrand() % 256);
label->setStyleSheet(QString("QLabel { background-color : %1;}")
.arg(color.name()));
scroll.addWidget(label, row, column);
}
});
w.show();
return a.exec();
}
以下link是完整的示例。
输出: