PyQt5 - Scrollbar thinks its QTextEdit thinks is smaller than it is (doesn't resize with window)
Unsolved
Qt for Python
-
wrote on 28 Sept 2021, 23:52 last edited by ZeHgSThis post is deleted!
-
wrote on 29 Sept 2021, 07:12 last edited by JonB
@ZeHgS
This is just a thought. Where are you resetting this scrollbar (well, you are doing this insidesetHtml()
)? Anything outside a resize/show event in Qt widgets is liable to produce an "unreliable" size, as that is only calculated correctly when the widget is shown. That is my understanding/experience. -
wrote on 29 Sept 2021, 09:53 last edited by ZeHgS
Thank you so much for replying! As far as I can tell everything takes place within resize events.
Here is a minimum reproducible example:
Program launcher:
from PyQt5.QtWidgets import QMainWindow, QApplication, QTextEdit, QWidget, QScrollArea, QVBoxLayout, QHBoxLayout, QSizePolicy from PyQt5.QtGui import QMouseEvent, QTextCursor, QIcon from PyQt5.QtCore import Qt import GUIMainWindow from itertools import chain # to unnest nested lists import re application = QApplication([]) class GUIMainWindow(QMainWindow): def __init__(self): super().__init__() # add the description editor description_editor = TextEditor() description_editor.setAcceptRichText(True) description_editor.setTextInteractionFlags(Qt.NoTextInteraction) description_editor.setText( 'Meditation has proven difficult to define as it covers a wide range of dissimilar practices in different traditions. In popular usage, the word "meditation" and the phrase "meditative practice" are often used imprecisely to designate practices found across many cultures.[4][20] These can include almost anything that is claimed to train the attention of mind or to teach calm or compassion.[21] There remains no definition of necessary and sufficient criteria for meditation that has achieved universal or widespread acceptance within the modern scientific community. In 1971, Claudio Naranjo noted that "The word "meditation" has been used to designate a variety of practices that differ enough from one another so that we may find trouble in defining what meditation is."[22]: 6 A 2009 study noted a "persistent lack of consensus in the literature" and a "seeming intractability of defining meditation".[23]: 135 <BR><BR>' 'In modern psychological research, meditation has been defined and characterized in a variety of ways. Many of these emphasize the role of attention[4][1][2][3] and characterize the practice of meditation as attempts to get beyond the reflexive, "discursive thinking"[note 1] or "logic"[note 2] mind[note 3] to achieve a deeper, more devout, or more relaxed state.<BR><BR>' 'Bond et al. (2009) identified criteria for defining a practice as meditation "for use in a comprehensive systematic review of the therapeutic use of meditation", using "a 5-round Delphi study with a panel of 7 experts in meditation research" who were also trained in diverse but empirically highly studied (Eastern-derived or clinical) forms of meditation[note 4]:<BR><BR>' 'three main criteria [...] as essential to any meditation practice: the use of a defined technique, logic relaxation,[note 5] and a self-induced state/mode.<BR><BR>' 'Other criteria deemed important [but not essential] involve a state of psychophysical relaxation, the use of a self-focus skill or anchor, the presence of a state of suspension of logical thought processes, a religious/spiritual/philosophical context, or a state of mental silence.[23]: 135 .<BR><BR>' '[...] It is plausible that meditation is best thought of as a natural category of techniques best captured by "family resemblances" [...] or by the related "prototype" model of concepts."[23]: 135 [note 6].<BR><BR>' 'Several other definitions of meditation have been used by influential modern reviews of research on meditation across multiple traditions:[note 7].<BR><BR>' 'Walsh & Shapiro (2006): "[M]editation refers to a family of self-regulation practices that focus on training attention and awareness in order to bring mental processes under greater voluntary control and thereby foster general mental well-being and development and/or specific capacities such as calm, clarity, and concentration"[1]: 228–29 .<BR>' 'Cahn & Polich (2006): "[M]editation is used to describe practices that self-regulate the body and mind, thereby affecting mental events by engaging a specific attentional set.... regulation of attention is the central commonality across the many divergent methods"[2]: 180 .<BR>' 'Jevning et al. (1992): "We define meditation... as a stylized mental technique... repetitively practiced for the purpose of attaining a subjective experience that is frequently described as very restful, silent, and of heightened alertness, often characterized as blissful"[3]: 415 .<BR>' 'Goleman (1988): "the need for the meditator to retrain his attention, whether through concentration or mindfulness, is the single invariant ingredient in... every meditation system"[4]: 107 ' 'Separation of technique from tradition.<BR>''Meditation has proven difficult to define as it covers a wide range of dissimilar practices in different traditions. In popular usage, the word "meditation" and the phrase "meditative practice" are often used imprecisely to designate practices found across many cultures.[4][20] These can include almost anything that is claimed to train the attention of mind or to teach calm or compassion.[21] There remains no definition of necessary and sufficient criteria for meditation that has achieved universal or widespread acceptance within the modern scientific community. In 1971, Claudio Naranjo noted that "The word "meditation" has been used to designate a variety of practices that differ enough from one another so that we may find trouble in defining what meditation is."[22]: 6 A 2009 study noted a "persistent lack of consensus in the literature" and a "seeming intractability of defining meditation".[23]: 135 <BR><BR>' 'In modern psychological research, meditation has been defined and characterized in a variety of ways. Many of these emphasize the role of attention[4][1][2][3] and characterize the practice of meditation as attempts to get beyond the reflexive, "discursive thinking"[note 1] or "logic"[note 2] mind[note 3] to achieve a deeper, more devout, or more relaxed state.<BR><BR>' 'Bond et al. (2009) identified criteria for defining a practice as meditation "for use in a comprehensive systematic review of the therapeutic use of meditation", using "a 5-round Delphi study with a panel of 7 experts in meditation research" who were also trained in diverse but empirically highly studied (Eastern-derived or clinical) forms of meditation[note 4]:<BR><BR>' 'three main criteria [...] as essential to any meditation practice: the use of a defined technique, logic relaxation,[note 5] and a self-induced state/mode.<BR><BR>' 'Other criteria deemed important [but not essential] involve a state of psychophysical relaxation, the use of a self-focus skill or anchor, the presence of a state of suspension of logical thought processes, a religious/spiritual/philosophical context, or a state of mental silence.[23]: 135 .<BR><BR>' '[...] It is plausible that meditation is best thought of as a natural category of techniques best captured by "family resemblances" [...] or by the related "prototype" model of concepts."[23]: 135 [note 6].<BR><BR>' 'Several other definitions of meditation have been used by influential modern reviews of research on meditation across multiple traditions:[note 7].<BR><BR>' 'Walsh & Shapiro (2006): "[M]editation refers to a family of self-regulation practices that focus on training attention and awareness in order to bring mental processes under greater voluntary control and thereby foster general mental well-being and development and/or specific capacities such as calm, clarity, and concentration"[1]: 228–29 .<BR>' 'Cahn & Polich (2006): "[M]editation is used to describe practices that self-regulate the body and mind, thereby affecting mental events by engaging a specific attentional set.... regulation of attention is the central commonality across the many divergent methods"[2]: 180 .<BR>' 'Jevning et al. (1992): "We define meditation... as a stylized mental technique... repetitively practiced for the purpose of attaining a subjective experience that is frequently described as very restful, silent, and of heightened alertness, often characterized as blissful"[3]: 415 .<BR>' 'Goleman (1988): "the need for the meditator to retrain his attention, whether through concentration or mindfulness, is the single invariant ingredient in... every meditation system"[4]: 107 ' 'Separation of technique from tradition.<BR>''Meditation has proven difficult to define as it covers a wide range of dissimilar practices in different traditions. In popular usage, the word "meditation" and the phrase "meditative practice" are often used imprecisely to designate practices found across many cultures.[4][20] These can include almost anything that is claimed to train the attention of mind or to teach calm or compassion.[21] There remains no definition of necessary and sufficient criteria for meditation that has achieved universal or widespread acceptance within the modern scientific community. In 1971, Claudio Naranjo noted that "The word "meditation" has been used to designate a variety of practices that differ enough from one another so that we may find trouble in defining what meditation is."[22]: 6 A 2009 study noted a "persistent lack of consensus in the literature" and a "seeming intractability of defining meditation".[23]: 135 <BR><BR>' 'In modern psychological research, meditation has been defined and characterized in a variety of ways. Many of these emphasize the role of attention[4][1][2][3] and characterize the practice of meditation as attempts to get beyond the reflexive, "discursive thinking"[note 1] or "logic"[note 2] mind[note 3] to achieve a deeper, more devout, or more relaxed state.<BR><BR>' 'Bond et al. (2009) identified criteria for defining a practice as meditation "for use in a comprehensive systematic review of the therapeutic use of meditation", using "a 5-round Delphi study with a panel of 7 experts in meditation research" who were also trained in diverse but empirically highly studied (Eastern-derived or clinical) forms of meditation[note 4]:<BR><BR>' 'three main criteria [...] as essential to any meditation practice: the use of a defined technique, logic relaxation,[note 5] and a self-induced state/mode.<BR><BR>' 'Other criteria deemed important [but not essential] involve a state of psychophysical relaxation, the use of a self-focus skill or anchor, the presence of a state of suspension of logical thought processes, a religious/spiritual/philosophical context, or a state of mental silence.[23]: 135 .<BR><BR>' '[...] It is plausible that meditation is best thought of as a natural category of techniques best captured by "family resemblances" [...] or by the related "prototype" model of concepts."[23]: 135 [note 6].<BR><BR>' 'Several other definitions of meditation have been used by influential modern reviews of research on meditation across multiple traditions:[note 7].<BR><BR>' 'Walsh & Shapiro (2006): "[M]editation refers to a family of self-regulation practices that focus on training attention and awareness in order to bring mental processes under greater voluntary control and thereby foster general mental well-being and development and/or specific capacities such as calm, clarity, and concentration"[1]: 228–29 .<BR>' 'Cahn & Polich (2006): "[M]editation is used to describe practices that self-regulate the body and mind, thereby affecting mental events by engaging a specific attentional set.... regulation of attention is the central commonality across the many divergent methods"[2]: 180 .<BR>' 'Jevning et al. (1992): "We define meditation... as a stylized mental technique... repetitively practiced for the purpose of attaining a subjective experience that is frequently described as very restful, silent, and of heightened alertness, often characterized as blissful"[3]: 415 .<BR>' 'Goleman (1988): "the need for the meditator to retrain his attention, whether through concentration or mindfulness, is the single invariant ingredient in... every meditation system"[4]: 107 ' 'Separation of technique from tradition.<BR>' 'Some of the difficulty in precisely defining meditation has been in recognizing the particularities of the many various traditions;[27] and theories and practice can differ within a tradition.[28] Taylor noted that even within a faith such as "Hindu" or "Buddhist", schools and individual teachers may teach distinct types of meditation.[29]: 2 Ornstein noted that "Most techniques of meditation do not exist as solitary practices but are only artificially separable from an entire system of practice and belief."[30]: 143 For instance, while monks meditate as part of their everyday lives, they also engage the codified rules and live together in monasteries in specific cultural settings that go along with their meditative practices.<BR>') main_window.setCentralWidget(description_editor) def resizeEvent(self, event): super().resizeEvent(event) self.set_up_window() def launch(self): self.set_up_window() self.showMaximized() class TextEditor(QTextEdit): def __init__(self): super(TextEditor, self).__init__() # make sure this widget is tracking the mouse position at all times self.setMouseTracking(True) self.last_mouse_position = None @staticmethod def get_selected_word(text_cursor): # extract selected word text_cursor.select(QTextCursor.WordUnderCursor) word_under_cursor = text_cursor.selectedText() # if the currently selected word is a '.', try to select the previous word while word_under_cursor == '.': # first move the character back one text_cursor.movePosition(QTextCursor.PreviousCharacter) # try to move to the beginning of the previous word successfully_moved_to_previous_word = text_cursor.movePosition(QTextCursor.PreviousWord) # if unsuccessful, try the next if not successfully_moved_to_previous_word: # undo the character move text_cursor.movePosition(QTextCursor.NextCharacter, 1) # try to move to the beginning of the next word if text_cursor.movePosition(QTextCursor.NextWord): text_cursor.select(QTextCursor.WordUnderCursor) word_under_cursor = text_cursor.selectedText() # move the QTextCursor from the '.' to the previous word else: text_cursor.select(QTextCursor.WordUnderCursor) word_under_cursor = text_cursor.selectedText() return word_under_cursor def get_whole_sentence_containing_selected_word(self, selected_word, text=None): if text is None: as_text = self.toPlainText() else: as_text = text # split into sentences text_lines = as_text.split('.') # add back the final stop for index, line in enumerate(text_lines[:-1]): text_lines[index] = line + '.' sentences = list(chain(*[s.splitlines() for s in text_lines])) # get the final selected sentence, if it's found selected_sentence = [s for s in sentences if selected_word in s] if len(selected_sentence) == 0: selected_sentence = '' else: selected_sentence = selected_sentence[0] return selected_sentence def get_whole_paragraph_containing_selected_word(self, selected_word): as_text = self.toPlainText() text_paragraphs = as_text.split('\n') selected_paragraph = [p for p in text_paragraphs if selected_word in p] return selected_paragraph[0] if len(selected_paragraph) > 0 else '' def replace_in_html(self, old_string, new_string, case_insensitive=False): if not case_insensitive: old_html = self.toHtml() new_html = old_html.replace(old_string, new_string) self.setHtml(new_html) else: old_html = self.toHtml() pattern = re.compile(old_string, re.IGNORECASE) new_html = pattern.sub(new_string, old_html) self.setHtml(new_html) def setText(self, text: str) -> None: extra_newlines_removed = text.replace('<BR><BR><BR>', '<BR><BR>').replace('\n\n', '\n') super().setText(extra_newlines_removed) def setHtml(self, text: str) -> None: old_value = self.verticalScrollBar().sliderPosition() old_value_hor = self.horizontalScrollBar().sliderPosition() super().setHtml(text) self.verticalScrollBar().setSliderPosition(old_value) self.horizontalScrollBar().setSliderPosition(old_value_hor) def mouse_inside_editor(self, position): self.last_mouse_position = position # create a QTextCursor at that position to select text text_cursor = self.cursorForPosition(position) # get the currently selected word word_under_cursor = self.get_selected_word(text_cursor) # replace substring with placeholder containing as many characters selected_word_placeholder = self.replace_selected_text_with_placeholder(text_cursor, 'ª') selected_fragment = self.get_whole_sentence_containing_selected_word(selected_word_placeholder) word_under_cursor = '<span style="background-color: #FFFF00;text-decoration:underline;">' + word_under_cursor + '</span>' highlighted_text = selected_fragment.replace(selected_word_placeholder, word_under_cursor) # replace the sentence with the new formatting self.replace_in_text(selected_fragment, highlighted_text) @staticmethod def replace_selected_text_with_placeholder(text_cursor, character): # remove the selected word to be replaced by the placeholder text_cursor.removeSelectedText() # create a placeholder with as many characters as the original word word_placeholder = '' for char in range(10): word_placeholder += character text_cursor.insertText(word_placeholder) return word_placeholder def mouseMoveEvent(self, mouse_event: QMouseEvent) -> None: if self.underMouse(): self.mouse_inside_editor(mouse_event.pos()) def replace_in_text(self, text_to_replace, text_to_replace_with): # replace newlines with a placeholder so they are kept once the HTML is removed to remove the previous formatting self.replace_in_html('<br/>', 'PL_BR', True) self.replace_in_html('<br />', 'PL_BR', True) # replace in the text replaced_text = self.toPlainText().replace(text_to_replace, text_to_replace_with) # remove stray final stops replaced_text = replaced_text.replace('..', '.') replaced_text = replaced_text.replace('PL_BR. ', 'PL_BR') # remove excessive empty lines replaced_text = replaced_text.replace('PL_BRPL_BRPL_BR', 'PL_BRPL_BR') while replaced_text.startswith('PL_BR'): replaced_text = replaced_text[5:] # return new lines final_html = replaced_text.replace('PL_BR', '<br/>') self.setHtml(final_html) # last stray final stops self.replace_in_html('">.<br/>', '"><br/>') main_window = GUIMainWindow() main_window.launch() application.exec()
1/3