QLineEdit与QValidator:无论输入是否有效都要响应编辑完成事件?

11

QLineEdit有一个信号QLineEdit::editingFinished,当用户完成编辑(例如按下回车键)时会发出该信号。然而,如果设置了验证器或输入掩码,则只有在输入有效时才会发出editingFinished信号。

但是,无论输入是否有效,我如何才能对用户完成编辑做出反应?我需要手动检查Enter、Return、小部件失去焦点等吗?

原因是:我想创建一个自定义的小部件来使用QDoubleValidator编辑数字。当用户完成编辑并且输入无效(范围错误、空文本等),我希望将其重置为某个有效的默认值。类似于这样:

class NumberEdit: public QLineEdit
{
public:
    NumberEdit(double min, double max)
    {
        setValidator(new QDoubleValidator(min, max, 10));
        setText(QString::number(min));

        connect(this, /* this is the problem */, [this, min]() {
            if(!hasAcceptableInput())
                setText(QString::number(min));    // Reset to valid number
        });
    }
};
1个回答

10

我认为您并不需要子类化QLineEdit

QLineEdit没有Acceptable输入时,改变其值的正确方法是重写QValidator并提供fixup()的实现。来自文档的描述如下:

fixup()是为那些能够修复一些用户错误的验证器提供的。 默认实现什么也不做。QLineEdit会在用户按下Enter(或Return)且内容无效时调用fixup()。 这允许fixup()函数有机会执行一些魔法,使一个Invalid字符串成为Acceptable

由于您正在使用 QDoubleValidator,因此您可以对其进行子类化,并为 fixup() 提供实现,因为它没有这个功能,请参见此处

该类应该如下所示:

class MyDoubleValidator : public QDoubleValidator{
public:
    explicit MyDoubleValidator(QObject* parent= nullptr)
        :QDoubleValidator(parent){}
    MyDoubleValidator(double bottom, double top, int decimals, QObject* parent=nullptr)
        :QDoubleValidator(bottom, top, decimals, parent){}

    virtual void fixup(QString& input)const override{
        input= QString::number(bottom(), 'f', decimals());
    }
};

那么,您可以像这样使用验证器与任何QLineEdit一起使用:
lineEdit->setValidator(new MyDoubleValidator(100, 200, 2, lineEdit));

请注意,这种方式下 lineEdit 将在每次编辑后发出 editingFinished() 信号。因为即使 QLineEdit 的内容不是 Acceptable,我们的 fixup() 实现也会始终将内容“修复”为 Acceptable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接