一个类似于QTextEdit的QWidget,能够自动根据内容调整高度的吗?

12

我正在创建一个包含一些QTextEdit小部件的表单。

QTextEdit的默认高度超过了一行文本,随着其内容高度超过QTextEdit的高度,它会创建滚动条来滚动内容。

我想重写此行为,以创建一个QTextEdit,它会将其高度调整为其内容。这意味着默认高度将仅为一行,在换行或输入新行时,QTextEdit将自动增加其高度。每当内容高度超过QTextEdit的高度时,后者不应创建滚动条,而只需增加高度即可。

我该如何做到这一点?谢谢。

2个回答

7
这几乎和我前几天回答的一个问题一模一样,关于如何使QTextEdit根据内容更改自适应高度:PySide Qt: Auto vertical growth for TextEdit Widget 我想回答这个问题而不是标记为重复,因为我猜你可能需要的是这个问题的变体。如果你想让我扩展这个答案,请告诉我:
另一个问题有多个部分。这里是增长高度部件的摘录:
class Window(QtGui.QDialog):

    def __init__(self):
        super(Window, self).__init__()
        self.resize(600,400)

        self.mainLayout = QtGui.QVBoxLayout(self)
        self.mainLayout.setMargin(10)

        self.scroll = QtGui.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.mainLayout.addWidget(self.scroll)

        scrollContents = QtGui.QWidget()
        self.scroll.setWidget(scrollContents)

        self.textLayout = QtGui.QVBoxLayout(scrollContents)
        self.textLayout.setMargin(10)

        for _ in xrange(5):
            text = GrowingTextEdit()
            text.setMinimumHeight(50)
            self.textLayout.addWidget(text)


class GrowingTextEdit(QtGui.QTextEdit):

    def __init__(self, *args, **kwargs):
        super(GrowingTextEdit, self).__init__(*args, **kwargs)  
        self.document().contentsChanged.connect(self.sizeChange)

        self.heightMin = 0
        self.heightMax = 65000

    def sizeChange(self):
        docHeight = self.document().size().height()
        if self.heightMin <= docHeight <= self.heightMax:
            self.setMinimumHeight(docHeight)

2
另外(我在你的其他帖子中没有看到这一点),我必须连接以下内容,以便在调整QTextEdit的大小时将其高度包装到其文档中:self.document().documentLayout().documentSizeChanged.connect(self.wrapHeightToContents) - neydroydrec
1
如果您看我的示例,我在更高的位置使用了不同的信号。我不需要任何其他连接。 - jdi
1
@jdi 你连接的信号在C++中是受保护的。 - chacham15
@Jason 如果你不想要一个具有这种行为的可重用小部件,那当然可以。 - jdi
回答自己:self.document().documentLayout().documentSizeChanged 可能是需要连接的信号。 - Jason
显示剩余5条评论

7
以下代码将QTextEdit小部件设置为内容的高度:
# using QVBoxLayout in this example
grid = QVBoxLayout()
text_edit = QTextEdit('Some content. I make this a little bit longer as I want to see the effect on a widget with more than one line.')

# read-only
text_edit.setReadOnly(True)

# no scroll bars in this example
text_edit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 
text_edit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 
text_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

# you can set the width to a specific value
# text_edit.setFixedWidth(400)

# this is the trick, we nee to show the widget without making it visible.
# only then the document is created and the size calculated.

# Qt.WA_DontShowOnScreen = 103, PyQt does not have this mapping?!
text_edit.setAttribute(103)
text_edit.show()

# now that we have a document we can use it's size to set the QTextEdit's size
# also we add the margins
text_edit.setFixedHeight(text_edit.document().size().height() + text_edit.contentsMargins().top()*2)

# finally we add the QTextEdit to our layout
grid.addWidget(text_edit)

我希望这能帮到你。

1
这是一个非常有趣的技巧,但我觉得可能还有其他方法。不过另一方面,我意识到在实践中这可能是最好的方法,因为你不需要计算帧宽度等,也不需要弄清楚所有这些细节。 - eric
1
从技术上讲,contentsMargins().top() + contentsMargins().bottom()contentsMargins().top()*2 更正确,尽管这些值通常是相同的。 - Андрей Беньковский
这个答案发布已经10年了,但它确实帮助了我。谢谢! - Escovado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接