简体   繁体   中英

QLineEdit paint a different text than the actual text (placeholder with text() non-empty)

I want my QLineEdit subclass to paint a different text (actually, HTML) than the real text.

More specifically, when the cursor is at end of string, it should paint as if the (HTML) text would be text() + "<font color='gray'>ThisIsExtraText</font>" :

在此输入图像描述

How can this be achieved?

I'm thinking about overriding the paint() method, but I don't really need to change any paint behavior, just that it should paint a different text.

However, I want that by all means, the text() property of the widget holds the real text, and not the modified text.

More details: the behavior I'm trying to implement is similar to placeholder text, but it is displayed when there is some text in the line-edit widget (unlike the placeholder, which is displayed when there is NO text).


A few problems I encountered:

QLineEdit does not accept HTML. I was thinking I can render the QLineEdit in two passes:

void MyLineEdit::paintEvent(QPaintEvent *event)
{
    if(cursorPosition() == text().length())
    {
        bool oldBlockSignals = blockSignals(true);

        // save old state:
        QString oldText = text();
        QString oldStyleSheet = styleSheet();
        bool oldReadOnly = isReadOnly();

        // change state:
        setText(oldText + "ThisIsExtraText");
        setStyleSheet("color: gray");
        setReadOnly(true);

        // paint changed state:
        QLineEdit::paintEvent(event);

        // restore state:
        setText(oldText);
        setStyleSheet(oldStyleSheet);
        setReadOnly(oldReadOnly);

        blockSignals(oldBlockSignals);
    }
    QLineEdit::paintEvent(event);
}

but the paintEvent would clear the background.

Even if I give up changing the color, the text is rendered with the cursor in the wrong position.

Implementation of @joe_chip's answer:

void MyLineEdit::paintEvent(QPaintEvent *event)
{
    QLineEdit::paintEvent(event);

    if(!hasFocus()) return;
    if(cursorPosition() < txt.length()) return;

    ensurePolished(); // ensure font() is up to date

    QRect cr = cursorRect();
    QPoint pos = cr.topRight() - QPoint(cr.width() / 2, 0);

    QTextLayout l("ThisIsExtraText", font());
    l.beginLayout();
    QTextLine line = l.createLine();
    line.setLineWidth(width() - pos.x());
    line.setPosition(pos);
    l.endLayout();

    QPainter p(this);
    p.setPen(QPen(Qt::gray, 1));
    l.draw(&p, QPoint(0, 0));
}

QLineEdit internally uses QTextLayout for rendering. You could use it for "ThisIsExtraText" by creating QTextLayout instance for it and drawing it from paintEvent of QLineEdit 's subclass.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM