I'm trying to create a custom QTextEdit
widget in PyQt5 that automatically expands and contracts based on its content. The widget should grow in height as the user types new lines and shrink when lines are removed. I have some code but when the TextEdit is resized, the window size remains constant so the widget above the TextEdit, which is supposed to have a dynamic size, increases in size. My MRE is as follows:
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;
}
""")
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
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
self.document().contentsChanged.connect(self.update_height)
self.setFixedHeight(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)
else:
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setFixedHeight(int(desired_height))
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_())
I'd appreciate it if someone could help, thanks!
Attempt/Goal/Expectation: I tried to make the TextEdit resize as the number of lines increase. Problem: The other widgets are being resized / The window is not being resized.