QLineEdit:显示处理过的文本,而不是输入的文本,但保留它(自定义回显模式)

QLineEdit: Show a processed text, not the entered one, but keep it (custom echo mode)

我想要 QLineEdit 不显示输入的文本,而是显示经过处理的版本,同时保留原始文本并在通过 text() 请求时返回它。与密码回显模式一样,但我不希望每个字符都被屏蔽。我想可视化空间:

E. G。输入 some text with spaces in between 时,应显示 some·text·with·spaces·in·between 以便可以看到空格。就像当 e. G。您在 LibreOffice 中激活那个 ¶ 符号。

QLineEdit::displayText(),但不能设置,只能读取。此外,echoMode 只能通过枚举设置,并且设置 EchoMode::Password 后,处理似乎发生在 QLineEdit 的私有函数中,因此我也无法覆盖某些处理功能。

这可能吗?

恕我直言,QLineEdit很难做到这一点。

但是,通过配置 QTextDocument:

使用 QTextEdit 非常容易
class TextEdit : public QTextEdit
{
    Q_OBJECT
public:
        explicit TextEdit(QWidget* parent=nullptr): QTextEdit (parent)
        {
                QTextDocument* doc = new QTextDocument(this);
                setDocument(doc);
                QTextOption option;
                option.setFlags(QTextOption::ShowLineAndParagraphSeparators | QTextOption::ShowTabsAndSpaces);
                doc->setDefaultTextOption(option);
        }
};

然后,您必须配置 TextEdit 以获得与 QLineEdit 相同的行为(即单行、无滚动条等)。

作为良好开端的快速示例:

class OneLineTextEdit : public QTextEdit
{
    Q_OBJECT
public:
        explicit OneLineTextEdit(QWidget* parent=nullptr): QTextEdit (parent)
        {
                setTabChangesFocus(true);
                setWordWrapMode(QTextOption::NoWrap);
                // No scrollbars
                setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

                // One line only
                setFixedHeight(sizeHint().height());

                // Show the space/tabs/return
                QTextDocument* doc = new QTextDocument(this);
                setDocument(doc);
                QTextOption option;
                option.setFlags(QTextOption::ShowLineAndParagraphSeparators | QTextOption::ShowTabsAndSpaces);
                doc->setDefaultTextOption(option);
        }

    // We don't want to write more than one line
    void keyPressEvent(QKeyEvent *event)
    {
        if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
                return event->ignore();
        return QTextEdit::keyPressEvent(event);
    }

    // Don't display more than one line
    QSize sizeHint() const
    {
        QFontMetrics const fm(font());
        int const h = qMax(fm.height(), 14) + 4;
        int const w = fm.width(QLatin1Char('x')) * 17 + 4;
        QStyleOption opt;
        opt.initFrom(this);
        // Use the current app style to find the size of a real QLineEdit
        return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
                expandedTo(QApplication::globalStrut()), this));
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    OneLineTextEdit *editor = new OneLineTextEdit();
    editor->show();

    return app.exec();
};

最后是这样的:

SpacesLineEdit.h:

#include <QPlainTextEdit>

class SpacesLineEdit : public QPlainTextEdit
{
    Q_OBJECT

public:
    explicit SpacesLineEdit(QWidget *parent = nullptr);
    void setText(const QString &text);
    QString text() const;

protected:
    virtual void keyPressEvent(QKeyEvent *event) override;
    virtual QSize sizeHint() const override;
    virtual QSize minimumSizeHint() const override;
    virtual void insertFromMimeData(const QMimeData *source) override;

private: // Variables
    QSize m_sizeHint;

};

SpacesLineEdit.cpp:

#include "SpacesLineEdit.h"
#include <QLineEdit>
#include <QMimeData>

SpacesLineEdit::SpacesLineEdit(QWidget *parent) : QPlainTextEdit(parent)
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setLineWrapMode(QPlainTextEdit::NoWrap);
    setTabChangesFocus(true);

    QTextOption option = document()->defaultTextOption();
    option.setFlags(option.flags() | QTextOption::ShowTabsAndSpaces);
    document()->setDefaultTextOption(option);

    // Stealing the sizeHint from a plain QLineEdit will do for now :-P
    QLineEdit lineEdit;
    m_sizeHint = lineEdit.sizeHint();
}

QSize SpacesLineEdit::minimumSizeHint() const
{
    return m_sizeHint;
}

QSize SpacesLineEdit::sizeHint() const
{
    return m_sizeHint;
}

void SpacesLineEdit::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        event->ignore();
        return;
    }
    QPlainTextEdit::keyPressEvent(event);
}

void SpacesLineEdit::insertFromMimeData(const QMimeData *source)
{
    QString text = source->text();
    text.replace(QLatin1String("\r\n"), QLatin1String(" "));
    text.replace(QLatin1Char('\n'), QLatin1String(" "));
    text.replace(QLatin1Char('\r'), QLatin1String(" "));

    QMimeData processedSource;
    processedSource.setText(text);
    QPlainTextEdit::insertFromMimeData(&processedSource);
}

void SpacesLineEdit::setText(const QString &text)
{
    setPlainText(text);
}

QString SpacesLineEdit::text() const
{
    return toPlainText();
}