设置 QPushButton 的最小宽度,同时保持默认的 minimumSizeHint 行为

Setting minimum width of QPushButton while keeping default minimumSizeHint behavior

在我的应用程序中,我需要所有 QPushButton 的宽度至少为 150px,但如果需要则更大。 为此,我使用了具有以下简单约束的全局样式表(其中包含许多其他属性):

QPushButton {
    min-width: 150px;
}

问题是,我还希望带有不适合 150px 的文本的按钮无法缩小到无法显示整个文本的宽度。
这应该是 QPushButton 的正常行为,但问题是,如 minimumSizeHint() 的文档中所述:

QLayout will never resize a widget to a size smaller than the minimum size hint unless minimumSize() is set or the size policy is set to QSizePolicy::Ignore. If minimumSize() is set, the minimum size hint will be ignored.

这会导致某些情况下,带有长文本的按钮在启动时以正确的大小显示,但当缩小 window 时,按钮变得太小而无法显示所有文本。
我准备了一个简单的例子来展示这种行为:

#include <QWidget>
#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget *w = new QWidget();
    QLayout* layout = new QHBoxLayout(w);

    QPushButton* buttonA = new QPushButton("A", w);
    QPushButton* buttonB = new QPushButton("B", w);
    buttonB->setStyleSheet("min-width: 150px");
    QPushButton* buttonC = new QPushButton("Long long text that doesn't fit in 150px", w);
    QPushButton* buttonD = new QPushButton("Very very very long text that doesn't fit in 150px", w);
    buttonD->setStyleSheet("min-width: 150px");

    layout->addWidget(buttonA);
    layout->addWidget(buttonB);
    layout->addWidget(buttonC);
    layout->addWidget(buttonD);

    w->show();

    return a.exec();
}

我考虑过使用 dynamic properties 将最小宽度限制仅设置为基本宽度 < 150px 的按钮,但这似乎不可行。

有没有办法用样式表做我想做的事情,还是我必须子类化 QPushButton 并覆盖 minimumSizeHint() 方法(我想避免这种情况,因为我必须替换我的应用程序中的很多按钮) ?

如果你sub-class QPushButton 就更好了。但是有 2 个解决此问题的方法:

  1. 您可以strip将长文本设置为特定字符数,并使用setToolTip(QString)功能在鼠标进入按钮时显示全文。

  2. 您可以覆盖父小部件 resizeEvent 并且可以检查宽度,如果尺寸变得非常小,则使用方法 1。

  3. 使用省略文本example to get idea about elide for QPushButton。不确定这是否有效。

我无法找到仅使用样式表来执行此操作的方法,但这是我通过子类化 QPushButton

提出的解决方案

MyPushButton.h

#include <QPushButton>

class MyPushButton
    : public QPushButton
{
    Q_OBJECT
    Q_PROPERTY(int minWidth READ minWidth WRITE setMinWidth)

public:
    MyPushButton(QWidget* parent = nullptr);
    virtual ~MyPushButton();

    int minWidth() const;
    void setMinWidth(int width);

    virtual QSize minimumSizeHint() const override;

private:
    int _minWidth;
};

MyPushButton.cpp

#include "MyPushButton.h"

MyPushButton::MyPushButton(QWidget* parent)
    : QPushButton(parent)
    , _minWidth(0)
{
}

MyPushButton::~MyPushButton()
{
}

int MyPushButton::minWidth() const
{
    return _minWidth;
}

void MyPushButton::setMinWidth(int width)
{
    _minWidth = width;
}

QSize MyPushButton::minimumSizeHint() const
{
    // if the minimum width is less than minWidth, set it to minWidth
    // else return the default minimumSizeHint
    return QSize(qMax(QPushButton::minimumSizeHint().width(), _minWidth),
        QPushButton::minimumSizeHint().height());
}

stylesheet.qss

MyPushButton {
    qproperty-minWidth: 150;
}

minimumSizeHint 宽度小于 150px 的按钮将被强制为该尺寸,较大的按钮将保持 QPushButton 的默认行为。