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

发布于 2024-09-06 00:02:28 字数 1727 浏览 8 评论 0原文

我正在尝试在包含多个 QT 小部件的表单中使用 QTextEdit 小部件。表单本身位于 QScrollArea 内,它是窗口的中央小部件。我的意图是,任何必要的滚动都将发生在主 QScrollArea 中(而不是在任何小部件内),并且内部的任何小部件将自动调整其高度以容纳其内容。

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

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

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();
}

QTextEdit 的大小策略子类是:

this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);

我在阅读

我的问题:

随着 QTextEdit 逐渐调整大小以填充窗口,它会停止变大并开始在 QTextEdit 内滚动,无论从 sizeHint() 返回什么高度。如果我最初让 sizeHint() 返回一些大的常量,那么 QTextEdit 就会非常大,并且正如人们所期望的那样,很好地包含在外部 QScrollArea 中。然而,如果 sizeHint 逐渐调整 QTextEdit 的大小,而不是一开始就让它变得很大,那么当它填满当前窗口并开始滚动而不是增长时,它就会达到顶峰。

我发现这个问题是,无论我的 sizeHint() 返回什么,它都不会将 QTextEdit 的大小调整为大于从 MaximumViewportSize() 返回的值,该值是从 QAbstractScrollArea 继承的。请注意,这与 viewport()->maximumSize() 不同。我无法弄清楚如何设置该值。

查看 QT 的源代码,maximumViewportSize() 返回“视口的大小,就好像滚动条没有有效的滚动范围一样”。该值基本上计算为小部件的当前大小减去(2 * 框架宽度 + 边距)加上任何滚动条宽度/高度。这对我来说没有多大意义,并且我不清楚为什么该数字会在任何地方以取代子类的 sizeHint() 实现的方式使用。另外,在计算宽度和高度时使用单个“frameWidth”整数似乎很奇怪。

谁能解释一下吗?我怀疑我对 QT 布局引擎的理解不佳是罪魁祸首。

编辑:最初发布此内容后,我想到重新实现 MaximumViewportSize() 以返回与 sizeHint() 相同的内容。不幸的是,这不起作用,因为我仍然遇到同样的问题。

I am trying to use a QTextEdit widget inside of a form containing several QT widgets. The form itself sits inside a QScrollArea that is the central widget for a window. My intent is that any necessary scrolling will take place in the main QScrollArea (rather than inside any widgets), and any widgets inside will automatically resize their height to hold their contents.

I have tried to implement the automatic resizing of height with a QTextEdit, but have run into an odd issue. I created a sub-class of QTextEdit and reimplemented sizeHint() like this:

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

this->fitted_height is kept up-to-date via this slot that is wired to the QTextEdit's "contentsChanged()" signal:

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

The size policy of the QTextEdit sub-class is:

this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);

I took this approach after reading this post.

Here is my problem:

As the QTextEdit gradually resizes to fill the window, it stops getting larger and starts scrolling within the QTextEdit, no matter what height is returned from sizeHint(). If I initially have sizeHint() return some large constant number, then the QTextEdit is very big and is contained nicely within the outer QScrollArea, as one would expect. However, if sizeHint gradually adjusts the size of the QTextEdit rather than just making it really big to start, then it tops out when it fills the current window and starts scrolling instead of growing.

I have traced this problem to be that, no matter what my sizeHint() returns, it will never resize the QTextEdit larger than the value returned from maximumViewportSize(), which is inherited from QAbstractScrollArea. Note that this is not the same number as viewport()->maximumSize(). I am unable to figure out how to set that value.

Looking at QT's source code, maximumViewportSize() is returning "the size of the viewport as if the scroll bars had no valid scrolling range." This value is basically computed as the current size of the widget minus (2 * frameWidth + margins) plus any scrollbar widths/heights. This does not make a lot of sense to me, and it's not clear to me why that number would be used anywhere in a way that supercede's the sub-class's sizeHint() implementation. Also, it does seem odd that the single "frameWidth" integer is used in computing both the width and the height.

Can anyone please shed some light on this? I suspect that my poor understanding of QT's layout engine is to blame here.

Edit: after initially posting this, I had the idea to reimplement maximumViewportSize() to return the same thing as sizeHint(). Unfortunately, this did not work as I still have the same problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阳光①夏 2024-09-13 00:02:28

我已经解决了这个问题。为了让它工作,我必须做两件事:

  1. 沿着小部件层次结构向上走,并确保所有大小策略都有意义,以确保如果任何子小部件想要变大/变小,那么父小部件就会变大/变小想要成为相同的东西。

  2. 这是修复的主要来源。事实证明,由于 QTextEdit 位于 QScrollArea 中主要小部件的 QFrame 内,因此 QScrollArea 有一个约束,即除非“widgetResizable”属性为 true,否则它不会调整内部小部件的大小。相关文档位于: http://doc.qt.io/ qt-4.8/qscrollarea.html#widgetResizable-prop。直到我尝试了这个设置并让它发挥作用之前,我并不清楚文档。从文档来看,这个属性似乎只处理主滚动区域想要调整小部件大小的时间(即从父级到子级)。它实际上意味着,如果滚动区域中的主小部件想要调整大小(即子级到父级),则必须将此设置设置为 true。

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

耶!有用!

I have solved this issue. There were 2 things that I had to do to get it to work:

  1. Walk up the widget hierarchy and make sure all the size policies made sense to ensure that if any child widget wanted to be big/small, then the parent widget would want to be the same thing.

  2. This is the main source of the fix. It turns out that since the QTextEdit is inside a QFrame that is the main widget in a QScrollArea, the QScrollArea has a constraint that it will not resize the internal widget unless the "widgetResizable" property is true. The documentation for that is here: http://doc.qt.io/qt-4.8/qscrollarea.html#widgetResizable-prop. The documentation was not clear to me until I played around with this setting and got it to work. From the docs, it seems that this property only deals with times where the main scroll area wants to resize a widget (i.e. from parent to child). It actually means that if the main widget in the scroll area wants to ever resize (i.e. child to parent), then this setting has to be set to true.

So, the moral of the story is that the QTextEdit code was correct in overriding sizeHint, but the QScrollArea was ignoring the value returned from the main frame's sizeHint.

Yay! It Works!

简单爱 2024-09-13 00:02:28

您可以尝试设置 minimumSize 属性QTextEdit 来查看是否会强制布局增长。

我不明白 Qt 的大部分布局方案,但设置最小和最大尺寸几乎可以满足我的要求。好吧,无论如何,大多数时候。

You may try setting minimumSize property of the QTextEdit to see if that force the layout to grow.

I don't understand most of Qt's layout scheme but setting minimum and maximum size pretty much does what I want it to do. Well, most of the time anyways.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文