QLineEdit绘制与实际文本不同的文本(带有text()的占位符非空)

时间:2018-05-19 09:12:54

标签: c++ qt

我希望我的QLineEdit子类绘制与实际文本不同的文本(实际上是HTML)。

更具体地说,当光标位于字符串的末尾时,它应该绘制为(HTML)文本为text() + "<font color='gray'>ThisIsExtraText</font>"

enter image description here

如何实现这一目标?

我正在考虑覆盖paint()方法,但我并不是真的需要更改任何绘制行为,只是它应该绘制不同的文本。

但是,我想通过各种方式,小部件的text()属性保存真实文本,而不是修改后的文本。

更多细节:我尝试实现的行为类似于占位符文本,但是当行编辑小部件中有一些文本时显示它(与占位符不同,占位符在没有文本时显示)。

我遇到的一些问题:

QLineEdit不接受HTML。我以为我可以在两遍中渲染QLineEdit:

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

但paintEvent会清除背景。

即使我放弃更改颜色,文本也会在光标位于错误的位置时呈现。

2 个答案:

答案 0 :(得分:4)

实施@ joe_chip的答案:

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

答案 1 :(得分:3)

QLineEdit在内部使用QTextLayout进行渲染。你可以用它 为"ThisIsExtraText"创建QTextLayout实例,并从paintEvent的{​​{1}}子类中提取实例。