Qt 子类 QStyledItemDelegate 不提供对列的编辑

Qt subclassed QStyledItemDelegate does not provide editing for columns

我将 QStyledItemDelegate 分类为 QTableView 提供编辑,我的问题是委托从未被称为女巫意味着如果双击没有编辑行为。另外,我检查了函数签名,它们看起来是正确的。

StudentNotesDelegate

#include "studentnotesdelegate.h"
#include <QLineEdit>
#include <qDebug>

StudentNotesDelegate::StudentNotesDelegate(QWidget *parent): QStyledItemDelegate(parent)
{
}


QWidget *StudentNotesDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
    if (index.column() > 3) {
        QLineEdit *inputText = new QLineEdit(parent);
        qDebug() << "ds:";
        inputText->setFrame(false);
        return inputText;
    }

    return QStyledItemDelegate::createEditor(parent, option, index);
}

void StudentNotesDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const {
    if (index.column() > 3) {
        QString indexValue = index.model()->data(index).toString();
        qDebug() << "Value:" << indexValue;
        QLineEdit *inputText = static_cast<QLineEdit*>(editor);
        inputText->setText(indexValue);
    }
}

void StudentNotesDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
    if (index.column() > 3) {
        QLineEdit *inputText = static_cast<QLineEdit*>(editor);
        QString indexValue = inputText->text();
        model->setData(index, indexValue, Qt::EditRole);
    }
}

void StudentNotesDelegate::updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const {
    if (index.column() > 3) {
        editor->setGeometry(option.rect);
    }
}


#ifndef STUDENTNOTESDELEGATE_H
#define STUDENTNOTESDELEGATE_H

#include <QStyledItemDelegate>

class StudentNotesDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    StudentNotesDelegate(QWidget *parent = 0);

protected:
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void    setEditorData(QWidget *editor, const QModelIndex &index) const;
    void    setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void    updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

#endif // STUDENTNOTESDELEGATE_H

我这样称呼setItemDelegate:

QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("Removed to avoid horizontal scroll");
    ui->listStudentsTable->setModel(model);
    model->insertColumns(3, classMaterials.length());
    StudentNotes::setModelHeader(model, classMaterials, classMaterials.length());
    //ui->listStudentsTable->setItemDelegate(new StudentNotesDelegate); 

更新:

我采用了 QStyledItemDelegate,而不是对 QSqlQueryModel 进行了子分类,并重新实现了 flags()data()setData()

Qt::ItemFlags StudentNotesModel::flags(const QModelIndex &index) const {
    Qt::ItemFlags flags = QSqlQueryModel::flags(index);
    if (index.column() > 2)
        flags |= Qt::ItemIsEditable;

    return flags;
}

QVariant StudentNotesModel::data(const QModelIndex &index, int role) const
{
    return QSqlQueryModel::data(index, role);
}

bool StudentNotesModel::setData(const QModelIndex &index, QVariant &value, int role)
{
    qDebug() << "setData() call";
    if (index.isValid() && index.column() > 2)
    {
        QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model());
        model->setData(index, value, Qt::EditRole);
        emit dataChanged(index, index);
        return true;
    }

    return false;
}

StudentNotesModel *model = new StudentNotesModel;Class.mat_class = " + mat_class;
    model->setQuery("SELECT Student.mat_stud, fname, lname FROM Student, Division, Class "
                    "WHERE Division.mat_div = Class.mat_class AND Student.mat_class = Class.mat_class" + studentsClassRoom);
    ui->listStudentsTable->setModel(model);

QTableView 现在是可编辑的,但是当我按下回车键时它会重置回默认值,我注意到 setData() 从未被调用过。我现在缺少什么?

您的主要问题是QSqlQueryModel,它是只读模型。正如医生所说:

The model is read-only by default. To make it read-write, you must subclass it and reimplement setData() and flags(). Another option is to use QSqlTableModel, which provides a read-write model based on a single database table.

所以编辑委托在这里没有任何意义。因此,请尝试使用 QSqlTableModel 或子类化您当前的模型。

同样在您当前的委托中尝试调用每个方法中的默认实现,就像您在 createEditor() 中所做的那样。

但是子类化可能是一个很长的过程,所以尽量只使用 QSqlTableModel。假设您的代码现在看起来像:

QSqlQueryModel *mmm = new QSqlQueryModel;
mmm->setQuery("SELECT * FROM newTab");
QTableView *view = new QTableView;
view->setItemDelegate(new ItemDelegate);
view->setModel(mmm);
view->show();

然后改成:

QSqlTableModel *mmm = new QSqlTableModel(this,sdb);
mmm->setTable("newTab");
mmm->setEditStrategy(QSqlTableModel::OnManualSubmit);
mmm->select();
QTableView *view = new QTableView;
view->setItemDelegate(new ItemDelegate);
view->setModel(mmm);
view->show();

这就是你所需要的,项目委托现在可以工作了(我在我的电脑上测试过,它可以工作)

在我推进我的项目后,子类化 QSqlQueryModelQSortFilterProxyModel 不能满足我的需要,所以我切换到 QStandardItemModel 因为我需要一些行和列只读。

将某些列设置为只读: StudentNotesModel::StudentNotesModel(整数行,整数列,QObject *parent) :QStandardItemModel(行,列,父级) { }

Qt::ItemFlags StudentNotesModel::flags(const QModelIndex &index) const {
    Qt::ItemFlags flags = QStandardItemModel::flags(index);
    // Line 1,2, and 3 are read only
    if (index.column() < 3) {
        flags &= ~Qt::ItemIsEditable;
    }

    if (index.row() > index.model()->rowCount()) {
        qDebug() << index.row();
        flags &= ~Qt::ItemIsEditable;
    }

    return flags;
}

StudentNotesModel *model = new StudentNotesModel;

将某些行设置为只读:

for (int row = 0; row < numRows ; ++row) {
    for (int col = 0; col < numColumns; ++col) {
        QStandardItem *item = new QStandardItem("0");
        if (row == 7 || row == 8)) {
            item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        }

        model->setItem(row, col, item);