【问题标题】:How to display a blinking cursor in QLineEdit during read-only如何在只读期间在 QLineEdit 中显示闪烁的光标
【发布时间】:2019-06-05 21:00:41
【问题描述】:

标题几乎说明了一切。我在表单上有一个只读文本框,用户可以通过表单上的按钮编辑此文本框的内容。该表单基本上是一个键盘。当用户单击按钮时,文本框中的值将添加一个数字。

从技术上讲,最终应用程序将在没有键盘但有触摸屏的机器上运行。用户使用触摸屏与应用程序交互,他们不应该在机器上安装键盘,但如果他们这样做,我会将文本框设置为只读。

现在,如何让文本框的光标在只读状态下仍然闪烁?

我想知道我是否需要做类似这个用户的解决方案:

Hide QLineEdit blinking cursor

我也尝试过使用 setFocus 方法,并且正在研究样式表。然而,一切都没有成功。

【问题讨论】:

    标签: c++ qt user-interface


    【解决方案1】:

    其他答案为您的问题提供了技术解决方案。但是,我认为你走错了方向。你想要一个只读的 QLineEdit,但有一个光标并且仍然接受来自虚拟键盘的输入......是的,所以它不是真正的只读......它闻起来不好。 一般来说,任意主动禁用标准功能并不是一个好主意。特别是,如果这意味着围绕标准小部件行为破解您的方式,则需要语义来做到这一点。

    让我们从头开始思考。接受键盘输入有什么问题? 从你的问题我敢猜测你想确保 QLineEdit 只接受数字,并禁止用户输入其他字符。

    如果我是对的,你想要的是 QValidatorQIntvalidatorQRegExpValidator。然后您可以让用户使用键盘,但他们只能输入数字,就像使用您的虚拟键盘一样。

    【讨论】:

    • 经过进一步考虑,项目要求要求我也为文本框的值设置一个上限。我选择了 QIntValidator。经过一些额外的考虑。我保留了键盘功能,因为这会将输入值限制为数字,并且可以在主接口设备出现故障时用作备用输入的冗余
    【解决方案2】:

    创建一个继承自QLineEdit 的类并忽略按键事件(用户按下按键时触发的事件)。它将使您的行编辑只读但没有外观:

    class LineEdit: public QLineEdit
    {
        Q_OBJECT
    public:
        LineEdit(QWidget* parent=nullptr): QLineEdit(parent)
        {
        }
        virtual void keyPressEvent(QKeyEvent* event)
        {
            event->ignore();
        }
    
    public slots:
        void add(QString const& textToAdd)
        {
            setText(text() + textToAdd);
        }
    };
    

    使用示例(定时器模拟虚拟键盘):

    LineEdit* line = new LineEdit;
    line->show();
    
    QTimer timer;
    timer.setInterval(2000);
    QObject::connect(&timer, &QTimer::timeout, [=]() { line->add("a"); });
    timer.start();
    

    【讨论】:

    • 也许有点晚了,但是如果我们点击 QPushButton 就会停止闪烁。
    • button->setFocusPolicy(Qt::NoFocus) 这将禁用从 LineEdit 移除焦点
    【解决方案3】:

    Romha Korev 的答案似乎有效,但它不会抓住一切。仍然可以将文本粘贴或拖放到行编辑中,或者作为与区域设置相关的输入法键盘事件的结果。我不知道以这种方式最终将文本输入到行编辑中的所有各种方式。你会在寻找要塞的洞。

    所以我建议为此滥用QValidator。不要将您的行编辑设置为只读模式。创建您自己的验证器来阻止所有输入,除非您特别禁用它:

    class InputBlockerValidator final: public QValidator
    {
        Q_OBJECT
    
    public:
        void enable()
        { is_active_ = true; }
    
        void disable()
        { is_active_ = false; }
    
        QValidator::State validate(QString& /*input*/, int& /*pos*/) const override
        {
            if (is_active_) {
                return QValidator::Invalid;
            }
            return QValidator::Acceptable;
        }
    
    private:
        bool is_active_ = true;
    };
    

    现在将 this 的一个实例设置为行编辑的验证器:

    // ...
    private:
        QLineEdit lineedit_;
        InputBlockerValidator validator_;
    // ...
    
    lineedit_.setValidator(&validator_);
    

    然后,每当您在行编辑中插入文本时,禁用并重新启用验证器:

    validator_.disable();
    lineedit_.insert(text_to_be_inserted);
    validator_.enable();
    

    永远不要在行编辑时调用setText()。出于某种原因,这会永久阻止验证器阻止输入。我不知道这是有意的还是 Qt 错误。仅使用insert()。要模拟setText(),请使用clear(),后跟insert()

    【讨论】:

    • setText() 不会禁用验证器。但是,传递给setText() 的字符串不会针对验证器进行检查。这意味着您最终可能会遇到QLineEdit 的文本对验证器无效的情况,在这种情况下,验证器将被有效地暂时禁用,直到文本不再无效为止。
    • @BenjaminT 这对我来说没有意义。该文本对于验证器始终无效,除非is_active_ == false。事实上,我可以创建一个始终返回QValidator::Invalid 的验证器。 setText() 将使其停止工作。
    • 那是因为你必须同时考虑QValidatorQLineEdit。最初,QLineEdit 认为其当前文本有效(无论验证器如何),当用户尝试输入文本时,验证器被检查并返回 Invalid。 QLineEdit 检测到文本将从有效变为无效并阻止更改。但是,一旦调用了setText(),即使 QLineEdit 接受了新文本,它也会检测到它是无效的。然后当用户输入文本时,QLineEdit 检测到文本将从无效变为无效并接受更改。
    猜你喜欢
    • 2014-09-30
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多