使 QLabel 宽度独立于文本
Make QLabel width independent of text
我需要一个 QLabel
,其宽度不应适应包含的文本,但可由用户调整大小(或准确地说是布局)。如果文本对于 QLabel
的宽度而言太长,则应简单地对其进行剪裁。
这个问题在某种程度上与
How to make QLabel expand width geometry to accommodate text. However, the content of that question didn't help me. Neither did Setting text on a QLabel in a layout, doesn't resize.
背景
QLabel
将显示来自另一个系统的标识符(单个单词)。有时这些标识符每秒变化多次,这使得整个布局闪烁。 QLabel
是垂直停靠栏的一部分,因此停靠栏的宽度会闪烁。
另一方面,应由用户决定可以看到多少标识符 s/he。所以我想允许用户更改扩展坞的宽度,以便 QLabel
的宽度适应它。
解决方案尝试
为了实现这一点,我将水平大小策略设置为 QSizePolicy::Preferred
并从 QLabel
派生了我自己的标签 class,其中我已将 sizeHint()
覆盖为 return固定大小。但这并没有改变行为。
我知道我可以应用 QFontMetrics
来计算文本的宽度,然后将其剪切以适合 QLabel
宽度。但这似乎不是正确的解决方案,特别是因为我希望在最后一个字母不完全适合时将其本身剪掉,以便为用户提供标识符太长而无法显示的线索。
版本
- Qt 5.5.1
- 海湾合作委员会 5.4.0
- 全部来自当前 Ubuntu 16.04 存储库
我想我找到了一个相当肮脏的解决方案来解决你的问题,它可能会导致更多问题,但你可以尝试一下。它只是阻止 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;
}
}
制作您自己的标签 class,扩展 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
重写的方法中。这里重要的是手头有字体指标,可以在不更改文本 属性 本身的情况下即时决定必须显示多少文本(我在部分显示的文本末尾添加了省略号)。只需将此 class 的实例添加到停靠栏内的垂直布局。我认为它可以工作。
缩放文本不是一个好主意,因为缩放后的文本在长字符串和小标签的情况下几乎不可见。作为替代方案,我会将我的标签放在滚动区域中,这样它就可以容纳任何大小的标签而无需调整自身大小(并防止我的 GUI 闪烁)。这是一个简单的例子:
QLabel *label = new QLabel;
label->setAlignment(Qt::AlignTop);
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(label);
label->setText("ThisIsVeryLargeStringThatIWantToPutIntoALabel");
scrollArea->show();
此滚动区域可以放置在可停靠的 window 中。
我需要一个 QLabel
,其宽度不应适应包含的文本,但可由用户调整大小(或准确地说是布局)。如果文本对于 QLabel
的宽度而言太长,则应简单地对其进行剪裁。
这个问题在某种程度上与 How to make QLabel expand width geometry to accommodate text. However, the content of that question didn't help me. Neither did Setting text on a QLabel in a layout, doesn't resize.
背景
QLabel
将显示来自另一个系统的标识符(单个单词)。有时这些标识符每秒变化多次,这使得整个布局闪烁。 QLabel
是垂直停靠栏的一部分,因此停靠栏的宽度会闪烁。
另一方面,应由用户决定可以看到多少标识符 s/he。所以我想允许用户更改扩展坞的宽度,以便 QLabel
的宽度适应它。
解决方案尝试
为了实现这一点,我将水平大小策略设置为 QSizePolicy::Preferred
并从 QLabel
派生了我自己的标签 class,其中我已将 sizeHint()
覆盖为 return固定大小。但这并没有改变行为。
我知道我可以应用 QFontMetrics
来计算文本的宽度,然后将其剪切以适合 QLabel
宽度。但这似乎不是正确的解决方案,特别是因为我希望在最后一个字母不完全适合时将其本身剪掉,以便为用户提供标识符太长而无法显示的线索。
版本
- Qt 5.5.1
- 海湾合作委员会 5.4.0
- 全部来自当前 Ubuntu 16.04 存储库
我想我找到了一个相当肮脏的解决方案来解决你的问题,它可能会导致更多问题,但你可以尝试一下。它只是阻止 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;
}
}
制作您自己的标签 class,扩展 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
重写的方法中。这里重要的是手头有字体指标,可以在不更改文本 属性 本身的情况下即时决定必须显示多少文本(我在部分显示的文本末尾添加了省略号)。只需将此 class 的实例添加到停靠栏内的垂直布局。我认为它可以工作。
缩放文本不是一个好主意,因为缩放后的文本在长字符串和小标签的情况下几乎不可见。作为替代方案,我会将我的标签放在滚动区域中,这样它就可以容纳任何大小的标签而无需调整自身大小(并防止我的 GUI 闪烁)。这是一个简单的例子:
QLabel *label = new QLabel;
label->setAlignment(Qt::AlignTop);
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(label);
label->setText("ThisIsVeryLargeStringThatIWantToPutIntoALabel");
scrollArea->show();
此滚动区域可以放置在可停靠的 window 中。