Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PyQt5 - QSyntaxHighlighter not working properly

PyQt5 - QSyntaxHighlighter not working properly

Scheduled Pinned Locked Moved Solved Qt for Python
5 Posts 3 Posters 581 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • PatitotectiveP Offline
    PatitotectiveP Offline
    Patitotective
    wrote on last edited by Patitotective
    #1

    I'm using QSyntaxHighlighter to highlight a QTextEdit but it doesn't work if the QTextEdit has a text at start. It highlights all with a same color. If I instead of adding the whole text at once I add each character by character it works.
    So not sure of which is the proper way to use a QSyntaxHighlighter.

    Take a look at this minimal example:
    Do uncomment 81, 93 and 84 lines and comment 80 line to see how it should look like.

    import sys
    import re
    from PyQt5.QtGui import QBrush, QSyntaxHighlighter, QTextCharFormat, QColor, QPalette, QFont, QTextCursor, QTextLayout
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QTextEdit, QMainWindow, QApplication
    
    class MarkdownHighlighter(QSyntaxHighlighter):
    
        MARKDOWN_KEYS_REGEX = {
            'HeaderAtx': re.compile(u'(?u)^\#{1,6}(.*?)\#*(\n|$)'), # ## Header
        }
    
        def __init__(self, parent):
            super().__init__(parent)
            self.parent = parent
            parent.setTabStopWidth(parent.fontMetrics().width(' ') * 6)
    
            self.defaultTheme =  {
                "background-color":"#3e3d32", 
                "color":"#ffffff", 
                "header": {
                    "color":"#fd971f", 
                    "font-weight":"bold", 
                    "font-style":"normal"
                }
            }
            
            self.setTheme(self.defaultTheme)
    
        def setTheme(self, theme):
            self.theme = theme
            self.MARKDOWN_KWS_FORMAT = {}
    
            pal = self.parent.palette()
            pal.setColor(QPalette.Base, QColor(theme['background-color']))
            self.parent.setPalette(pal)
            self.parent.setTextColor(QColor(theme['color']))
    
            text_char_format = QTextCharFormat()
            text_char_format.setForeground(QBrush(QColor(theme['header']['color'])))
            text_char_format.setFontWeight(QFont.Bold if theme['header']['font-weight']=='bold' else QFont.Normal)
            text_char_format.setFontItalic(True if theme['header']['font-style']=='italic' else False)
            self.MARKDOWN_KWS_FORMAT['HeaderAtx'] = text_char_format
    
            self.rehighlight()
    
        def highlightBlock(self, text):
            text = str(text)
            self.highlightMarkdown(text,0)
    
        def highlightMarkdown(self, text, strt):
            cursor = QTextCursor(self.document())
            bf = cursor.blockFormat()
            self.setFormat(0, len(text), QColor(self.theme['color']))
    
            if self.highlightAtxHeader(text, cursor, bf, strt):
                return
    
        def highlightEmptyLine(self, text, cursor, bf, strt):
            textAscii = str(text.replace(u'\u2029','\n'))
            if textAscii.strip():
                return False
            else:
                return True
    
        def highlightAtxHeader(self, text, cursor, bf, strt):
            found = False
            for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HeaderAtx'],text):
                #bf.setBackground(QBrush(QColor(7,54,65)))
                #cursor.movePosition(QTextCursor.End)
                #cursor.mergeBlockFormat(bf)
                self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HeaderAtx'])
                found = True
            return found
    
    class MainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            text_edit = QTextEdit("## Some header<br>Some paragraph")
            # text_edit = QTextEdit("")
    
            # for char in "## Some header\nSome paragraph":
                # add_text_to_text_edit(text_edit, char)
    
            syntax_highlighter = MarkdownHighlighter(text_edit)
    
            self.setCentralWidget(text_edit)
    
            self.show()
    
    def add_text_to_text_edit(text_edit: QTextEdit, text: str) -> None:
        current_text = text_edit.toPlainText()
        new_text = current_text + text
    
        text_edit.setPlainText(new_text)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        
        main_window = MainWindow()
    
        sys.exit(app.exec_())
    
    eyllanescE 1 Reply Last reply
    0
    • PatitotectiveP Patitotective

      I'm using QSyntaxHighlighter to highlight a QTextEdit but it doesn't work if the QTextEdit has a text at start. It highlights all with a same color. If I instead of adding the whole text at once I add each character by character it works.
      So not sure of which is the proper way to use a QSyntaxHighlighter.

      Take a look at this minimal example:
      Do uncomment 81, 93 and 84 lines and comment 80 line to see how it should look like.

      import sys
      import re
      from PyQt5.QtGui import QBrush, QSyntaxHighlighter, QTextCharFormat, QColor, QPalette, QFont, QTextCursor, QTextLayout
      from PyQt5.QtCore import Qt
      from PyQt5.QtWidgets import QTextEdit, QMainWindow, QApplication
      
      class MarkdownHighlighter(QSyntaxHighlighter):
      
          MARKDOWN_KEYS_REGEX = {
              'HeaderAtx': re.compile(u'(?u)^\#{1,6}(.*?)\#*(\n|$)'), # ## Header
          }
      
          def __init__(self, parent):
              super().__init__(parent)
              self.parent = parent
              parent.setTabStopWidth(parent.fontMetrics().width(' ') * 6)
      
              self.defaultTheme =  {
                  "background-color":"#3e3d32", 
                  "color":"#ffffff", 
                  "header": {
                      "color":"#fd971f", 
                      "font-weight":"bold", 
                      "font-style":"normal"
                  }
              }
              
              self.setTheme(self.defaultTheme)
      
          def setTheme(self, theme):
              self.theme = theme
              self.MARKDOWN_KWS_FORMAT = {}
      
              pal = self.parent.palette()
              pal.setColor(QPalette.Base, QColor(theme['background-color']))
              self.parent.setPalette(pal)
              self.parent.setTextColor(QColor(theme['color']))
      
              text_char_format = QTextCharFormat()
              text_char_format.setForeground(QBrush(QColor(theme['header']['color'])))
              text_char_format.setFontWeight(QFont.Bold if theme['header']['font-weight']=='bold' else QFont.Normal)
              text_char_format.setFontItalic(True if theme['header']['font-style']=='italic' else False)
              self.MARKDOWN_KWS_FORMAT['HeaderAtx'] = text_char_format
      
              self.rehighlight()
      
          def highlightBlock(self, text):
              text = str(text)
              self.highlightMarkdown(text,0)
      
          def highlightMarkdown(self, text, strt):
              cursor = QTextCursor(self.document())
              bf = cursor.blockFormat()
              self.setFormat(0, len(text), QColor(self.theme['color']))
      
              if self.highlightAtxHeader(text, cursor, bf, strt):
                  return
      
          def highlightEmptyLine(self, text, cursor, bf, strt):
              textAscii = str(text.replace(u'\u2029','\n'))
              if textAscii.strip():
                  return False
              else:
                  return True
      
          def highlightAtxHeader(self, text, cursor, bf, strt):
              found = False
              for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HeaderAtx'],text):
                  #bf.setBackground(QBrush(QColor(7,54,65)))
                  #cursor.movePosition(QTextCursor.End)
                  #cursor.mergeBlockFormat(bf)
                  self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HeaderAtx'])
                  found = True
              return found
      
      class MainWindow(QMainWindow):
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
      
              text_edit = QTextEdit("## Some header<br>Some paragraph")
              # text_edit = QTextEdit("")
      
              # for char in "## Some header\nSome paragraph":
                  # add_text_to_text_edit(text_edit, char)
      
              syntax_highlighter = MarkdownHighlighter(text_edit)
      
              self.setCentralWidget(text_edit)
      
              self.show()
      
      def add_text_to_text_edit(text_edit: QTextEdit, text: str) -> None:
          current_text = text_edit.toPlainText()
          new_text = current_text + text
      
          text_edit.setPlainText(new_text)
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
          
          main_window = MainWindow()
      
          sys.exit(app.exec_())
      
      eyllanescE Offline
      eyllanescE Offline
      eyllanesc
      wrote on last edited by
      #3

      @Patitotective Don't combine plain text not html. I think that in the first case it is happening that QTextEdit considers it to be plain text as opposed to the second that you explicitly consider to be plain text.

      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

      PatitotectiveP 1 Reply Last reply
      2
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Did you already check the Syntax Highlighter Example ?

        I think it provides a pretty good base that you can base your code on.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        PatitotectiveP 1 Reply Last reply
        2
        • PatitotectiveP Patitotective

          I'm using QSyntaxHighlighter to highlight a QTextEdit but it doesn't work if the QTextEdit has a text at start. It highlights all with a same color. If I instead of adding the whole text at once I add each character by character it works.
          So not sure of which is the proper way to use a QSyntaxHighlighter.

          Take a look at this minimal example:
          Do uncomment 81, 93 and 84 lines and comment 80 line to see how it should look like.

          import sys
          import re
          from PyQt5.QtGui import QBrush, QSyntaxHighlighter, QTextCharFormat, QColor, QPalette, QFont, QTextCursor, QTextLayout
          from PyQt5.QtCore import Qt
          from PyQt5.QtWidgets import QTextEdit, QMainWindow, QApplication
          
          class MarkdownHighlighter(QSyntaxHighlighter):
          
              MARKDOWN_KEYS_REGEX = {
                  'HeaderAtx': re.compile(u'(?u)^\#{1,6}(.*?)\#*(\n|$)'), # ## Header
              }
          
              def __init__(self, parent):
                  super().__init__(parent)
                  self.parent = parent
                  parent.setTabStopWidth(parent.fontMetrics().width(' ') * 6)
          
                  self.defaultTheme =  {
                      "background-color":"#3e3d32", 
                      "color":"#ffffff", 
                      "header": {
                          "color":"#fd971f", 
                          "font-weight":"bold", 
                          "font-style":"normal"
                      }
                  }
                  
                  self.setTheme(self.defaultTheme)
          
              def setTheme(self, theme):
                  self.theme = theme
                  self.MARKDOWN_KWS_FORMAT = {}
          
                  pal = self.parent.palette()
                  pal.setColor(QPalette.Base, QColor(theme['background-color']))
                  self.parent.setPalette(pal)
                  self.parent.setTextColor(QColor(theme['color']))
          
                  text_char_format = QTextCharFormat()
                  text_char_format.setForeground(QBrush(QColor(theme['header']['color'])))
                  text_char_format.setFontWeight(QFont.Bold if theme['header']['font-weight']=='bold' else QFont.Normal)
                  text_char_format.setFontItalic(True if theme['header']['font-style']=='italic' else False)
                  self.MARKDOWN_KWS_FORMAT['HeaderAtx'] = text_char_format
          
                  self.rehighlight()
          
              def highlightBlock(self, text):
                  text = str(text)
                  self.highlightMarkdown(text,0)
          
              def highlightMarkdown(self, text, strt):
                  cursor = QTextCursor(self.document())
                  bf = cursor.blockFormat()
                  self.setFormat(0, len(text), QColor(self.theme['color']))
          
                  if self.highlightAtxHeader(text, cursor, bf, strt):
                      return
          
              def highlightEmptyLine(self, text, cursor, bf, strt):
                  textAscii = str(text.replace(u'\u2029','\n'))
                  if textAscii.strip():
                      return False
                  else:
                      return True
          
              def highlightAtxHeader(self, text, cursor, bf, strt):
                  found = False
                  for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HeaderAtx'],text):
                      #bf.setBackground(QBrush(QColor(7,54,65)))
                      #cursor.movePosition(QTextCursor.End)
                      #cursor.mergeBlockFormat(bf)
                      self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HeaderAtx'])
                      found = True
                  return found
          
          class MainWindow(QMainWindow):
              def __init__(self, *args, **kwargs):
                  super().__init__(*args, **kwargs)
          
                  text_edit = QTextEdit("## Some header<br>Some paragraph")
                  # text_edit = QTextEdit("")
          
                  # for char in "## Some header\nSome paragraph":
                      # add_text_to_text_edit(text_edit, char)
          
                  syntax_highlighter = MarkdownHighlighter(text_edit)
          
                  self.setCentralWidget(text_edit)
          
                  self.show()
          
          def add_text_to_text_edit(text_edit: QTextEdit, text: str) -> None:
              current_text = text_edit.toPlainText()
              new_text = current_text + text
          
              text_edit.setPlainText(new_text)
          
          if __name__ == "__main__":
              app = QApplication(sys.argv)
              
              main_window = MainWindow()
          
              sys.exit(app.exec_())
          
          eyllanescE Offline
          eyllanescE Offline
          eyllanesc
          wrote on last edited by
          #3

          @Patitotective Don't combine plain text not html. I think that in the first case it is happening that QTextEdit considers it to be plain text as opposed to the second that you explicitly consider to be plain text.

          If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

          PatitotectiveP 1 Reply Last reply
          2
          • SGaistS SGaist

            Hi,

            Did you already check the Syntax Highlighter Example ?

            I think it provides a pretty good base that you can base your code on.

            PatitotectiveP Offline
            PatitotectiveP Offline
            Patitotective
            wrote on last edited by
            #4

            @SGaist I'll take a look at it, thanks 🙃

            1 Reply Last reply
            0
            • eyllanescE eyllanesc

              @Patitotective Don't combine plain text not html. I think that in the first case it is happening that QTextEdit considers it to be plain text as opposed to the second that you explicitly consider to be plain text.

              PatitotectiveP Offline
              PatitotectiveP Offline
              Patitotective
              wrote on last edited by Patitotective
              #5

              @eyllanesc Thanks, you were right 🙃
              I did:

              text_edit = QTextEdit()
              text_edit.setPlainText(text)
              

              Instead of:

              text_edit = QTextEdit(text)
              

              And it worked.

              1 Reply Last reply
              1

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved