首页 > 解决方案 > 当有委托时,使 QTableView 的 Key_Up 和 Key_Tab 行为相同

问题描述

我有一个 QTable,其中一列有时,即某些行,有一个 QLineEdit 类型的委托编辑器。用户只能选择整行。当一个 QLineEdit 具有焦点并且用户按下 Key_Up/Key_Down 时,上一行/下一行被选中,并且上一个/下一个 QLineEdit 自动获得焦点。如何为选项卡获得相同的行为?我试图在表格视图中捕获关键事件,即

void ScalarTableTableView::keyPressEvent(QKeyEvent *event)
{
    // Change tab to arrow up/down to be able to move to next row with one key.
    if(event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)
    {
        QKeyEvent newEvent(event->type(),
                           event->key() == Qt::Key_Tab ? Qt::Key_Down : Qt::Key_Up,
                           event->modifiers(),
                           event->nativeScanCode(),
                           event->nativeModifiers(),
                           event->nativeVirtualKey(),
                           event->text(),
                           event->isAutoRepeat(),
                           event->count());
        event->accept();
        MoveBetweenViewsWithDragAndDropTableView::keyPressEvent(&newEvent);
    }
    else
    {
        MoveBetweenViewsWithDragAndDropTableView::keyPressEvent(event);
    }
}

这适用于选择上一行/下一行,但 QLineEdit 没有获得焦点。我需要手动设置焦点吗?如果是这样,我怎样才能获得某一行的委托 QLineEdit?这似乎隐藏在 QAbstractItemView 的私有部分中。

经过测试的解决方案不起作用:

void ScalarTableTableView::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)
    {
        QModelIndex newCurrent = moveCursor(event->key() == Qt::Key_Tab ? MoveDown: MoveUp, event->modifiers());
        QItemSelectionModel::SelectionFlags command = selectionCommand(newCurrent, event);
        selectionModel()->setCurrentIndex(newCurrent, command);
        return;
    }
    QTableView::keyPressEvent(event);
}

在 QLineEdit 中捕获制表键不起作用 - 它永远不会到达那里。

调用 QAbstractItemView::edit 也不起作用。

最小可重现示例

主文件

#include "delegate.h"
#include "MyTableModel.h"
#include "MyTableView.h"
#include <QApplication>
#include <QHeaderView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyTableModel model;
    MyTableView tableView;
    tableView.setModel(&model);
    tableView.setSelectionBehavior(QAbstractItemView::SelectRows);
    SpinBoxDelegate delegate;
    tableView.setItemDelegate(&delegate);

    for (int i = 0; i < 2; i++)
    {
        tableView.openPersistentEditor(model.createIndexValue(i, 1));
    }

    tableView.horizontalHeader()->setStretchLastSection(true);

    tableView.setWindowTitle(QObject::tr("Delegate"));
    tableView.show();
    return app.exec();
}

委托人.h

#ifndef DELEGATE_H
#define DELEGATE_H

#include <QStyledItemDelegate>

class SpinBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    SpinBoxDelegate(QObject *parent = nullptr);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override;

    void setEditorData(QWidget *editor, const QModelIndex &index) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const override;

    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const override;
};

#endif

委托.cpp

#include "delegate.h"

#include <QLineEdit>

SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
}
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    QLineEdit *editor = new QLineEdit(parent);

    return editor;
}
void SpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QLineEdit *edit = static_cast<QLineEdit*>(editor);
    edit->setText(std::to_string(value).c_str());
}
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QLineEdit *edit = static_cast<QLineEdit*>(editor);
    int value = stoi(edit->text().toStdString());

    model->setData(index, value, Qt::EditRole);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
                                           const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

MyTableModel.h

#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H

#include <QAbstractTableModel>

class MyTableModel : public QAbstractTableModel
{
public:
    explicit MyTableModel(QObject *parent = nullptr);

    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    QModelIndex createIndexValue(int row, int column) {return createIndex(row, column);}
};

#endif // MYTABLEMODEL_H

MyTableModel.cpp

#include "MyTableModel.h"

MyTableModel::MyTableModel(QObject *parent) : QAbstractTableModel(parent)
{

}


int MyTableModel::columnCount(const QModelIndex &parent) const
{
    return 2;
}

QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
    return std::to_string((index.column() + 1) * (index.row() + 1)).c_str();
}

Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const
{
    return Qt::ItemNeverHasChildren|Qt::ItemIsEnabled|Qt::ItemIsSelectable;
}

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    return 2;
}

MyTableView.h

#ifndef MYTABLEVIEW_H
#define MYTABLEVIEW_H

#include <QTableView>

class MyTableView : public QTableView
{
public:
    MyTableView();
protected:
   void keyPressEvent(QKeyEvent *event) override;
};

#endif // MYTABLEVIEW_H

MyTableView.cpp

#include "MyTableView.h"

#include <QKeyEvent>

MyTableView::MyTableView()
{

}


void MyTableView::keyPressEvent(QKeyEvent *event)
{
    // Change tab to arrow up/down to be able to move to next row with one key.
    if(event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)
    {
        QKeyEvent newEvent(event->type(),
                           event->key() == Qt::Key_Tab ? Qt::Key_Down : Qt::Key_Up,
                           event->modifiers(),
                           event->nativeScanCode(),
                           event->nativeModifiers(),
                           event->nativeVirtualKey(),
                           event->text(),
                           event->isAutoRepeat(),
                           event->count());
        //QCoreApplication::sendEvent(this, &newEvent);
        event->accept();
        QTableView::keyPressEvent(&newEvent);
    }
    else
    {
        QTableView::keyPressEvent(event);
    }
}

标签: qtqt5

解决方案


推荐阅读