I am trying to create a UI that resembles OpenAI's, where code and markdown snippets follow each other and markdown and the code are parsed/syntax highlighted accordingly. I've been using PyQt6 and my subclass of QTextEdit to resemble the text snippets that may either be code or plain text (not markdown for now). Syntax highlighting and markdown parsing aside, I am failing to understand why FormattedSnippet does not take as much space as it can in the QVBoxLayout. By changing the size of my test_doc (with *=) I got the impression that the FormattedSnippet widgets squeeze each other as I add more of them to Window. Which results in my FormattedSnippets being scrollable. Instead, I need the Window to expand as I add each FormattedSnippet and I the user should be able to see each snippet by scrolling through Window, not the individual FormattedSnippets You can see everything I have been working with below (except my QSyntaxHighlighter subclass because it isn't relevant), though the problem probably lies in the FormattedSnippet or Window classes. I tried subclassing QLabel instead of QTextEdit instead since it is not scrollable and it actually lays out its content fully, just as I want it to. However, as I understand it, QLabel does not support rich text so syntax highlighting is off the table. I am pretty new to PyQt6 so please correct me if any of my explanations/understandings are wrong. Here is what the UI currently looks like. Each snippet has its scroll bar on the far-right: class Snippet: class Type(Enum): CODE = "CODE" PLAINTEXT = "PLAINTEXT" def __init__(self, type: Type, text: str): self.type = type self.text = text class FormattedSnippet(QTextEdit): def __init__(self, snippet: Snippet): super().__init__() self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) self.setReadOnly(True) if snippet.type == Snippet.Type.CODE: language, code = parse_snippet(snippet.text) self.setText(code) font = QFont("Courier New") font.setStyleHint(QFont.StyleHint.Monospace) self.setFont(font) self.setStyleSheet( """ QTextEdit { background-color: #000000; color: #dcdcdc; border-radius: 4px; padding: 4px; } """ ) else: self.setText(snippet.text) self.setStyleSheet( """ QTextEdit { background-color: transparent; color: #E0E0E0; border: none; padding: 4px; } """ ) def parse_snippet(snippet: str): """ Parse a fenced code block: ```lang code here ``` Returns (language, code). """ pattern = re.compile(r"```(\w+)\s*(.*?)\s*```", re.DOTALL) match = re.search(pattern, snippet.strip()) if match: lang, code = match.groups() return lang.strip(), code.strip() return "text", snippet # fallback def extract_snippets(document: str) -> list[Snippet]: # Split the document by code fence markers parts = re.split(r"(```\w+[\s\S]*?```)", document) snippets = [] for part in parts: if part.strip(): if part.startswith("```") and part.endswith("```"): snippets.append(Snippet(Snippet.Type.CODE, part)) else: snippets.append(Snippet(Snippet.Type.PLAINTEXT, part)) return snippets class Window(QScrollArea): def __init__(self, test_doc): super().__init__() layout = QtWidgets.QVBoxLayout(self) frame = QtWidgets.QFrame() self.setWidgetResizable(True) frame.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) frame.setLayout(layout) self.setWidget(frame) snippets = extract_snippets(test_doc) for snippet in snippets: formatted_snippet = FormattedSnippet(snippet) layout.addWidget(formatted_snippet) if __name__ == "__main__": test_doc = """Here is some text Here is some text Here is some text Here is some text Here is some text ```python def hello(document: str): print("world") # Prints 'world' print("world") a = "hello" print(a) def test(): return ``` More text here ```java import java.util.Random; public class RandomSnippet { public static void main(String[] args) { // Generate a random element from an array String[] colors = {"red", "green", "blue"}; int randomIndex = random.nextInt(colors.length); String randomColor = colors[randomIndex]; System.out.println("Random color: " + randomColor); // Example of generating multiple random numbers System.out.println("Generating 5 random numbers:"); for (int i = 0; i < 5; i++) { System.out.println(random.nextInt(100)); // Generates random numbers between 0 and 99 } } } ``` Final text""" test_doc *= 1 app = QtWidgets.QApplication(["Test"]) window = Window(test_doc) window.resize(800, 600) window.show() sys.exit(app.exec()) Continue reading...