我有一个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);
答案 0 :(得分:6)
你(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进行编译和测试:
在玩这个测试应用程序时,我发现文本并非完全适合QLabel
。我尝试使用QRect rectLbl = rect();
改进代码交换QRect rectLbl = contentsRect();
。这使它变得更好但仍然不完美。似乎有一些必要的微调(开发开始变得努力)。 (请参见文本末尾的更新。)
实际上,没有必要派生QLabel
。在我的第一个实现中,layout()
是一个以QLabel&
和const QString&
为参数的函数。
在我完成字体大小管理后,我还打算考虑调整大小事件。谷歌搜索了一下,我找到了应用事件过滤器的解决方案。但是,事件过滤器在处理事件之前被称为,但我需要在之后。最后,我决定继承QLabel
并重载QLabel::resizeEvent()
以保持简单。
顺便说一下。我注意到甚至没有必要设置
正如我之前在评论中所建议的那样。高度最终达到非常大的值
QFontMetrics::boundingRect(const QRect &rect, int flags, ...)
似乎qlabel.cpp on woboq.org在启用Qt::TextWordWrap
时自动增加高度以保持所需的宽度。
更新
@annacarolina鼓励我更深入地研究这个问题,即字体大小有时会被选择为大。 Label::layout()
中的一些调试发现,有时计算的rect
看起来像是包装了视觉输出的未包装文本。这使我怀疑rectLbl
的正确性。因此,我从QLabel: Resize font to contentsRect开始,但实际上Qt论坛QLabelPrivate::documentRect()
提供了最后的提示,引导我https://docs.npmjs.com/cli/install(实际上再次在woboq.org,我已经寻找了启发)。因此,我向我的班级添加了一个方法Label::documentRect()
。这使得结果更好(尽管我并不完全相信“完美”)。
答案 1 :(得分:1)
在下面的代码中,我正在制作一个逻辑,我首先得到字符串中的所有单词。然后我在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);
}
答案 2 :(得分:1)
在努力解决这个问题后,我创建了DynamicFontSizeLabel和DynamicFontSizePushButton小部件。希望它有所帮助。
https://github.com/jonaias/DynamicFontSizeWidgets/
感谢Scheff的一些灵感。