簡體   English   中英

如何在Qt中自動增加/減少標簽中的文字大小

[英]How to automatically increase/decrease text size in label in 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);

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

在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看起來像是包裝了視覺輸出的未包裝文本。 這讓我suspiciuous有關的正確性rectLbl 因此,我從woboq.org上的qlabel.cpp開始,但實際上Qt論壇QLabel:將字體調整為contentsRect提供了最終提示,引導我到QLabelPrivate::documentRect() (實際上再次在woboq.org上我已經找過了啟示)。 因此,我在我的類中添加了一個方法Label::documentRect() 這使得結果更好(盡管我並不完全相信“完美”)。

在下面的代碼中,我正在制作一個邏輯,我首先得到字符串中的所有單詞。 然后我在QList<QString> data附加單詞並檢查附加單詞的寬度是否小於標簽的寬度。 如果寬度超過標簽的寬度,那么我使用\\n打破它。 因此,通過這種方式,我創建了一個子字符串列表,其總寬度大約是標簽的寬度,並將其保存在List中。 然后我計算存儲在列表中的子字符串的寬度,然后減小其字體大小,直到其總寬度小於標簽的寬度。 在此之后,我將其顯示在標簽上。

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

}

在努力解決這個問題之后,我創建了DynamicFontSizeLabel和DynamicFontSizePushButton小部件。 希望能幫助到你。

https://github.com/jonaias/DynamicFontSizeWidgets/

感謝Scheff的一些靈感。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM