在不需要滚动条的情况下使 QPlainTextEdit 尽可能小

Keeping QPlainTextEdit as small as possible without needing a scroll bar

我有一个 QPlainTextEdit 将包含不同数量的文本 - 有时什么都没有,有时太多以至于它会绕行几十次。我想将 QPlainTextEdit 保持在必要的高度,以保持其所有内容可见。除非完全为空,否则不应有空行。

我已尝试将尺寸政策设置为 MinimumMinimumExpanding,并将最小和最大高度设置为零。没有这些作品的组合;在所有情况下,空的 QPlainTextEdit 大约有四行半高。

唯一似乎将高度降低到 4.5 行限制以下的是 setFixedHeight。但是,如果我这样做,那么我将需要自己计算所需的高度,这首先会破坏使用库的意义。

现在,我能想到的唯一可行的选择是这样的:

def onResize_or_textChanged(...):
  my_text_edit.setHeight(0)
  while my_text_exit has a visible scroll bar:
    my_text_edit.setHeight(my_text_edit.height() + 1)

这显然是一个相当老套的解决方案。

如何使 QPlainTextEdit 保持完整显示其文本所需的最小高度?

解决方案是计算最小高度,以便使用 blockBoundingGeometry():

所有 QTextBlock 都可见
from PyQt5 import QtCore, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.te = QtWidgets.QPlainTextEdit()
        self.te.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.te.updateRequest.connect(self.handle_updateRequest)
        self.handle_updateRequest()

        central_widget = QtWidgets.QWidget()
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.te, alignment=QtCore.Qt.AlignTop)
        self.setCentralWidget(central_widget)

        self.resize(640, 480)

    def handle_updateRequest(self):
        doc = self.te.document()
        tb = doc.findBlockByNumber(doc.blockCount() - 1)
        h = self.te.blockBoundingGeometry(tb).bottom() + 2 * doc.documentMargin()
        self.te.setFixedHeight(h)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())