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

Joe*_*oey 3 c++ qt focus qlineedit

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

在此输入图像描述

如果人们不小心且不专心,这会导致他们在文本框的中间键入,而他们应该在开头打字.我尝试了通过安装事件过滤器确保光标在焦点开始时的简单方法:

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

这与keybaord焦点一起工作正常,即按下+时,但是当用鼠标点击时,光标总是在我点击的位置结束.我的猜测是,QLineEdit设置在点击自己的光标位置它得到了关注,从而解开我的位置变化.

深入挖掘,点击¹,从而按以下顺序更改焦点时,会引发以下事件:

  1. FocusIn
  2. MouseButtonPress
  3. MouseButtonRelease

我无法在事件过滤器中完全捕获鼠标点击,因此有一种很好的方法可以将光标位置设置为在控件被聚焦时启动(无论是通过鼠标还是键盘)?


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

Rei*_*ica 7

下面是一个实现,它被分解为一个单独的类.它将光标的设置推迟到为对象发布任何待处理事件之后,从而回避事件顺序的问题.

#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"
Run Code Online (Sandbox Code Playgroud)