How to make the text fill all the QLabel's space?

谁说我不能喝 提交于 2019-11-27 07:37:46

问题


I am working on a PyQt5 project, but would be happy to read C++/Qt answer as well, because C++ solutions may work on Python too.

I have a MainWindow with a horizontal layout, and a QLabel in it.

My QLabel's size Policy is "Expanding", therefore all my window is filled by the QLabel.

However, the text displayed by my QLabel does not change its size. I would like the text to grow when the window grows, and be as big as possible, in the limit of the QLabel size.

I have heard of QWidget::adjustSize() but could not figure out how to use it. The option scaledContents for my QLabel on QtDesigner does not do anything, so I guess it is only useful for when using pixmap.

For the moment, my solution is to reimplement the resizeEvent() method of my window and change the font size of my label with setFont(). But I think that there must be an easier solution. Moreover, my resizeEvent() method is not very good because I make a linear relation between myWindowWidth* myWindowHeight and myTextFontSize, therefore when only myWindowWidth increase, myTextFontSize increases and forces myWindowHeight to increase, which is bad.


回答1:


This is a quick sketch that might point to a solution. Instead of deriving from a label, an event filter can be installed on any label to make its text fill the available space. The filter uses the existing scaledContents property, and extends its applicability to text content.

The label's font size is adjusted using Newton's algorithm to fill the available space. Some adjustments would be needed to make it work with labels that enable word wrap; the font size should then never overshoot what fits.

// https://github.com/KubaO/stackoverflown/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"


来源:https://stackoverflow.com/questions/36575192/how-to-make-the-text-fill-all-the-qlabels-space

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!