さて、ついに私はそれについていくつかの研究をしました。
説明
ビューがcreateEditorデリゲートの関数を呼び出すと、デリゲートイベントフィルターもエディターにインストールされます。
QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
                                          const QStyleOptionViewItem &options)
{
    Q_Q(QAbstractItemView);
    QWidget *w = editorForIndex(index).widget.data();
    if (!w) {
        QAbstractItemDelegate *delegate = delegateForIndex(index);
        if (!delegate)
            return 0;
        w = delegate->createEditor(viewport, options, index);
        if (w) {
            w->installEventFilter(delegate);
    ......
}
ただし、デリゲートはエディターウィジェットのイベントのみをキャッチでき、その子のイベントはキャッチできません。Tabキーが押されると、関数QWidget::eventが呼び出され、それを使用してフォーカスを別のウィジェットに変更します。
bool QWidget::event(QEvent *event)
{
    ......
    switch (event->type()) {
        ......
        case QEvent::KeyPress: {
        QKeyEvent *k = (QKeyEvent *)event;
        bool res = false;
        if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
            if (k->key() == Qt::Key_Backtab
                || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
                res = focusNextPrevChild(false);
            else if (k->key() == Qt::Key_Tab)
                res = focusNextPrevChild(true);
            if (res)
                break;
        }
        ......
    }
    ......
}
したがって、私の場合、フォーカスはnext QPushButtonafterに設定されQLineEdit、イベントは親に伝播されません(LineEditor)。
解決する
問題を解決する正しい方法QSpinBoxはそれと同じです。もあるのでQLineEdit。ウィジェットのコンストラクターでは、行編集用のフォーカスプロキシを設定します。
edit->setFocusProxy(this);
したがって、すべてのフォーカスイベントがメインウィジェットに到達します。また、デフォルトfocusPolicyであるため、プロパティを設定する必要があります。NoFocus
setFocusPolicy(Qt::WheelFocus);
この瞬間に必要なのは、QLineEdit次のようにメインウィジェットから必要なイベントを伝播することだけです。
bool LineEditor::event(QEvent *e)
{
    switch(e->type())
    {
    case QEvent::ShortcutOverride:
        if(m_lineEdit->event(e))
            return true;
        break;
    case QEvent::InputMethod:
        return m_lineEdit->event(e);
    default:
        break;
    }
    return QWidget::event(e);
}
void LineEditor::keyPressEvent(QKeyEvent *e)
{
    m_lineEdit->event(e);
}
void LineEditor::mousePressEvent(QMouseEvent *e)
{
    if(e->button() != Qt::LeftButton)
        return;
    e->ignore();
}
void LineEditor::mouseReleaseEvent(QMouseEvent *e)
{
    e->accept();
}
void LineEditor::focusInEvent(QFocusEvent *e)
{
    m_lineEdit->event(e);
    QWidget::focusInEvent(e);
}
void LineEditor::focusOutEvent(QFocusEvent *e)
{
    m_lineEdit->event(e);
    QWidget::focusOutEvent(e);
}
これで十分です。
トリッキー
上で述べたように、デリゲートは編集者の子のイベントをキャッチできません。したがって、編集者の動作を「ネイティブ」のようにするには、子から編集者にイベントを複製する必要があります。
LineEditorQLineEditコンストラクターにイベントフィルターをインストールします。
edit->installEventFilter(this);
フィルタの実装は次のようになります。
bool LineEditor::eventFilter(QObject *object, QEvent *event)
{
    if(event->type() == QEvent::KeyPress)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent *>(event);
        if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab)
        {
            QApplication::postEvent(this, new QKeyEvent(keyEvent->type(), keyEvent->key(), keyEvent->modifiers()));
            // Filter this event because the editor will be closed anyway
            return true;
        }
    }
    else if(event->type() == QEvent::FocusOut)
    {
        QFocusEvent* focusEvent = static_cast<QFocusEvent *>(event);
        QApplication::postEvent(this, new QFocusEvent(focusEvent->type(), focusEvent->reason()));
        // Don't filter because focus can be changed internally in editor
        return false;
    }
    return QWidget::eventFilter(object, event);
}
とにかくこのイベントをフィルタリングするqApp->notify(this, event)ため、QKeyEvent代わりにを使用することもできます。QApplication::postEventただし、イベントをリダイレクトし、子に到達しないため、それは不可能ですQFocusEvent。notify
標準(QItemDelegateまたはQStyledItemDelegate)デリゲートは、フォーカスがそれ自体で内部的に変更された場合の状況を気にすることに注意してください。
if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
        //the Hide event will take care of he editors that are in fact complete dialogs
        if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
            QWidget *w = QApplication::focusWidget();
            while (w) { // don't worry about focus changes internally in the editor
                if (w == editor)
                    return false;
                w = w->parentWidget();
            }
    ......