如何在Qt中自动增加/减少标签中的文本大小 [英] How to automatically increase/decrease text size in label in Qt

查看:87
本文介绍了如何在Qt中自动增加/减少标签中的文本大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Qt application where I have a textedit and a label. When a user presses the button, the textedit text should be displayed on label. For the label I have set few properties like word wrap is enabled and horizontal and vertically it is aligned center. Below is the screenshot :

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

Now I have to automatically adjust the size of the text in label so that if someone enters a large string, then it should fit inside the label, that means size of text should decrease. And if the text string is small, then size should increase automatically to fill up the complete label. Currently if I am typing it the large string, it looks like something:

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

As you can see, in the above image, text is moving out of the label. It should remain inside the label.

如何在应用程序中检测文本是否移出标签高度&宽度.然后如何减小文字大小.我希望大小在字符串较小时自动增加,在字符串较大时减小以填满整个标签.QT是否提供任何课程或其他课程?请提供任何帮助或示例.谢谢.

How to detect in application if the text is moving out of the label height & width. Then how to reduce the text size. I want the size to automatically increase if the string is small and decrease it string is large to fill up the complete label. Is there any class or something provided in QT. Any help or example please. Thanks.

使用下面的代码,我能够减小文本大小以适合标签宽度,但不能使文本多行显示.

With the below code I am able to reduce the size of text to fit inside the label width but not able to make the text multi line.

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);

推荐答案

您(安德鲁·S·安德鲁)解决了它,就像我建议的一样(只是陈述,但没有批评者).您自己做了自动换行.

You (S. Andrew) solved it a little bit different like I proposed (just a statement but not critics). You did the word wrapping by yourself.

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

I wrote a minimal complete application to check how the Qt internal word wrapping can be used for your problem:

// 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();
}

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

Compiled and tested with VS2013 / Qt 5.6 on Windows 10 (64 bit):

在使用此测试应用程序时,我认识到文本并非总是完美地适合 QLabel .我试图改善与 QRect rectLbl = contentsRect(); 交换 QRect rectLbl = rect(); 的代码.这使它更好,但仍不完美.似乎有必要进行一些微调(开发开始变得努力).(请参阅文本末尾的更新.)

When playing around with this test application, I recognized that the text fits not everytimes perfectly into the QLabel. I tried to improve the code exchanging QRect rectLbl = rect(); with QRect rectLbl = contentsRect();. This made it better but still not perfect. It seems there is some finetuning necessary (where the development starts to become effort). (See update at end of text.)

实际上,不需要派生 QLabel .在我的第一个实现中, layout()是一个以 QLabel& const QString& 作为参数的函数.

Actually, it would not be necessary to derive QLabel. In my first implementation, layout() was a function with QLabel& and const QString& as parameters.

在字体大小管理工作之后,我还打算考虑调整大小事件.仔细搜索一下,我找到了应用事件过滤器的解决方案.但是,事件过滤器在处理事件之前称为 ,但我需要之后.最后,我决定继承 QLabel 并重载 QLabel :: resizeEvent()以使事情简单.

After I got the font size management working, I intended to consider resize events also. Googling a little bit, I found the solution to apply event filters. However, event filters are called before the event is processed but I need after. Finally, I decided to inherit QLabel and to overload QLabel::resizeEvent() to keep things simple.

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

Btw. I noticed it is even not necessary to set

高度最终达到非常大的值

height eventually to a very large value

正如我在前面的评论中所建议的.看来 QFontMetrics :: boundingRect(const QRect&int标志,...) 在启用 Qt :: TextWordWrap 时自动增加高度,以保持所需的宽度.

as I suggested in a comment earlier. It seems that QFontMetrics::boundingRect(const QRect &rect, int flags, ...) increases the height automa[gt]ically to keep required width when Qt::TextWordWrap is enabled.

更新:

@annacarolina鼓励我对这个问题进行更深入的研究,因为有时会选择较大的字体.在 Label :: layout()中进行的一些调试发现,有时计算出的 rect 看起来像是包装了可视输出的未包装文本.这使我对 rectLbl 的正确性感到怀疑.因此,我从woboq.org上的 qlabel.cpp开始./a>,但实际上是Qt论坛 QLabel:将字体大小调整为contentsRect 提供了最终的提示,引导我进入 QLabelPrivate :: documentRect() (实际上还是在我已经在寻找启示的woboq.org上).因此,我在类中添加了 Label :: documentRect()方法.这样可以使结果好得多(尽管我并不完全相信完美").

@annacarolina encouraged me to investigate a little bit deeper into this issue that font size is sometimes choosen to large. Some debugging in Label::layout() uncovered that sometimes computed rect looked like unwrapped text where visual output was wrapped. This made me suspiciuous about correctness of the rectLbl. Thus, I started in qlabel.cpp on woboq.org but actually the Qt forum QLabel: Resize font to contentsRect provided the final hint which leaded me to QLabelPrivate::documentRect() (actually again on woboq.org where I already had looked for enlightment). Thus, I added a method Label::documentRect() to my class. This makes results much better (although I'm not fully convinced about "perfect").

这篇关于如何在Qt中自动增加/减少标签中的文本大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆