如何让文字填满所有QLabel的space?
How to make the text fill all the QLabel's space?
我正在从事 PyQt5 项目,但也很乐意阅读 C++/Qt 答案,因为 C++ 解决方案也可以在 Python 上工作。
我有一个水平布局的 MainWindow,里面有一个 QLabel。
我的 QLabel 的大小策略是 "Expanding",因此我所有的 window 都由 QLabel 填充。
但是,我的 QLabel 显示的文本并没有改变它的大小。我希望文本在 window 增长时增长,并且在 QLabel 大小的限制内尽可能大。
我听说过 QWidget::adjustSize()
但不知道如何使用它。
QtDesigner 上我的 QLabel 的选项 scaledContents
没有做任何事情,所以我想它只在使用 pixmap 时有用。
目前,我的解决方案是重新实现 window 的 resizeEvent()
方法,并使用 setFont()
更改标签的字体大小。但我认为必须有一个更简单的解决方案。而且,我的resizeEvent()
方法不是很好,因为我在myWindowWidth* myWindowHeight
和myTextFontSize
之间建立了线性关系,因此当只有myWindowWidth
增加时,myTextFontSize
增加并强制myWindowHeight
要增加,不好。
这是一个可能指向解决方案的快速草图。可以在任何标签上安装事件过滤器,而不是从标签派生,以使其文本填充可用 space。该过滤器使用现有的 scaledContents
属性,并将其适用性扩展到文本内容。
使用牛顿算法调整标签的字体大小以填充可用space。需要进行一些调整才能使其与启用自动换行的标签一起使用;字体大小永远不会超过适合的大小。
// https://github.com/KubaO/Whosebugn/tree/master/questions/label-text-size-36575192
#include <QtWidgets>
class LabelStretcher : public QObject {
Q_OBJECT
public:
LabelStretcher(QObject * parent = 0) : QObject(parent) {
apply(qobject_cast<QLabel*>(parent));
}
void apply(QLabel * label) { if (label) label->installEventFilter(this); }
protected:
bool eventFilter(QObject * obj, QEvent * ev) Q_DECL_OVERRIDE {
if (ev->type() != QEvent::Resize) return false;
auto label = qobject_cast<QLabel*>(obj);
if (!label || label->text().isEmpty() || !label->hasScaledContents()) return false;
qDebug() << "pre: " << label->minimumSizeHint() << label->sizeHint() << label->size();
static auto dSize = [](const QSize & inner, const QSize & outer) -> int {
auto dy = inner.height() - outer.height();
auto dx = inner.width() - outer.width();
return std::max(dx, dy);
};
static auto f = [](qreal fontSize, QLabel * label) -> qreal {
auto font = label->font();
font.setPointSizeF(fontSize);
label->setFont(font);
auto d = dSize(label->sizeHint(), label->size());
qDebug() << "f:" << fontSize << "d" << d;
return d;
};
static auto df = [](qreal fontSize, QLabel * label) -> qreal {
if (fontSize < 1.0) fontSize = 1.0;
return f(fontSize + 0.5, label) - f(fontSize - 0.5, label);
};
// Newton's method
auto font = label->font();
auto fontSize = font.pointSizeF();
int i;
for (i = 0; i < 5; ++i) {
auto d = df(fontSize, label);
qDebug() << "d:" << d;
if (d < 0.1) break;
fontSize -= f(fontSize, label)/d;
}
font.setPointSizeF(fontSize);
label->setFont(font);
qDebug() << "post:" << i << label->minimumSizeHint() << label->sizeHint() << label->size();
return false;
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QLabel label{"Hello There!"};
label.setScaledContents(true);
label.show();
LabelStretcher stretch(&label);
return app.exec();
}
#include "main.moc"
我正在从事 PyQt5 项目,但也很乐意阅读 C++/Qt 答案,因为 C++ 解决方案也可以在 Python 上工作。
我有一个水平布局的 MainWindow,里面有一个 QLabel。
我的 QLabel 的大小策略是 "Expanding",因此我所有的 window 都由 QLabel 填充。
但是,我的 QLabel 显示的文本并没有改变它的大小。我希望文本在 window 增长时增长,并且在 QLabel 大小的限制内尽可能大。
我听说过 QWidget::adjustSize()
但不知道如何使用它。
QtDesigner 上我的 QLabel 的选项 scaledContents
没有做任何事情,所以我想它只在使用 pixmap 时有用。
目前,我的解决方案是重新实现 window 的 resizeEvent()
方法,并使用 setFont()
更改标签的字体大小。但我认为必须有一个更简单的解决方案。而且,我的resizeEvent()
方法不是很好,因为我在myWindowWidth* myWindowHeight
和myTextFontSize
之间建立了线性关系,因此当只有myWindowWidth
增加时,myTextFontSize
增加并强制myWindowHeight
要增加,不好。
这是一个可能指向解决方案的快速草图。可以在任何标签上安装事件过滤器,而不是从标签派生,以使其文本填充可用 space。该过滤器使用现有的 scaledContents
属性,并将其适用性扩展到文本内容。
使用牛顿算法调整标签的字体大小以填充可用space。需要进行一些调整才能使其与启用自动换行的标签一起使用;字体大小永远不会超过适合的大小。
// https://github.com/KubaO/Whosebugn/tree/master/questions/label-text-size-36575192
#include <QtWidgets>
class LabelStretcher : public QObject {
Q_OBJECT
public:
LabelStretcher(QObject * parent = 0) : QObject(parent) {
apply(qobject_cast<QLabel*>(parent));
}
void apply(QLabel * label) { if (label) label->installEventFilter(this); }
protected:
bool eventFilter(QObject * obj, QEvent * ev) Q_DECL_OVERRIDE {
if (ev->type() != QEvent::Resize) return false;
auto label = qobject_cast<QLabel*>(obj);
if (!label || label->text().isEmpty() || !label->hasScaledContents()) return false;
qDebug() << "pre: " << label->minimumSizeHint() << label->sizeHint() << label->size();
static auto dSize = [](const QSize & inner, const QSize & outer) -> int {
auto dy = inner.height() - outer.height();
auto dx = inner.width() - outer.width();
return std::max(dx, dy);
};
static auto f = [](qreal fontSize, QLabel * label) -> qreal {
auto font = label->font();
font.setPointSizeF(fontSize);
label->setFont(font);
auto d = dSize(label->sizeHint(), label->size());
qDebug() << "f:" << fontSize << "d" << d;
return d;
};
static auto df = [](qreal fontSize, QLabel * label) -> qreal {
if (fontSize < 1.0) fontSize = 1.0;
return f(fontSize + 0.5, label) - f(fontSize - 0.5, label);
};
// Newton's method
auto font = label->font();
auto fontSize = font.pointSizeF();
int i;
for (i = 0; i < 5; ++i) {
auto d = df(fontSize, label);
qDebug() << "d:" << d;
if (d < 0.1) break;
fontSize -= f(fontSize, label)/d;
}
font.setPointSizeF(fontSize);
label->setFont(font);
qDebug() << "post:" << i << label->minimumSizeHint() << label->sizeHint() << label->size();
return false;
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QLabel label{"Hello There!"};
label.setScaledContents(true);
label.show();
LabelStretcher stretch(&label);
return app.exec();
}
#include "main.moc"