[英]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進行編譯和測試:
在玩這個測試應用程序時,我認識到文本並不適合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.