【问题标题】:QLineEdit: Show a processed text, not the entered one, but keep it (custom echo mode)QLineEdit:显示已处理的文本,而不是输入的文本,但保留它(自定义回显模式)
【发布时间】:2019-10-05 09:20:16
【问题描述】:

我希望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 的私有函数中,所以我也无法覆盖某些处理函数。

这可能吗?

【问题讨论】:

    标签: c++ qt qt5 qlineedit


    【解决方案1】:

    这是最终的结果:

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

    【讨论】:

    • lineEdit的回车键行为应该是接受输入,而不是忽略事件
    • 好吧,在我的特殊用例中,我需要这种行为。
    【解决方案2】:

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

    但是,通过配置QTextEdit 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();
    };
    

    【讨论】:

    • 看起来这也是 Qt 家伙在 Qt 语言学家中实现这种精确行为的方式。我猜 Qt 开发人员会知道 ;-)
    • 这解决了具体的例子,但不是一般情况。这将改善解决一般情况的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多