QLineEdit:将光标位置设置为开始对焦

我有一个带有输入掩码的QLineEdit ,因此可以轻松地输入(或粘贴)某种代码。 由于您可以将光标放在QLineEdit任何位置,即使没有文本(因为输入掩码中有一个占位符):

如果人们粗心大意并且注意力不够,这会导致他们在文本框中间键入内容,而他们应该从头开始键入内容。 我尝试了通过安装一个事件过滤器确保光标处于焦点位置的简单方法:

bool MyWindowPrivate::eventFilter(QObject * object, QEvent * event)
{
    if (object == ui.tbFoo && event->type() == QEvent::FocusIn) {
        ui.tbFoo->setCursorPosition(0);
    }
    return false;
}

这适用于keybaord焦点,即当按⇆或⇧+⇆时,但用鼠标点击时,光标总是会在我点击的地方结束。 我的猜测是, QLineEdit在获得焦点后单击自身时设置光标位置,从而消除我的位置变化。

深入挖掘一下,当点击¹并因此改变焦点时,会发生以下事件:

  • FocusIn
  • MouseButtonPress
  • MouseButtonRelease
  • 我无法在事件过滤器中完全捕获鼠标点击,因此是否有一种很好的方法来设置光标位置,使其仅在控件聚焦时(无论是通过鼠标还是键盘)启动?


    ¹旁注:我讨厌Qt没有关于此类常见场景的信号/事件订单的任何文档。


    下面是一个被分解到一个单独的类中的实现。 它将光标的设置推迟到针对该对象发布任何未决事件之后,从而避免了事件顺序的问题。

    #include <QApplication>
    #include <QLineEdit>
    #include <QFormLayout>
    #include <QMetaObject>
    
    // Note: A helpful implementation of
    // QDebug operator<<(QDebug str, const QEvent * ev)
    // is given in http://stackoverflow.com/q/22535469/1329652
    
    /// Returns a cursor to zero position on a QLineEdit on focus-in.
    class ReturnOnFocus : public QObject {
       Q_OBJECT
       /// Catches FocusIn events on the target line edit, and appends a call
       /// to resetCursor at the end of the event queue.
       bool eventFilter(QObject * obj, QEvent * ev) {
          QLineEdit * w = qobject_cast<QLineEdit*>(obj);
          // w is nullptr if the object isn't a QLineEdit
          if (w && ev->type() == QEvent::FocusIn) {
             QMetaObject::invokeMethod(this, "resetCursor",
                                       Qt::QueuedConnection, Q_ARG(QWidget*, w));
          }
          // A base QObject is free to be an event filter itself
          return QObject::eventFilter(obj, ev);
       }
       // Q_INVOKABLE is invokable, but is not a slot
       /// Resets the cursor position of a given widget.
       /// The widget must be a line edit.
       Q_INVOKABLE void resetCursor(QWidget * w) {
          static_cast<QLineEdit*>(w)->setCursorPosition(0);
       }
    public:
       ReturnOnFocus(QObject * parent = 0) : QObject(parent) {}
       /// Installs the reset functionality on a given line edit
       void installOn(QLineEdit * ed) { ed->installEventFilter(this); }
    };
    
    class Ui : public QWidget {
       QFormLayout m_layout;
       QLineEdit m_maskedLine, m_line;
       ReturnOnFocus m_return;
    public:
       Ui() : m_layout(this) {
          m_layout.addRow(&m_maskedLine);
          m_layout.addRow(&m_line);
          m_maskedLine.setInputMask("NNNN-NNNN-NNNN-NNNN");
          m_return.installOn(&m_maskedLine);
       }
    };
    
    int main(int argc, char *argv[])
    {
       QApplication a(argc, argv);
       Ui ui;
       ui.show();
       return a.exec();
    }
    
    #include "main.moc"
    

    您可以在focusInEvent使用QTimer调用将光标位置设置为0的插槽。

    这很好,因为单次计时器在对象的事件队列的末尾发送一个计时器事件。 鼠标始发的焦点事件必须将鼠标点击发送到事件队列。 因此,您可以确保定时器的事件(以及由此产生的槽调用)将在任何持续的鼠标按下事件后被调用。

    void LineEdit::focusInEvent(QFocusEvent *e)
    {
        QLineEdit::focusInEvent(e);
        QTimer::singleShot(0, this, SLOT(resetCursorPos()));
    }
    
    void LineEdit::resetCursorPos()
    {
        setCursorPosition(0);
    }
    

    设置一个验证器而不是输入掩码。 http://doc.qt.io/qt-5/qregularexpressionvalidator.html

    链接地址: http://www.djcxy.com/p/39311.html

    上一篇: QLineEdit: Set cursor location to beginning on focus

    下一篇: QWebView set border visible