如何在Qt中自动增加/减少标签中的文字大小

S A*_*rew 3 c++ qt

我有一个Qt应用程序,我有一个textedit和一个标签.当用户按下按钮时,textedit文本应显示在标签上.对于标签我设置了一些属性,如启用了自动换行,水平和垂直,它是对齐的中心.以下是截图:

在此输入图像描述

现在我必须自动调整标签中文本的大小,这样如果有人输入一个大字符串,那么它应该适合标签内部,这意味着文本的大小应该减少.如果文本字符串很小,那么大小应该自动增加以填满整个标签.目前,如果我输入大字符串,它看起来像是:

在此输入图像描述

如您所见,在上图中,文本正在移出标签.它应该保留在标签内.

如何在应用程序中检测文本是否移出标签高度和宽度.那么如何减少文字大小.如果字符串很小,我希望大小自动增加,减少字符串很大,以填满整个标签.QT中是否提供任何课程或内容.任何帮助或示例请.谢谢.

编辑:使用下面的代码我可以减少文本的大小以适应标签宽度,但不能使文本多行.

QString string = ui->textEdit->toPlainText();   //Getting data from textEdit

ui->label->setAlignment(Qt::AlignCenter);   //Aligning label text to center
QFont f("Arial",50);        //Setting the default font size to 50
QFontMetrics fm(f);
ui->label->setFont(f);      //Setting the font to the label
int width = fm.width(string);   //Getting the width of the string
int size;
while(width >= 870)     //870 is the max width of label
{

    size = ui->label->font().pointSize()-1;     //Reduce font size by 1
    QFont newFont("Arial",size);            
    QFontMetrics nfm(newFont);          
    ui->label->setFont(newFont);        //Set the new font with new size
    width = nfm.width(string);      //Get the new width
}
ui->label->setText(string);
Run Code Online (Sandbox Code Playgroud)

Sch*_*eff 8

你(S.安德鲁)解决了它有点不同,就像我提出的那样(只是一个声明而不是评论家).你自己做了包装.

我写了一个最小的完整应用程序,以检查Qt内部自动换行如何用于您的问题:

// standard C++ header:
#include <iostream>
#include <string>

// Qt header:
#include <QApplication>
#include <QBoxLayout>
#include <QFrame>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QMainWindow>
#include <QStyle>

using namespace std;

class Label: public QLabel {

  public:
    void layout();
    QRect documentRect(); // borrowed from QLabelPrivate
  protected:
    virtual void resizeEvent(QResizeEvent *pQEvent);
};

QRect Label::documentRect()
{
  QRect rect = contentsRect();
  int m = margin(); rect.adjust(m, m, -m, -m);
  layoutDirection();
  const int align
    = QStyle::visualAlignment(layoutDirection(), QLabel::alignment());
  int i = indent();
  if (i < 0 && frameWidth()) { // no indent, but we do have a frame
    m = fontMetrics().width(QLatin1Char('x')) / 2 - m;
  }
  if (m > 0) {
    if (align & Qt::AlignLeft) rect.setLeft(rect.left() + m);
    if (align & Qt::AlignRight) rect.setRight(rect.right() - m);
    if (align & Qt::AlignTop) rect.setTop(rect.top() + m);
    if (align & Qt::AlignBottom) rect.setBottom(rect.bottom() - m);
  }
  return rect;
}

void Label::layout()
{
  // get initial settings
  QString text = this->text();
  QRect rectLbl = documentRect(); // wrong: contentsRect();
  QFont font = this->font();
  int size = font.pointSize();
  QFontMetrics fontMetrics(font);
  QRect rect = fontMetrics.boundingRect(rectLbl,
    Qt::TextWordWrap, text);
  // decide whether to increase or decrease
  int step = rect.height() > rectLbl.height() ? -1 : 1;
  // iterate until text fits best into rectangle of label
  for (;;) {
    font.setPointSize(size + step);
    QFontMetrics fontMetrics(font);
    rect = fontMetrics.boundingRect(rectLbl,
      Qt::TextWordWrap, text);
    if (size <= 1) {
      cout << "Font cannot be made smaller!" << endl;
      break;
    }
    if (step < 0) {
      size += step;
      if (rect.height() < rectLbl.height()) break;
    } else {
      if (rect.height() > rectLbl.height()) break;
      size += step;
    }
  }
  // apply result of iteration
  font.setPointSize(size);
  setFont(font);
}

void Label::resizeEvent(QResizeEvent *pQEvent)
{
  QLabel::resizeEvent(pQEvent);
  layout();
}

int main(int argc, char **argv)
{
  cout << QT_VERSION_STR << endl;
  // main application
#undef qApp // undef macro qApp out of the way
  QApplication qApp(argc, argv);
  // setup GUI
  QMainWindow qWin;
  QGroupBox qGBox;
  QVBoxLayout qBox;
  Label qLbl;
  qLbl.setFrameStyle(Label::Box);
  qLbl.setFrameShadow(Label::Sunken);
  qLbl.setWordWrap(true);
  qBox.addWidget(&qLbl, 1);
  QLineEdit qTxt;
  qBox.addWidget(&qTxt, 0);
  qGBox.setLayout(&qBox);
  qWin.setCentralWidget(&qGBox);
  qWin.show();
  // install signal handlers
  QObject::connect(&qTxt, &QLineEdit::editingFinished,
    [&qTxt, &qLbl]() {
      QString text = qTxt.text();
      qLbl.setText(text);
      qLbl.layout();
    });
  return qApp.exec();
}
Run Code Online (Sandbox Code Playgroud)

在Windows 10(64位)上使用VS2013/Qt 5.6进行编译和测试:

testQFontMetric.exe的快照

在玩这个测试应用程序时,我认识到文本并不适合每次都完美QLabel.我试图提高代码交换QRect rectLbl = rect();QRect rectLbl = contentsRect();.这使它变得更好但仍然不完美.似乎有一些必要的微调(开发开始变得努力).(参见文本末尾的更新.)

实际上,没有必要推导出来QLabel.在我的第一个实现中,layout()是一个带有QLabel&const QString&作为参数的函数.

在我完成字体大小管理后,我打算考虑调整大小事件.谷歌搜索了一下,我找到了应用事件过滤器的解决方案.但是,事件过滤器在事件处理之前被调用,但我需要在之后.最后,我决定继承QLabel并重载QLabel::resizeEvent()以保持简单.

顺便说一句.我注意到甚至没有必要设置

高度最终达到很大的价值

正如我之前在评论中所建议的那样.QFontMetrics::boundingRect(const QRect &rect, int flags, ...)Qt::TextWordWrap启用时,似乎自动地增加高度以保持所需的宽度.

更新:

@annacarolina鼓励我更深入地研究这个问题,即字体大小有时会被选择为大.有些Label::layout()计算rect看起来像打开视觉输出被包装的未包装文本.这让我怀疑这个问题的正确性rectLbl.因此,我开始在woboq.org上的qlabel.cpp,但实际上Qt论坛QLabel:调整大小字体到contentsRect提供了最终的提示,导致我QLabelPrivate::documentRect()(实际上再次在woboq.org上我已经寻找启发).因此,我Label::documentRect()在课堂上添加了一个方法.这使得结果更好(尽管我并不完全相信"完美").