QLineEdit/QTextEdit different colors while typing
-
I try to implement a
QLineEditwith 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
QTextEditthat has a plaintext insert and supports color setup. One issue is that attaching totextChangedwill get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every50msto 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?

This is the sketch -
pyside6.4.2is 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()) -
I try to implement a
QLineEditwith 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
QTextEditthat has a plaintext insert and supports color setup. One issue is that attaching totextChangedwill get triggered by keyboard and when text is changed in the code - therefore I implemented a timer that is triggered every50msto 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?

This is the sketch -
pyside6.4.2is 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())@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.
-
@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.
@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()) -
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()) -
Have you checked QSyntaxHighlighter ?