Qt子类QttyledItemDelegate不提供列的编辑

时间:2015-01-06 01:04:06

标签: c++ qt model

我对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现在可以编辑,但是当我按Enter键时,它会重置为默认值,我注意到setData()永远不会被调用。我现在缺少什么?

2 个答案:

答案 0 :(得分:0)

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

  

默认情况下,模型是只读的。要使它成为读写,你必须   将它子类化并重新实现setData()和flags()。另一种选择是   使用QSqlTableModel,它提供了基于a的读写模型   单个数据库表。

所以编辑委托在这里没有任何意义。因此,请尝试使用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();

这就是你所需要的,物品代表现在正在工作(我在我的电脑上测试过,它有效)

答案 1 :(得分:0)

在我的项目进展之后,对QSqlQueryModelQSortFilterProxyModel进行子分类并没有满足我的需要,所以我切换到QStandardItemModel,因为我需要阅读一些行和列仅

将某些列设置为只读:     StudentNotesModel :: StudentNotesModel(int rows,int columns,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);