I am trying to make the text cursor on a QTextEdit red (rgb(255,0,0)). Despite my best efforts, it continues to blink white.
From what I've found, the Style Sheet "color" property is supposed to change the color of the cursor. Not sure what's wrong.
My Code:
textEntry = new QTextEdit();
textEntry->setFont(QFont("Electrolize", 9, 1));
textEntry->setMinimumHeight(25);
textEntry->setMaximumHeight(25);
textEntry->setLineWrapMode(QTextEdit::NoWrap);
textEntry->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
textEntry->setStyleSheet("color: rgb(255, 0, 0);"
"border: 1px solid rgb(255, 0, 0);");
Edit: I encourage a full read of Scheff's answer. It's awesome. I noticed that the cursor created with his solution didn't blink, though, so I wanted to share a blinking version derived from Scheff's code with my (inexperienced) addition.
TextEdit.h
#ifndef TEXTEDIT_H
#define TEXTEDIT_H
#include <QTextEdit>
#include <QTimer>
class TextEdit : public TextEdit
{
Q_OBJECT
public:
explicit TextEdit(QWidget *parent = nullptr);
private:
QTimer *timer;
QPainter *pPainter;
bool bCursorVisible;
protected:
virtual void paintEvent(QPaintEvent *pEvent) override;
signals:
sendUpdate();
public slots:
void timerSlot();
};
#endif // TEXTEDIT_H
TextEdit.cpp
#include "textedit.h"
#include <QPainter>
#include <QColor>
#include <QTimer>
TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent) {
bCursorVisible = true;
timer = new QTimer(this);
timer->start(500);
connect(this, SIGNAL(sendUpdate()), this, SLOT(update()));
connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));
}
void TextEdit::paintEvent(QPaintEvent *event)
{
// use paintEvent() of base class to do the main work
QTextEdit::paintEvent(event);
// draw cursor (if widget has focus)
if (hasFocus()) {
if(bCursorVisible) {
const QRect qRect = cursorRect(textCursor());
QPainter qPainter(viewport());
qPainter.fillRect(qRect, QColor(255, 0, 0, 255));
} else {
const QRect qRect = cursorRect(textCursor());
QPainter qPainter(viewport());
qPainter.fillRect(qRect, QColor(0, 0, 0, 255));
}
}
}
void TextEdit::timerSlot() {
if(bCursorVisible) {
bCursorVisible = false;
} else {
bCursorVisible = true;
}
emit sendUpdate();
}
There was some conversation with OP beforehand, as I had serious doubts whether the color property of the
QTextEdit
is responsible for the color of text cursor as well.All I found in the Qt Style Sheets Reference:
Out of curiosity, I fiddled a little bit with colors of
QTextEdit
.I could reproduce what OP described:
Changing the text color of
QTextEdit
(e.g. withQTextEdit::setTextColor()
) has an effect on inserted text typed afterwards but it didn't change the text cursor color (at least, on the platforms where I tested).While fiddling I realized another fact that encouraged me to write this answer:
IMHO, the text cursor ignores any color setting. Instead, it inverts the pixels under the drawn text cursor bar.
Have a look at
QPainter::RasterOp_NotSource
to see what I mean.My sample application
testQTextEditCursorColor.cc
:and the corresponding Qt project file
testQTextEditCursorColor.pro
:Compiled and tested in cygwin64 on Windows 10:
So, black makes a white cursor, white makes a black cursor (independent of any color setting). Assuming my above statement is correct, cyan background (
#00ffff
) should make red cursor (#ff0000
):For a comparison, I wrote a CMake script
CMakeLists.txt
:and compiled and tested in VS2017 again:
(Please note, the different style engine.)
The rendering in the Windows GDI makes it obvious that glyph pixels are inverted as well (but I noticed the same in the X11 test above):
The above in mind, it becomes obvious that it's a bad idea to use middle gray as background color. The bitwise NOT of e.g.
#808080
is#7f7f7f
and there is little contrast between these two colors. (I don't provide a snapshot because I was not able to recognize the right time to hit the Print key for a snapshot with text cursor drawn.)OP referred to another Q&A: SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color. Though, this answer was accepted and upvoted, it didn't help to change the cursor color on my side in any other way as described above. These are the modifications, I tried on my sample:
QTextEdit
byQPlainTextEdit
qTextEdit.setCursorWidth()
including using the exposed code in linked answer "literally".
After some conversation with thuga (the author of the accepted answer to SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color, it appeared that there is a bug report for Qt 5.8 concerning this:
Qt 5.8 no longer allows QPlainTextEdit's cursor color to be set
which is marked as
Unresolved
at the time of writing. (Currently, Qt5.12 is the most recent version.)After having long explained why it cannot work out-of-the-box, finally a sample how OPs intention can be achieved with a custom-painted cursor:
The
QTextEdit
is replaced by the derivedTextEdit
with an overriddenpaintEvent()
.The
QTextEdit::paintEvent()
is called inTextEdit::paintEvent()
to do the main work. Afterwards the cursor is (re-)painted with a rectangle in thetextColor
. (This simply over-paints the already rendered built-in text cursor.)Note:
A smalls trap is the usage of
QPainter
inTextEdit::paintEvent()
. BecauseQTextEdit
is derived fromQAbstractScrollArea
,QPainter qPainter(this);
would be wrong. Instead,QPainter qPainter(viewport());
has to be used. This is mentioned in the Qt doc. forQAbstractScrollArea::paintEvent()
: