PyQt5自定义QTextEdit自动伸缩异常:窗口未同步调整求助
问题解决:PyQt5实现随内容伸缩的QTextEdit并同步窗口尺寸
问题背景
需要实现自定义QTextEdit控件:输入换行时高度自动增加,删除内容时高度缩小。当前代码运行后,QTextEdit尺寸变化时窗口大小固定,导致上方聊天区域控件被异常拉伸,目标是让窗口随QTextEdit尺寸同步调整,避免其他控件变形。
解决方案
核心调整方向:
- 为上方聊天区域的QScrollArea设置合理尺寸策略,确保垂直方向仅在窗口有多余空间时扩展,而非被压缩
- 修改CustomTextEdit的高度控制逻辑,用最小高度替代固定高度,允许窗口整体调整尺寸
- 触发顶层窗口布局更新,确保控件尺寸变化被正确传递
修改后的完整代码
from PyQt5.QtWidgets import * from PyQt5.QtCore import * import sys class App(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) self.init_ui() def init_ui(self): ### ChatWidget ### chat_widget = QWidget(self) chat_widget.setObjectName("chatbox") chat_widget.setStyleSheet("#chatbox {background-color: black; border: 0;}") chat_widget.scroll_area = QScrollArea(self) chat_widget.scroll_area.setWidgetResizable(True) chat_widget.scroll_area.setWidget(chat_widget) chat_widget.scroll_area.setStyleSheet(""" QScrollArea { } QScrollBar:vertical { background-color: black; color: white; } """) # 关键修改:设置ScrollArea尺寸策略,垂直方向为Expanding并保留最小高度 chat_widget.scroll_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) chat_widget.setMinimumHeight(449) chat_widget.setMinimumWidth(300) chat_widget.scroll_area.setMinimumHeight(453) chat_widget.scroll_area.setMinimumWidth(333) self.layout.addWidget(chat_widget.scroll_area) ### ### CustomTextEdit ### self.text_edit = CustomTextEdit(5, self) self.layout.addWidget(self.text_edit) self.text_edit.setStyleSheet(""" font-size: 12pt; """) QTimer().singleShot(5, self.text_edit.update_height) ### class CustomTextEdit(QTextEdit): def __init__(self, max_lines=5, parent=None): super().__init__(parent) self.max_lines = max_lines # 关键修改:调整尺寸策略,垂直方向设为Minimum以支持窗口动态调整 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self.document().contentsChanged.connect(self.update_height) # 初始设置最小高度而非固定高度 self.setMinimumHeight(self.fontMetrics().height()) def update_height(self): document_height = self.document().size().height() line_height = self.fontMetrics().lineSpacing() text_layout = self.document().documentLayout() block = self.document().begin() num_lines = 0 while block.isValid(): layout = block.layout() num_lines += layout.lineCount() block = block.next() desired_height = document_height + self.contentsMargins().top() + self.contentsMargins().bottom() if num_lines > self.max_lines: self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) # 超过最大行数时固定高度,避免无限增高 self.setFixedHeight(int(line_height * self.max_lines + self.contentsMargins().top() + self.contentsMargins().bottom())) else: self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 未超过时设置最小高度,允许窗口扩展 self.setMinimumHeight(int(desired_height)) # 触发顶层窗口调整,同步尺寸变化 if self.parent(): self.parent().adjustSize() def scroll_to_bottom(self): scrollbar = self.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) if __name__ == '__main__': app = QApplication(sys.argv) app_widget = App() app_widget.show() sys.exit(app.exec_())
关键修改说明
- 聊天区域ScrollArea配置:将尺寸策略设为
(Expanding, Expanding)并保留最小高度,确保它仅在窗口有额外空间时扩展,不会被QTextEdit的尺寸变化压缩。 - CustomTextEdit高度控制:
- 初始化用
setMinimumHeight替代setFixedHeight,允许控件高度动态调整 - 未超过最大行数时设置最小高度,让窗口可以整体放大
- 超过最大行数时固定高度并显示滚动条,限制控件高度上限
- 初始化用
- 窗口同步调整:在
update_height中调用parent().adjustSize(),确保顶层窗口感知控件尺寸变化并同步更新自身大小。
内容的提问来源于stack exchange,提问作者ExUltra
相关产品推荐
相关产品推荐

