调整QT的QTextEdit大小以匹配文本高度:maximumViewportSize()

Aar*_*ron 11 qt qtextedit

我试图在包含几个QT小部件的表单中使用QTextEdit小部件.表单本身位于QScrollArea内,该窗口是窗口的中心窗口小部件.我的意图是,任何必要的滚动都将在主QScrollArea中进行(而不是在任何小部件内部),并且内部的任何小部件将自动调整其高度以保存其内容.

我试图用QTextEdit实现高度的自动调整,但遇到了一个奇怪的问题.我创建了一个QTextEdit的子类,并重新实现了sizeHint(),如下所示:

QSize OperationEditor::sizeHint() const {
  QSize sizehint = QTextBrowser::sizeHint();
  sizehint.setHeight(this->fitted_height);
  return sizehint;
}
Run Code Online (Sandbox Code Playgroud)

this-> fitted_height通过连接到QTextEdit的"contentsChanged()"信号的插槽保持最新:

void OperationEditor::fitHeightToDocument() {
      this->document()->setTextWidth(this->viewport()->width());
      QSize document_size(this->document()->size().toSize());
      this->fitted_height = document_size.height();
      this->updateGeometry();
}
Run Code Online (Sandbox Code Playgroud)

QTextEdit子类的大小策略是:

this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
Run Code Online (Sandbox Code Playgroud)

我在阅读这篇文章后采用了这种方法.

这是我的问题:

随着QTextEdit逐渐调整大小以填充窗口,无论sizeHint()返回什么高度,它都会停止变大并开始在QTextEdit中滚动.如果我最初让sizeHint()返回一些大的常数,那么QTextEdit非常大,并且很好地包含在外部QScrollArea中,正如人们所期望的那样.但是,如果sizeHint逐渐调整QTextEdit的大小而不是仅仅让它开始变大,那么当它填充当前窗口并开始滚动而不是增长时,它会突然出现.

我已经跟踪过这个问题,无论我的sizeHint()返回什么,它都不会将QTextEdit的大小调整为大于从QAbstractScrollArea继承的maximumViewportSize()返回的值.请注意,这与viewport() - > maximumSize()的数量不同.我无法弄清楚如何设置该值.

查看QT的源代码,maximumViewportSize()返回"视口的大小,好像滚动条没有有效的滚动范围".此值基本上计算为窗口小部件的当前大小减去(2*frameWidth +边距)加上任何滚动条宽度/高度.这对我来说没有多大意义,而且我不清楚为什么这个数字会以某种方式用于取代子类的sizeHint()实现.而且,单个"frameWidth"整数用于计算宽度和高度似乎很奇怪.

任何人都可以对此有所了解吗?我怀疑我对QT布局引擎的不了解是这里的责任.

编辑:在最初发布之后,我有想法重新实现maximumViewportSize()以返回与sizeHint()相同的东西.不幸的是,这不起作用,因为我仍然有同样的问题.

Aar*_*ron 10

我已经解决了这个问题.为了让它发挥作用,我必须做两件事:

  1. 走向窗口小部件层次结构并确保所有大小策略都有意义,以确保如果任何子窗口小部件想要大/小,那么父窗口小部件将希望是相同的东西.

  2. 这是修复的主要来源.事实证明,由于QTextEdit位于QFrame中,而QFrame是QScrollArea中的主要窗口小部件,因此QScrollArea具有一个约束,即除非"widgetResizable"属性为true,否则它不会调整内部窗口小部件的大小.该文档的文档如下:http://doc.qt.io/qt-4.8/qscrollarea.html#widgetResizable-prop.在我玩这个设置并让它工作之前,我不清楚文档.从文档中,似乎此属性仅处理主滚动区域要调整窗口小部件(即从父窗口到子窗口)的时间.它实际上意味着如果滚动区域中的主窗口小部件想要调整大小(即子节点到父节点),则必须将此设置设置为true.

因此,故事的寓意是QTextEdit代码在覆盖sizeHint时是正确的,但QScrollArea忽略了从主框架的sizeHint返回的值.

好极了!有用!

  • 亚伦,可以详细说明你的解决方案吗?我似乎无法访问与QTextEdit关联的QScrollArea.你能解释一下,给定QTextEdit你设置的widgetResizable属性是什么?即他们是如何联系的?QTextEdit实际上是从QAbstractScrollArea派生的,它没有setWidgetResizable属性(我在Qt 4.7中).谢谢这真让我烦恼! (2认同)
  • 我也有类似的问题,但有QPlainTextEdit,所以如果有人有QPlainTextEdit的问题 - 请注意,它有不同的文档布局管理器,它报告文件() - > size()的行数,而不是像素数.您必须从窗口小部件中获取QFont,使用QFontMetrics :: lineSpacing()并将其乘以document() - > size()以获得高度(以像素为单位).您可以在QPlainTextEdit类的一般描述中准备好它. (2认同)