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

新手上路,请多包涵

我有一个 Qt 应用程序,其中有一个 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);

原文由 S Andrew 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 716
2 个回答

你(S. Andrew)解决了它有点不同,就像我提议的那样(只是一个声明,而不是批评者)。你自己做了自动换行。

我编写了一个最小的完整应用程序来检查如何使用 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();
}

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

testQFontMetric.exe 的快照

在玩这个测试应用程序时,我意识到文本并不总是完全适合 QLabel 。我试图改进代码交换 QRect rectLbl = rect();QRect rectLbl = contentsRect(); 。这使它变得更好,但仍然不完美。似乎有必要进行一些微调(开发开始变得努力)。 ( 见文末更新。

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

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

顺便提一句。我注意到它甚至没有必要设置

高度最终达到一个非常大的值

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

更新:

@annacarolina 鼓励我对这个问题进行更深入的调查,即有时会选择较大的字体。 Label::layout() 中的一些调试发现有时计算出来的 rect 看起来像是包装了视觉输出的未包装文本。这让我怀疑 rectLbl 的正确性。因此,我从 woboq.org 上的 qlabel.cpp 开始,但实际上 Qt 论坛 QLabel: Resize font to contentsRect 提供了最终提示,导致我进入 QLabelPrivate::documentRect() (实际上又是在我已经看过的 woboq.org 上为启蒙)。因此,我在课堂上添加了一个方法 Label::documentRect() 。这使结果更好(尽管我并不完全相信“完美”)。

原文由 Scheff‘s Cat 发布,翻译遵循 CC BY-SA 3.0 许可协议

在下面的代码中,我正在创建一个逻辑,首先获取字符串中的所有单词。然后我在 QList<QString> data 中附加单词并检查附加单词的宽度是否小于标签的宽度。如果宽度超过标签的宽度,那么我使用 \n 打破它。所以通过这种方式,我制作了一个总宽度在标签宽度附近的子字符串列表,并将其保存在列表中。然后我计算存储在列表中的子字符串的宽度,然后减小它的字体大小,直到它的总宽度小于标签的宽度。在此之后,我将其显示在标签上。

 QList<QString> data;
CountWords Word;
ui->label->clear();
QString string = ui->textEdit->toPlainText();   //Getting data from textEdit
QStringList count = Word.GetWords(string);   //Here I get the list of words in string
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 size,fontSize;
QString temp = ui->label->text();
int last = count.size();
//Saving the words in QList
for(int i=0;i<count.size();i++)
{
    temp.append(count[i]+" ");
    size = fm.width(temp);
    if(size > 870)
    {
        temp.append("\n");
        data << temp;
        //data.append(temp);
        temp.clear();
    }
    if((last-1)==i)
    {
         subString.append("\n");
         data << subString;
         subString.clear();
    }
}

 //decreasing the font size
QList<int> wide;
for(int i=0;i<data.size();i++)
{
    wide << fm.width(data[i]);
    while(wide[i] >= 870)
    {
        fontSize = ui->label->font().pointSize() - 1;
        QFont newFont("Arial",fontSize);
        QFontMetrics nfm(newFont);
        ui->label->setFont(newFont);
        wide[i] = 0;
        wide[i] = nfm.width(data[i]);
    }

}

//Finally displaying it on label
QString labelData;
for(int i=0;i<data.size();i++)
{
    labelData = ui->label->text();
    labelData.append(data[i]);
    ui->label->setText(labelData);

}

原文由 S Andrew 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题