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. QLineEdit/QTextEdit different colors while typing
Qt 6.11 is out! See what's new in the release blog

QLineEdit/QTextEdit different colors while typing

Scheduled Pinned Locked Moved Unsolved Qt for Python
5 Posts 3 Posters 1.2k 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.
  • T Offline
    T Offline
    tilz0R
    wrote on last edited by
    #1

    I try to implement a QLineEdit with every bracket of different color - used for user to be able to match opening and closing bracket - I realized that this may not be really possible?

    So I moved to QTextEdit that has a plaintext insert and supports color setup. One issue is that attaching to textChanged will get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every 50ms to do the job.

    Now the problem is that if user sets cursor in the middle, obviously it gets auto set to the end of the line - so not really intuitive.

    How to implement that instead?

    dc42c1a1-1975-4ba9-960b-6fb737418db1-image.png

    This is the sketch - pyside6.4.2 is needed

    # This Python file uses the following encoding: utf-8
    import sys, faulthandler
    from mainwindow import MainWindow
    from PySide6.QtWidgets import QApplication
    from PySide6 import QtWidgets, QtCore, QtGui
    from PySide6.QtWidgets import *
    from PySide6.QtCore import *
    from PySide6.QtUiTools import *
    from PySide6.QtGui import *
    
    class MainWin(QMainWindow):
        def __init__(self):
            super().__init__()
            # Edit text
            self.textedit = QTextEdit()
            self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
            self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
            self.textedit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
            self.textedit.setFixedHeight(30)
            self.textedit_text = ''
    
            # Timer
            self.timer = QTimer()
            self.timer.setInterval(100)
            self.timer.timeout.connect(self.timer_timeout)
            self.timer.start()
    
            # Central
            self.setCentralWidget(self.textedit)
    
        def timer_timeout(self):
            colors = ['black', 'red', 'blue', 'green', 'magenta', 'orange']
            text = self.textedit.toPlainText()
            if self.textedit_text == text:
                return
            self.textedit_text = text
            
            bracket_index = 0
            self.textedit.setPlainText('')
            for c in text:
                if c == '(':
                    bracket_index += 1
                    self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                    self.textedit.insertPlainText('(')
                elif c == ')':
                    self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                    self.textedit.insertPlainText(')')
                    if bracket_index > 0:
                        bracket_index -= 1
                else:
                    self.textedit.setTextColor(QtGui.QColor.fromString(colors[0]))
                    self.textedit.insertPlainText(c)
    
    # Main application run
    if __name__ == '__main__':
        faulthandler.enable()
        app = QApplication(sys.argv)
        mainwindow = MainWin()
        mainwindow.show()
        sys.exit(app.exec())
    
    
    JonBJ 1 Reply Last reply
    0
    • T tilz0R

      I try to implement a QLineEdit with every bracket of different color - used for user to be able to match opening and closing bracket - I realized that this may not be really possible?

      So I moved to QTextEdit that has a plaintext insert and supports color setup. One issue is that attaching to textChanged will get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every 50ms to do the job.

      Now the problem is that if user sets cursor in the middle, obviously it gets auto set to the end of the line - so not really intuitive.

      How to implement that instead?

      dc42c1a1-1975-4ba9-960b-6fb737418db1-image.png

      This is the sketch - pyside6.4.2 is needed

      # This Python file uses the following encoding: utf-8
      import sys, faulthandler
      from mainwindow import MainWindow
      from PySide6.QtWidgets import QApplication
      from PySide6 import QtWidgets, QtCore, QtGui
      from PySide6.QtWidgets import *
      from PySide6.QtCore import *
      from PySide6.QtUiTools import *
      from PySide6.QtGui import *
      
      class MainWin(QMainWindow):
          def __init__(self):
              super().__init__()
              # Edit text
              self.textedit = QTextEdit()
              self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
              self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
              self.textedit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
              self.textedit.setFixedHeight(30)
              self.textedit_text = ''
      
              # Timer
              self.timer = QTimer()
              self.timer.setInterval(100)
              self.timer.timeout.connect(self.timer_timeout)
              self.timer.start()
      
              # Central
              self.setCentralWidget(self.textedit)
      
          def timer_timeout(self):
              colors = ['black', 'red', 'blue', 'green', 'magenta', 'orange']
              text = self.textedit.toPlainText()
              if self.textedit_text == text:
                  return
              self.textedit_text = text
              
              bracket_index = 0
              self.textedit.setPlainText('')
              for c in text:
                  if c == '(':
                      bracket_index += 1
                      self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                      self.textedit.insertPlainText('(')
                  elif c == ')':
                      self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                      self.textedit.insertPlainText(')')
                      if bracket_index > 0:
                          bracket_index -= 1
                  else:
                      self.textedit.setTextColor(QtGui.QColor.fromString(colors[0]))
                      self.textedit.insertPlainText(c)
      
      # Main application run
      if __name__ == '__main__':
          faulthandler.enable()
          app = QApplication(sys.argv)
          mainwindow = MainWin()
          mainwindow.show()
          sys.exit(app.exec())
      
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @tilz0R said in QLineEdit/QTextEdit different colors while typing:

      One issue is that attaching to textChanged will get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every 50ms to do the job.

      If you are in charge of the code callers to setText() you can avoid the timer per the answer in QLineEdit::textEdited() equivalent in QTextEdit?.

      Now the problem is that if user sets cursor in the middle, obviously it gets auto set to the end of the line - so not really intuitive.

      You would have to save the cursor position before changing and restore it afterwards.

      This whole idea of changing stuff while user is typing worries me.

      T 1 Reply Last reply
      0
      • JonBJ JonB

        @tilz0R said in QLineEdit/QTextEdit different colors while typing:

        One issue is that attaching to textChanged will get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every 50ms to do the job.

        If you are in charge of the code callers to setText() you can avoid the timer per the answer in QLineEdit::textEdited() equivalent in QTextEdit?.

        Now the problem is that if user sets cursor in the middle, obviously it gets auto set to the end of the line - so not really intuitive.

        You would have to save the cursor position before changing and restore it afterwards.

        This whole idea of changing stuff while user is typing worries me.

        T Offline
        T Offline
        tilz0R
        wrote on last edited by
        #3

        @JonB Idea is like rich text - vscode style - set colors of the brackets during typing.

        I started with another option, below, which test-wise does change the colors, but it always sets color of the whole string, not random color for each character. Any idea?

        # This Python file uses the following encoding: utf-8
        import sys, faulthandler
        from mainwindow import MainWindow
        from PySide6.QtWidgets import QApplication
        from PySide6 import QtWidgets, QtCore, QtGui
        from PySide6.QtWidgets import *
        from PySide6.QtCore import *
        from PySide6.QtUiTools import *
        from PySide6.QtGui import *
        import random
        
        class MainWin(QMainWindow):
            def __init__(self):
                super().__init__()
                # Edit text
                self.textedit = QTextEdit()
                #self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
                #self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
                #self.textedit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
                self.textedit.setFixedHeight(30)
                self.textedit_text = ''
        
                # Timer
                self.timer = QTimer()
                self.timer.setInterval(25)
                self.timer.timeout.connect(self.timer_timeout)
                self.timer.start()
        
                # Central
                self.setCentralWidget(self.textedit)
        
            def timer_timeout(self):
                colors = ['black', 'red', 'blue', 'green', 'magenta', 'orange', 'yellow', 'brown', 'grey']
                text = self.textedit.toPlainText()
                if self.textedit_text == text:
                    return
                self.textedit_text = text
        
                # Get cursor
                cursor = QTextCursor(self.textedit.textCursor())
                cursor.movePosition(QTextCursor.MoveOperation.Start)
                while not cursor.atEnd():
                    cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor)
                    format = QTextCharFormat()
                    format.setForeground(QColor.fromString(colors[random.randint(0, len(colors) - 1)]))
                    cursor.mergeCharFormat(format)
        
        # Main application run
        if __name__ == '__main__':
            faulthandler.enable()
            app = QApplication(sys.argv)
            mainwindow = MainWin()
            mainwindow.show()
            sys.exit(app.exec())
        
        
        1 Reply Last reply
        0
        • T Offline
          T Offline
          tilz0R
          wrote on last edited by
          #4

          This is somewhat working:

          # This Python file uses the following encoding: utf-8
          import sys, faulthandler
          from mainwindow import MainWindow
          from PySide6.QtWidgets import QApplication
          from PySide6 import QtWidgets, QtCore, QtGui
          from PySide6.QtWidgets import *
          from PySide6.QtCore import *
          from PySide6.QtUiTools import *
          from PySide6.QtGui import *
          
          class MainWin(QMainWindow):
              def __init__(self):
                  super().__init__()
                  # Edit text
                  self.textedit = QTextEdit()
                  self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
                  self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
                  self.textedit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
                  self.textedit.setFixedHeight(30)
                  self.textedit_text = ''
          
                  # Timer
                  self.timer = QTimer()
                  self.timer.setInterval(100)
                  self.timer.timeout.connect(self.timer_timeout)
                  self.timer.start()
          
                  # Central
                  self.setCentralWidget(self.textedit)
          
              def timer_timeout(self):
                  colors = ['black', 'red', 'blue', 'green', 'magenta', 'orange']
                  text = self.textedit.toPlainText()
                  if self.textedit_text == text:
                      return
                  self.textedit_text = text
                  self.textedit.blockSignals(True)
          
                  # Get cursor and position
                  cursor = self.textedit.textCursor()
                  pos = cursor.position()
          
                  bracket_index = 0
                  self.textedit.setPlainText('')
                  for c in text:
                      if c == '(':
                          bracket_index += 1
                          self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                          self.textedit.insertPlainText('(')
                      elif c == ')':
                          self.textedit.setTextColor(QtGui.QColor.fromString(colors[bracket_index % len(colors)]))
                          self.textedit.insertPlainText(')')
                          if bracket_index > 0:
                              bracket_index -= 1
                      else:
                          self.textedit.setTextColor(QtGui.QColor.fromString(colors[0]))
                          self.textedit.insertPlainText(c)
          
                  # Set new position and new cursor to text edit
                  cursor.setPosition(pos)
                  self.textedit.setTextCursor(cursor)
                  self.textedit.blockSignals(False)
          
          # Main application run
          if __name__ == '__main__':
              faulthandler.enable()
              app = QApplication(sys.argv)
              mainwindow = MainWin()
              mainwindow.show()
              sys.exit(app.exec())
          
          
          1 Reply Last reply
          0
          • F Offline
            F Offline
            friedemannkleint
            wrote on last edited by
            #5

            Have you checked QSyntaxHighlighter ?

            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