使QLabel宽度独立于文本

时间:2018-02-06 10:34:47

标签: c++ qt qt5 qwidget qlabel

我需要一个QLabel,其宽度不应该适应所包含的文本,但可以由用户调整(或者说布局是精确的)。如果文本对于QLabel的宽度来说太长,则应该剪切它。

这个问题与某种方式相反 How to make QLabel expand width geometry to accommodate text。但是,这个问题的内容对我没有帮助。 Setting text on a QLabel in a layout, doesn't resize也没有。

背景

QLabel将显示来自其他系统的标识符(单个单词)。有时这些标识符每秒会改变很多次,这使整个布局变得闪烁。 QLabel是垂直底座的一部分,因此底座的宽度会闪烁。

另一方面,应该由用户决定他/她可以看到多少标识符。所以我希望允许用户更改扩展坞的宽度,使QLabel的宽度适应该扩展。

解决方案尝试

为了达到这个目的,我将水平尺寸政策设置为QSizePolicy::Preferred并从QLabel派生了我自己的标签类,其中我已覆盖sizeHint()以返回固定尺寸。但这并没有改变这种行为。

我知道我可以应用QFontMetrics来计算文本的宽度,然后将其剪切掉以适合QLabel宽度。但这似乎不是正确的解决方案,特别是因为如果它不完全适合给用户提供标识符太长而无法显示的线索,我希望将最后一个字母剪切掉。

版本

  • Qt 5.5.1
  • GCC 5.4.0
  • 全部来自当前的Ubuntu 16.04存储库

3 个答案:

答案 0 :(得分:3)

我认为我找到了一个相当脏的解决方案,可能会导致更多问题,但您可以尝试一下。它只是阻止setText调整标签大小,同时它仍然允许用户和布局调整大小。

void CustomLabel::setText(const QString text)
{
    max = maximumSize();
    min = minimumSize();
    setMinimumSize(size());
    setMaximumSize(size());
    settingText = true;

    QLabel::setText(text);
}


void CustomLabel::resizeEvent(QResizeEvent *event)
{
    QLabel::resizeEvent(event);
    if(settingText){
        setMinimumSize(min);
        setMaximumSize(max);
        settingText = false;
    }
}

答案 1 :(得分:2)

制作自己的标签类,以这种方式扩展QWidget

#include <QWidget>

class DisplayWidget : public QWidget
{
    Q_OBJECT
    QString _text;
public:
    explicit DisplayWidget(QString text, QWidget *parent = nullptr);

    QString text() const;
    void setText(QString text);

protected:
    void paintEvent(QPaintEvent *event);
};

实施非常简单:

#include "displaywidget.h"

#include <QPainter>
#include <QFontMetrics>

bool DisplayWidget::ellipsis() const { return _ellipsis; }
void DisplayWidget::setEllipsis(bool ellipsis) { _ellipsis = ellipsis; }

DisplayWidget::DisplayWidget(QString text, QWidget *parent) : QWidget(parent), _text(text), _ellipsis(false) {}

QString DisplayWidget::text() const { return _text; }

void DisplayWidget::setText(QString text)
{
    _text = text;
    update();
}

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

    QFontMetrics metrics(painter.font());

    int maxwidth = rect().width();
    QString text = _text;
    int length = _text.size();
    while(length > 0 && metrics.width(text, length) > maxwidth)
    {
        --length;
    }
    if(length < _text.size())
    {
        text = text.left(length);
        if(_ellipsis)
        {
            const QString ellipsis = " ...";
            maxwidth -= metrics.width(ellipsis);
            while(length > 0 && metrics.width(text, length) > maxwidth)
            {
                --length;
            }
            if(length > 0)
            {
                text = text.left(length);
            }
            else
            {
                text = "";
            }
            text.append(ellipsis);
        }
    }
    painter.drawText(rect(), Qt::AlignLeft, text);
}

如您所见,大多数代码都在paintEvent重写方法中。重要的是,在这里,手头有字体指标,即时决定必须显示多少文本(我在部分显示的文本的末尾添加了省略号),而不更改文本属性本身。只需将此类的实例添加到Dock内的垂直布局即可。我认为它可行。

答案 2 :(得分:2)

缩放文本不是一个好主意,因为在长字符串和小标签的情况下,缩放文本几乎不可见。作为替代方案,我会将我的标签放在滚动区域中,这样它就可以保存任何大小的标签,而无需调整自身大小(并防止我的GUI闪烁)。这是一个简单的例子:

QLabel *label = new QLabel;
label->setAlignment(Qt::AlignTop);

QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(label);

label->setText("ThisIsVeryLargeStringThatIWantToPutIntoALabel");
scrollArea->show();

此滚动区域可以放置在可停靠的窗口中。