QPushButton 不支持水平扩展尺寸策略

Posted

技术标签:

【中文标题】QPushButton 不支持水平扩展尺寸策略【英文标题】:QPushButton does not honor horizontal expanding size policy 【发布时间】:2014-08-26 18:22:54 【问题描述】:

我试图将几个 QPushButton 实体放在 QVBoxLayout 中,以使它们居中并展开。扩展标签工作正常,直到我告诉 QVBoxLayout 使用 AlignHCenter,之后 QPushButton 都跳转到最小尺寸并停留在那里。我做错了什么?

QVBoxLayout *vBoxLayout = new QVBoxLayout(this);
setLayout(vBoxLayout);

//Create title and add to layout
QLabel *titleLabel = new QLabel(this);
titleLabel->setText(menuTitle);
titleLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
titleLabel->setMaximumHeight(35);
titleLabel->setStyleSheet(QString("QLabel  font-size: 16pt; "));
vBoxLayout->addWidget(titleLabel);
vBoxLayout->setStretchFactor(titleLabel, 1);


//Create buttons and add to layout
QMap<int, QString>::const_iterator it;
for (it = m_buttonMapping.cbegin(); it != m_buttonMapping.cend(); ++it)

    QPushButton *button = new QPushButton(it.value(), this);
    connect(button, SIGNAL(clicked()), sigMapper, SLOT(map()));
    sigMapper->setMapping(button, it.key());

    button->setMinimumHeight(40);
    button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    button->setMaximumWidth(800);
    button->setMinimumWidth(300);

    vBoxLayout->addWidget(button);
    vBoxLayout->setAlignment(button, Qt::AlignHCenter);  //<-- without this, expanding works fine!
    vBoxLayout->setStretchFactor(button, 1);


vBoxLayout->setContentsMargins(10, 0, 10, 0);

【问题讨论】:

【参考方案1】:

通过在布局上指定对齐方式,可以防止 QPushButtons 展开。可用的新空间将用于保持 QPushButtons 居中,而不是允许它们调整大小并让它们周围的空间用于居中。拉伸因子满足您对布局内容按比例调整大小和居中的要求。

要解决这个问题,请创建一个包装器小部件和布局(或只是一个布局),然后将您的 vBoxLayout 布局的小部件添加到应用了拉伸因子的包装器布局中。在添加小部件之前和之后,您将使用 QHBoxLayout::addStretch 将 QSpacerItems 添加到包装器布局中。然后,您可以调整小部件和垫片的拉伸系数以获得您想要的效果。

这里有一些示例代码应该可以解决您的问题:

MainWindow.cpp

#include "MainWindow.hpp"
#include <QPushButton>
#include <QLabel>
#include <QBoxLayout>

MainWindow::MainWindow(QWidget* parent)
  : QMainWindow(parent) 
  QWidget* centralWidget = new QWidget(this);

  QVBoxLayout* layout = new QVBoxLayout(centralWidget);

  // Create a wrapper widget that will align horizontally
  QWidget* alignHorizontalWrapper = new QWidget(centralWidget);
  layout->addWidget(alignHorizontalWrapper);

  // Layout for wrapper widget
  QHBoxLayout* wrapperLayout = new QHBoxLayout(alignHorizontalWrapper);
  // Set its contents margins to 0 so it won't interfere with your layout
  wrapperLayout->setContentsMargins(0, 0, 0, 0);

  wrapperLayout->addStretch(1);

  QWidget* widget = new QWidget(alignHorizontalWrapper);
  wrapperLayout->addWidget(widget, 3);

  wrapperLayout->addStretch(1);

  QVBoxLayout* vBoxLayout = new QVBoxLayout(widget);

  QLabel* titleLabel = new QLabel(this);
  titleLabel->setText(QStringLiteral("Menu"));
  titleLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
  titleLabel->setMaximumHeight(35);
  titleLabel->setStyleSheet(QStringLiteral("QLabel  font-size: 16pt; "));
  vBoxLayout->addWidget(titleLabel);
  vBoxLayout->setStretchFactor(titleLabel, 1);

  for (int i = 0; i < 3; ++i) 
    const QString& value = QStringLiteral("Button ") + QString::number(i);

    QPushButton* button = new QPushButton(value, this);

    button->setMinimumHeight(40);
    button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    //button->setMaximumWidth(800);
    button->setMinimumWidth(300);

    vBoxLayout->addWidget(button);
    //vBoxLayout->setAlignment(button, Qt::AlignHCenter);  // without this, expanding works fine!
    vBoxLayout->setStretchFactor(button, 3);
  

  vBoxLayout->setContentsMargins(10, 0, 10, 0);

  this->setCentralWidget(centralWidget);

MainWindow.hpp

#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP

#include <QMainWindow>

class MainWindow : public QMainWindow 
  Q_OBJECT

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

#endif // MAINWINDOW_HPP

ma​​in.cpp

#include "MainWindow.hpp"
#include <QApplication>

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

  MainWindow window;
  window.show();

  return app.exec();

【讨论】:

谢谢,这成功了!任何包装器布局类型或小部件都可以工作(只要它的扩展),还是必须是 QHBoxLayout? 您可以使用任何遵循布局管理 (qt-project.org/doc/qt-5/layout.html) 指南中规则的布局管理器类。据我所知,Qt 中的所有布局都可以。如果拉伸因子设置为非零,它将覆盖大小策略。从布局管理: 1.) 所有小部件最初将根据它们的 QWidget::sizePolicy() 和 QWidget::sizeHint() 分配一定量的空间。 2.) 如果任何小部件设置了拉伸因子,其值大于零,则它们将按其拉伸因子的比例分配空间。

以上是关于QPushButton 不支持水平扩展尺寸策略的主要内容,如果未能解决你的问题,请参考以下文章

从代码创建的 QPushButton 的最小尺寸/宽度

非对称高斯滤波器 - 水平和垂直滤波器的不同尺寸和 STD

ThingWorx 水平可扩展性

3.1.2 QGridLayout网格布局

AutoLayout:垂直到水平,没有明确的尺寸?

为啥 QPushButton 不尊重绝对像素大小?