How to change color only in selected letters in QLineEdit?
-
Hello,
I have QLineEdit and a text on it ( for example "abcdef" ). I select by mouse a part of the text "cdef".
Now I would like to change color of that part of the text "cdef" to green. So I would like to have in this QLineEdit text letters:
a // in black
b // in black
c // in green
d // in green
e // in green
f // in greenI try with setStyleSheet() but when I select text and use:
line->setStyleSheet("QLineEdit {color: green}");
I get the whole green text in this QLineEdit.
I tried with setStyleSheet and selection-color, but this in not what I want.
I prefer to use setStyleSheet.
Here is the image what I would like to:
-
@TomNow99
No, you won't be able to use stylesheet because that won't be able to address individual letters. You will have to use (in-line, as the actual content in the line edit) something like one of:ab<span style="color: green;">cdef</span> ab<font color="green">cdef</font>
depending on what
QLineEdit
accepts.BTW, officially
QLineEdit
apparently does not support rich text, you're supposed to useQTextEdit
for that. But in practice it does accept rich text, at least to some extent. If you get stuck tryQTextEdit
if you think what you're trying ought to be working. -
@TomNow99 said in How to change color only in selected letters in QLineEdit?:
I tried with setStyleSheet and selection-color, but this in not what I want.
What did you try and what do you want exactly?
@eyllanesc said in How to change color only in selected letters in QLineEdit?:
You have to use QPalette:
Your palette code can also be replaced by style sheet:
selection-color: green; selection-background-color: transparent;
So I'm not sure this is what the OP wants.
-
@eyllanesc @Bonnie I need something other
I would like to do something like in MS Word.
I write a text in MS Word document - "abcdef"
Next I would like to change a color in a part of this text - "cde"
What I do in MS Word?
I select part "cde" by mouse and click button "change font color" and choose red color.
Now I have 3 parts:
"ab" which is black
"cde" which is red
"f" which is blackI would like to do the same in QT in QLineEdit. I find that QTextEdit have what I would like:
edit->setTextColor(Qt::red);
But this is QTextEdit - I would like the same effect in QLineEdit.
-
@Bonnie said in How to change color only in selected letters in QLineEdit?:
selection-color: green;
I had not noticed the OP's question as saying anything about what he wants in green being selected, but now I see
I select by mouse a part of the text "cdef".
@TomNow99
Do you want the green only while the text remains selected, or did you want it stay green after having selected and no longer selected?
EDIT Even after your latest clarification this remains unclear --- need a clear answer to this question? -
@TomNow99
In that case it is rich text.
As @JonB said you need to set HTML codes.
Stylesheet cannot do that.But I'm not sure if QLineEdit supports rich text?
I don't see that in the doc, onlyA related class is QTextEdit which allows multi-line, rich text editing.
So maybe you need to use QTextEdit.
-
@TomNow99
Yes, that's what I suspected! So a stylesheet changing the color while selected will not do the job.I find that QTextEdit have what I would like:
edit->setTextColor(Qt::red);That should set the whole of the text edit red?
As I said earlier, I do believe that do color on some of the content but not all characters will require you to insert HTML/rich-text like I showed you earlier. Did you try that on a
QLineEdit
, I believe it's supposed to work on that as well as on aQTextEdit
though it may not be documented, as per the reference I gave you before? Otherwise, if you can't get that to work on aQLineEdit
you really need to change over top aQTextEdit
for just this purpose? -
-
Of course I can use QTextEdit, but here is other problem: I would like to have only one line.
It's not good, but you might look at e.g. https://stackoverflow.com/a/45310325/489865
I would like to avoid HTML, but of course this is solution :)
Well, you can't, at least not easily. How do you intended to get color into plain text?
I have now suggested/asked you twice whether you find the HTML/rich-text does work inside a
QLineEdit
as well as in aQTextEdit
, e.g. according to @raven-worx https://forum.qt.io/topic/69878/qcombobox-how-to-get-richtext-in-qlineedit/2Have you tried it yet?
-
I was able to accomplish this by overlaying a
QLabel
on top of aQLineEdit
then making the text color of the line edit white. When thetextEdited
signal is emitted, use it to update the text of theQLabel
. TheQLabel
accepts rich text so you can process the text in theQLineEdit
and replace key words with the HTML needed to display the text in the way you want it. I'm sure you could modify the code to change the text color of the current selection.class LabelEditPair(QLineEdit): """ QLineEdit that changes the color of the word 'blue' to blue and the changes the font weight of the word 'bold' to bold. """ def __init__(self): super().__init__() self.label = QLabel("starting out") self.label.setParent(self) self.label.move(3, 0) self.label.setAttribute(Qt.WA_TransparentForMouseEvents) self.setStyleSheet("QLineEdit{color: white}") self.textEdited.connect(self.text_edited) def resizeEvent(self, event): self.label.setFixedHeight(self.height()) self.label.setFixedWidth(self.width()) super().resizeEvent(event) def text_edited(self, text): text = text.replace("blue", "<span style='color: blue'>blue</span>") text = text.replace("bold", "<span style='font-weight: bold'>bold</span>") self.label.setText(text)
EDIT
The previous example doesn't work well in instances where the text overflows from the
QLineEdit
widget. Here is a more comprehensive widget that uses the same idea but instead of making a subclass ofQLineEdit
the widget is a subclass ofQFrame
with aQLineEdit
and twoQLabels
, one before the cursor and one after. The widget replaces regex matches with HTML to change the style of those characters.class LabelEditPair(QFrame): """ QLineEdit that changes the color of the word 'blue' to blue and the changes the font weight of the word 'bold' to bold. """ def __init__(self, initial_text: str): super().__init__() self.stylized_regex: List[Tuple[str, str]] = [] self.setFixedHeight(22) self.setObjectName("frame") self.setStyleSheet("QFrame#frame{background-color: white; border: 1px solid gray}" "QFrame:hover#frame{border: 1px solid black}" "QFrame:selected#frame{border: 1px solid blue}") self.setFrameStyle(QFrame.Box) self.line_edit = QLineEdit(initial_text) self.line_edit.setParent(self) self.line_edit.move(0, 2) self.line_edit.setStyleSheet("border: 0px solid white; background-color:transparent") self.line_edit.setFixedWidth(2**16) self.left_label = QLabel() self.left_label.setParent(self.line_edit) self.left_label.move(1, 1) self.left_label.setAlignment(Qt.AlignRight) self.left_label.setAttribute(Qt.WA_TransparentForMouseEvents) self.right_label = QLabel() self.right_label. setParent(self.line_edit) self.right_label.move(5, 1) self.right_label.setAlignment(Qt.AlignLeft) self.right_label.setAttribute(Qt.WA_TransparentForMouseEvents) self.right_label.setFixedWidth(2**16) self.offset = 0 self.line_edit.textEdited.connect(self.text_edited) self.line_edit.cursorPositionChanged.connect(self.apply_shift) self.line_edit.selectionChanged.connect(self.set_text_to_update) self.update_text_needed = True self.placeholder = "" self.color = (0, 0, 0) def text(self): return self.line_edit.text() def setReadOnly(self, read_only: bool): self.line_edit.setReadOnly(read_only) self.line_edit.setAttribute(Qt.WA_TransparentForMouseEvents, read_only) self.line_edit.end(False) def set_placeholder_text(self, text: str): self.placeholder = text def set_text_color(self, color: Tuple[int, int, int]): self.color = color def set_text_to_update(self): self.update_text_needed = True def text_edited(self, text: str): if len(text) == 0: self.left_label.setText(self.placeholder) self.left_label.setStyleSheet("color: gray") return self.left_label.setStyleSheet(f"color: rbg{self.color}") new = self.line_edit.cursorPosition() left_text = text[:new] right_text = text[new:] self.left_label.setText(left_text) self.right_label.setText(right_text) for style, regex in self.stylized_regex: matches = findall(regex, left_text) for match in matches: left_text = left_text.replace(match, f"<span style='{style}'>{match}</span>") self.left_label.setText(left_text) matches_right = findall(regex, right_text) for match in matches_right: right_text = right_text.replace(match, f"<span style='{style}'>{match}</span>") self.right_label.setText(right_text) self.update_text_needed = False def add_style_for_regex(self, style: str, regex: str): self.stylized_regex.append((style, regex)) def apply_shift(self, old=None, new=None): text = self.line_edit.text() rect = self.line_edit.cursorRect() x_pos = rect.x() if x_pos + self.offset > self.width() - 8 and new == old + 1: self.offset = -1*(x_pos - (self.width()-8)) elif new + 1 == old and x_pos + self.offset < self.width() * 1/2: self.offset += 5 self.offset = min(0, self.offset) if len(text) == 0: self.offset = 0 self.line_edit.move(self.offset, 2) self.left_label.setFixedWidth(x_pos + 4) self.right_label.move(x_pos + 5, 1) if self.update_text_needed: self.text_edited(text=text) self.update_text_needed = True
example usage
self.color_edit = LabelEditPair("") self.color_edit.add_style_for_regex("color: blue", "(?:HI|HELLO)") main_layout.addWidget(self.color_edit)
-
@eyllanesc Your answer is helpful for me. Thanks