【问题标题】:Change color of placeholder text in QLineEdit在 QLineEdit 中更改占位符文本的颜色
【发布时间】:2015-01-29 05:04:44
【问题描述】:

当我使用QLineEdit::setPlaceholderText() 设置占位符文本时,它显示为灰色。

有什么方法可以将颜色更改为其他颜色,例如红色?

【问题讨论】:

  • 你需要实现自己的占位符绘制功能。您可以通过 Qt 的源代码查看它是如何工作的。这很简单。
  • Here你可以在QLineEdit的源代码中看到它是如何处理的。基本上它只需要文本颜色并减少 alpha。
  • 我编辑了这个问题,使其更笼统和易于理解。

标签: c++ qt qlineedit


【解决方案1】:

您必须继承 QLineEdit 并在 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;
};

【讨论】:

  • 我不建议这样做。这是一个非常脆弱的 hack,因为您基本上是在现有的占位符文本上重绘。如果 Qt 决定微调样式并将内容移动一个像素左右怎么办?如果检查占位符是否应该被绘制的条件发生变化怎么办? (尤其是这段代码中的那个是错误的。)
  • @peppe Qt 标准占位符文本不存在。在某些条件下,我在 QLineEdit 上绘制自定义文本。您可以将条件更改为您想要的任何内容。
  • @peppe 我有个主意 - 你可以在 onFocus() 事件中更改文本颜色 - 在焦点离开时将其更改为自定义颜色,然后在焦点输入时将其更改回。
  • 而“无论你想要什么”都是我的问题。条件已经被破坏为it doesn't match the same condition under which Qt draws its own。当然,这可以通过使用私有标头来解决。但同样,if Qt 决定以某种方式改变行为(例如,就像你正在做的那样,通过修改边距)你最终会导致渲染中断。这是一个黑客。不是解决方法。不是解决方案。
【解决方案2】:

还有另一种有点hacky但简单可靠的方法。

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
    }
}

您也可以使用这种方式从 QLineEdit 类派生

【讨论】:

    【解决方案3】:

    你不能,至少在当前的 QLineEdit 代码中是这样。

    从源代码中可以看出,占位符文本只是简单地采用了调色板的前景画笔并使其部分透明,参见QLineEdit::paintEvent

    if (d->shouldShowPlaceholderText()) {
        if (!d->placeholderText.isEmpty()) {
            QColor col = pal.text().color();
            col.setAlpha(128);
            QPen oldpen = p.pen();
            p.setPen(col);
            QRect ph = lineRect.adjusted(minLB, 0, 0, 0);
            QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, ph.width());
            p.drawText(ph, va, elidedText);
            p.setPen(oldpen);
        }
    }
    

    不过,您可以将上游用于更通用的解决方案。特别是我希望将颜色添加到调色板中,或者通常由当前的QStyle 提供(例如style hint)。

    【讨论】:

      【解决方案4】:

      如果您想使用 QSS 而不是 QPalette,请尝试以下操作:

      setStyleSheet("QLineEdit{"
                    "    color: red;" //TEXT COLOR
                    "}"
                    "QLineEdit[text=\"\"]{"
                    "    color: gray;" //TEXTHOLDER COLOR
                    "}");
      connect(ui->lineEdit, &QLineEdit::textChanged, [=]{ style()->polish(ui->lineEdit); });
      

      您可以更改颜色,但请记住,源代码的占位符中设置了一个无法删除的 alpha 因子(如另一条评论中所述)。因此,您将始终看到占位符较暗(使用此选项不可能出现白色)。

      【讨论】:

        【解决方案5】:

        如果您想更改 QLineEdit 的占位符文本颜色,您必须自定义组件的 QPalette 对象。

        QPalette p = lineEdit->palette();
        p.setColor(QPalette::Mid, Qt::red); // assuming Mid is the color you want to change.
        lineEdit->setPalette(p);
        

        我不记得究竟哪个QPalette::ColorRole 适合更改QLineEdit 的占位符文本颜色。

        【讨论】:

        • 这段代码不起作用 - 我测试过,文本颜色保持灰色。我已经开始在这个问题上悬赏。
        • 在 Qt 5.12 中,有一个 QPalette::PlaceholderText 用于此目的,并避免了 0.5 的不透明度问题。
        • @AlexKritchevsky tnx QPalette::PlaceholderText 为我工作。
        【解决方案6】:

        @Meefte 解决方案非常好,因为 Qt 为占位符提供了与文本相同的颜色,但它增加了 50% 的不透明度。因此,几乎没有选择将占位符颜色设置为与文本不同。然而,即使是这个解决方案也可以通过确保您不需要设置一些其他变量而不是 Qt 为您提供的默认变量来改进。

        当您有很多 QLineEdit 控件已经被提升为某些覆盖 QLineEdit 行为的控件,并且 placeholderText() 已经通过代码或 Qt 设置时,可能需要使用默认 placeholderText() Creator,即引入另一个动态属性会有点痛苦。但是,如果您没有提升到某个子控件,则必须这样做才能使用此类解决方案。

        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;
        };
        

        【讨论】:

          【解决方案7】:

          QT还是有这个问题) 我是这样解决的:

          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;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-05-18
            • 2013-02-04
            • 2010-11-23
            • 1970-01-01
            • 2017-10-03
            • 2019-12-09
            • 2014-11-22
            相关资源
            最近更新 更多