When I set the placeholder text with QLineEdit::setPlaceholderText()
, it appears gray.
Is there any way to change the color to something else, for example red?
There is another a bit hacky but simple and reliable way.
connect(lineEdit, &QLineEdit::textChanged, this, &YourClass::updateLineEditStyleSheet);
void YourLineEdit::updateLineEditStyleSheet()
{
if (lineEdit->text().isEmpty()) {
lineEdit->setStyleSheet("#lineEdit { color: lightGray;"); // Set your color but remember that Qt will reduce alpha
} else {
lineEdit->setStyleSheet("#lineEdit { color: black;"); // usual color
}
}
also you can use this way to derived from QLineEdit class
If you want to change placeholder text color for a QLineEdit
you have to customize the component's QPalette
object.
QPalette p = lineEdit->palette();
p.setColor(QPalette::Mid, Qt::red); // assuming Mid is the color you want to change.
lineEdit->setPalette(p);
I don't recall exactly which QPalette::ColorRole
is appropriate for changing QLineEdit
's placeholder text color though.
@Meefte solution is quite good given the situation that Qt gives placeholder the same color as for the text, except it adds 50% opacity. So, there is little choice to set placeholder color to be different than the text. However, even this solution could be improved by making sure that you would not need to set some other variable than the default one Qt provides you.
The need to use default placeholderText()
might arise from the situation when you have lots of QLineEdit
controls which are already promoted to some control overriding QLineEdit
behavior, and placeholderText()
is already set through code or through Qt Creator, i.e. it would be a bit painful to introduce another dynamic property. However, if you did not promote to some child control, then it would be a necessity to do so in order to use such solution.
class CustomColorPlaceholderLineEdit : public QLineEdit
{
public:
CustomColorPlaceholderLineEdit(QWidget * parent = 0) : QLineEdit(parent) { color = QColor(0,0,0,128); }
const QString &customPlaceholderText() const { return mText; }
void setCustomPlaceholderColor(const QColor &color) { this->color = color; }
const QColor &customPlaceholderColor() const { return color; }
void paintEvent(QPaintEvent *event)
{
if(color.isValid() && text().isEmpty() && (!placeholderText().isEmpty() || !mText.isEmpty()))
{
if(!placeholderText().isEmpty())
{
// In this way, placeholderText() is taken into local variable 'mText' care. Whenever placeholderText() will change, there it will be taken care of.
mText = placeholderText();
// This will ensure Qt will not draw placeholder for us.
setPlaceholderText("");
}
// By this, we make sure Qt will paint QLineEdit default parts properly.
QLineEdit::paintEvent(e);
// And now @Meefte code is reused here.
QPainter p(this);
p.setPen(color);
QFontMetrics fm = fontMetrics();
int minLB = qMax(0, -fm.minLeftBearing());
QRect lineRect = this->rect();
QRect ph = lineRect.adjusted(minLB + 3, 0, 0, 0);
QString elidedText = fm.elidedText(mText, Qt::ElideRight, ph.width());
p.drawText(ph, Qt::AlignVCenter, elidedText);
return; // No need to paint again.
}
// Default Qt's painting behavior for QLineEdit.
QLineEdit::paintEvent(e);
}
private:
QString mText;
QColor color;
};
QT still has this problem) I solved it like this:
bool CustomLineEdit::event(QEvent *event)
{
bool eventResult = QLineEdit::event(event);
if (event->type() == QEvent::StyleChange) {
QPalette pal = palette();
pal.setColor(QPalette::PlaceholderText, Qt::red);
setPalette(pal);
}
return eventResult;
}
If you want to use QSS instead of QPalette, try the following:
setStyleSheet("QLineEdit{"
" color: red;" //TEXT COLOR
"}"
"QLineEdit[text=\"\"]{"
" color: gray;" //TEXTHOLDER COLOR
"}");
connect(ui->lineEdit, &QLineEdit::textChanged, [=]{ style()->polish(ui->lineEdit); });
You can change the color, but bare in mind there is an alpha factor set in the placeholder from the source code (as mentioned in another comment) that cannot be removed. Therefore you will always see the placeholder darker (no white possible with this option).
You'll have to subclass QLineEdit
and paint your own placeholder in the paintEvent()
.
class CustomColorPlaceholderLineEdit : public QLineEdit
{
public:
CustomColorPlaceholderLineEdit(QWidget * parent = 0) : QLineEdit(parent) { color = QColor(0,0,0,128); }
void setCustomPlaceholderText(const QString &text) { this->mText = text; }
const QString &customPlaceholderText() const { return mText; }
void setCustomPlaceholderColor(const QColor &color) { this->color = color; }
const QColor &customPlaceholderColor() const { return color; }
void paintEvent(QPaintEvent *event) {
QLineEdit::paintEvent(event);
if (!hasFocus() && text().isEmpty() && !mText.isEmpty()) {
// QLineEdit's own placeholder clashes with ours.
Q_ASSERT(placeholderText().isEmpty());
QPainter p(this);
p.setPen(color);
QFontMetrics fm = fontMetrics();
int minLB = qMax(0, -fm.minLeftBearing());
QRect lineRect = this->rect();
QRect ph = lineRect.adjusted(minLB + 3, 0, 0, 0);
QString elidedText = fm.elidedText(mText, Qt::ElideRight, ph.width());
p.drawText(ph, Qt::AlignVCenter, elidedText);
}
}
private:
QString mText;
QColor color;
};
You can't, at least with the current QLineEdit code.
As you can see from the source code, the placeholder text is simply taking the foreground brush of the palette and making it partially transparent, see
QLineEdit::paintEvent
:You can work with upstream into a more general solution, though. In particular I one would expect that color to be added to the palette, or in general provided by the current
QStyle
(for instance as a style hint).