如何去除PyQt5中QPlainTextEdit组件底部的空白区域
如何去除PyQt5中QPlainTextEdit组件底部的空白区域?
问题复现
以下是能复现该问题的示例代码:
from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 130) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.plainTextEdit = QtWidgets.QPlainTextEdit(self.centralwidget) self.plainTextEdit.setStyleSheet("padding:0px;") self.plainTextEdit.setObjectName("plainTextEdit") self.gridLayout.addWidget(self.plainTextEdit, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.plainTextEdit.setPlainText(_translate("MainWindow", "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\nlast line.")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
运行效果:
已尝试的方案
你已经尝试过调整文档边距、计算文本高度并设置固定高度等操作,但未完全解决问题:
# self.main_self.ui_scheduled_transmitions_create_window.review_text.setPlainText("") self.main_self.ui_scheduled_transmitions_create_window.review_text.setPlainText(review_text) self.main_self.ui_scheduled_transmitions_create_window.review_text.setDocumentTitle("123") # if self.main_self.ui_scheduled_transmitions_create_window.review_text.height()<800: # self.main_self.ui_scheduled_transmitions_create_window.review_text.setFixedHeight(self.main_self.ui_scheduled_transmitions_create_window.review_text.height()) # else: # self.main_self.ui_scheduled_transmitions_create_window.review_text.setFixedHeight(800) self.main_self.ui_scheduled_transmitions_create_window.review_text.document().setDocumentMargin(0) # self.main_self.ui_scheduled_transmitions_create_window.review_text.setCenterOnScroll(False) m = self.main_self.ui_scheduled_transmitions_create_window.review_text.fontMetrics() RowHeight = m.lineSpacing() nRows = self.main_self.ui_scheduled_transmitions_create_window.review_text.document().blockCount() text_height = RowHeight*nRows document_format = self.main_self.ui_scheduled_transmitions_create_window.review_text.document().rootFrame().frameFormat() document_format.setBottomMargin(0) document_format.setHeight(text_height) self.main_self.ui_scheduled_transmitions_create_window.review_text.document().rootFrame().setFrameFormat(document_format) scrollBarHeight=self.main_self.ui_scheduled_transmitions_create_window.review_text.horizontalScrollBar().sizeHint().height() # scrollBarHeight=0 if text_height+scrollBarHeight>800: self.main_self.ui_scheduled_transmitions_create_window.review_text.setFixedHeight(600) else: self.main_self.ui_scheduled_transmitions_create_window.review_text.setFixedHeight(text_height+scrollBarHeight)
解决方案
方法1:精确计算内容高度并调整组件尺寸
问题核心是QPlainTextEdit的文档会预留额外空间,默认行高计算可能忽略文本块的上下边距。通过以下步骤解决:
- 清除文档、根框架、文本块的所有边距
- 逐块计算文本总高度
- 结合水平滚动条高度设置组件固定高度
修改后的代码示例:
def adjust_plain_text_edit_height(plain_text_edit): # 清除文档边距 plain_text_edit.document().setDocumentMargin(0) # 清除根框架边距 frame_format = plain_text_edit.document().rootFrame().frameFormat() frame_format.setMargin(0) plain_text_edit.document().rootFrame().setFrameFormat(frame_format) # 清除文本块边距 block_format = QtGui.QTextBlockFormat() block_format.setTopMargin(0) block_format.setBottomMargin(0) cursor = QtGui.QTextCursor(plain_text_edit.document()) cursor.select(QtGui.QTextCursor.Document) cursor.mergeBlockFormat(block_format) # 计算总内容高度 fm = plain_text_edit.fontMetrics() total_height = 0 block = plain_text_edit.document().firstBlock() while block.isValid(): total_height += fm.lineSpacing() block = block.next() # 考虑水平滚动条的高度(如果显示的话) scroll_bar_height = plain_text_edit.horizontalScrollBar().sizeHint().height() if plain_text_edit.horizontalScrollBar().isVisible() else 0 # 设置固定高度 plain_text_edit.setFixedHeight(total_height + scroll_bar_height) # 在setupUi之后调用 ui.setupUi(MainWindow) adjust_plain_text_edit_height(ui.plainTextEdit)
方法2:重写QPlainTextEdit的sizeHint方法
如果需要组件自动适应内容高度,可以自定义继承类,重写sizeHint方法实现动态适配:
class AutoHeightPlainTextEdit(QtWidgets.QPlainTextEdit): def __init__(self, parent=None): super().__init__(parent) self.document().setDocumentMargin(0) frame_format = self.document().rootFrame().frameFormat() frame_format.setMargin(0) self.document().rootFrame().setFrameFormat(frame_format) def sizeHint(self): fm = self.fontMetrics() total_height = 0 block = self.document().firstBlock() while block.isValid(): total_height += fm.lineSpacing() block = block.next() scroll_bar_height = self.horizontalScrollBar().sizeHint().height() if self.horizontalScrollBar().isVisible() else 0 return QtCore.QSize(self.width(), total_height + scroll_bar_height) # 使用自定义类替换原有的QPlainTextEdit # 在setupUi中修改: self.plainTextEdit = AutoHeightPlainTextEdit(self.centralwidget)
方法1适合静态内容场景,方法2适合内容动态变化时自动调整高度的场景,两种方案都能彻底消除底部空白。
内容的提问来源于stack exchange,提问作者Chris P
相关产品推荐
相关产品推荐

