Qt utilisant Qitemdelegate personnalisé pour QTableView

j'ai suivi le tutoriel Spin Box Delegate, que Qt fournit, pour essayer d'implémenter mon propre QItemDelegate. Il peut être utilisé pour spécifier un QComboBox pour représenter les données dans un QTableView cellule, mais il ne fonctionne pas.

enter image description here

Mon plus gros problème est que je ne sais pas quand mon QItemDelegate va être utilisé.

  • quand itemModel->setData() est utilisé ou lorsque itemModel->setItem(). Je soupçonne setItem() parce que j'ai réimplementé un QItemDelegate (accent sur le "Point"), mais le tutoriel utilise setData() et il fonctionne très bien.

  • je sais que si l' QItemDelegate ne fonctionne pas, il utilise celui par défaut, mais comment puis-je maintenant que celle que j'ai indiquée ne fonctionne pas?

  • quand dois-je suspect pour QTableView pour utiliser mon délégué. Je voudrais préciser quels délégués utiliser pour chaque cellule. Est-ce possible ou ne l' QTableView n'utiliser qu'un seul délégué à travers?

  • Comment puis-je spécifier les éléments pour remplir le QComboBox une fois affiché par le <!--8?

j'ai mis en place QItemDelegate ici:

  • la partie où j'essaie d'ajouter de la cellule qui est supposé utiliser le QComboBox est sous le commentaire "Activé" dans mainwindow.rpc plus bas dans cette post.

qcomboboxitemdelegate.h

#ifndef QCOMBOBOXITEMDELEGATE_H
#define QCOMBOBOXITEMDELEGATE_H

#include <QItemDelegate>
#include <QComboBox>

class QComboBoxItemDelegate : public QItemDelegate
{
    Q_OBJECT

public: 

    explicit QComboBoxItemDelegate(QObject *parent = 0);

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

signals:

private:

};

#endif // QCOMBOBOXITEMDELEGATE_H

qcomboboxitemdelegate.rpc

#include "qcomboboxitemdelegate.h"
#include <QDebug>

QComboBoxItemDelegate::QComboBoxItemDelegate(QObject *parent)
: QItemDelegate(parent)
{

}

QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const   QStyleOptionViewItem &option, const QModelIndex &index) {
    // create widget for use
    QComboBox* comboBox = new QComboBox(parent);
    return comboBox;
}

void QComboBoxItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) {
    // update model widget
    QString value = index.model()->data(index, Qt::EditRole).toString();
    qDebug() << "Value:" << value;
    QComboBox* comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentIndex(comboBox->findText(value));
}

void QComboBoxItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,   const QModelIndex &index) {
    // store edited model data to model
    QComboBox* comboBox = static_cast<QComboBox*>(editor);
    QString value = comboBox->currentText();
    model->setData(index, value, Qt::EditRole);
}

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

mainwindow.rpc : c'est là que j'initialise l' QStandardItemModel

void MainWindow::init() {
    itemModel = new QStandardItemModel(this);
}

void MainWindow::setupUi() {
    this->setWindowTitle("QAlarmClock");        
    QStringList labelList;
    labelList << "Alarm Name" << "Time" << "Enabled";
    itemModel->setHorizontalHeaderLabels(labelList);    
    ui->tableView->setModel(itemModel);
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableView->setItemDelegate(comboBoxItemDelegate);
}

void MainWindow::on_actionNew_triggered() {
    alarmDialog = new AlarmDialog(this);
    connect(alarmDialog, SIGNAL(on_close()), this, SLOT(on_alarmDialog_close()));
    alarmDialog->exec();
}

mainwindow.cpp: c'est ici que je mets à jour QStandardItemModel

void MainWindow::on_alarmDialog_close() {
    QString alarmName = alarmDialog->getAlarmName();
    QDateTime alarmDateTime = alarmDialog->getDateTime();

    itemModel->insertRow(itemModel->rowCount());
    int rowCount = itemModel->rowCount();

    // Alarm Name
    QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"),  alarmName);
    itemModel->setItem(rowCount - 1 , 0, alarmItem);

    // Date Time
    QStandardItem* dateTimeItem = new QStandardItem();
    dateTimeItem->setText(alarmDateTime.toString());
    dateTimeItem->setEditable(false);
    itemModel->setItem(rowCount - 1, 1, dateTimeItem);

    // Enabled
    QStandardItem* enabledItem = new QStandardItem();
    QList<QStandardItem*> optionList;
    optionList << new QStandardItem("Enabled") << new QStandardItem("Disabled");
    enabledItem->appendRows(optionList);
    itemModel->setItem(rowCount - 1, 2, enabledItem);
}

Edit 1

qcomboboxdelegate.rpc

QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) {
    // create widget for use
    qDebug() << "Column: " << index.column();
    if (index.column() == 2) {
        QComboBox* comboBox = new QComboBox(parent);
        QStringList values;
        values << "Enabled" << "Disabled";
        comboBox->addItems(values);
        return comboBox;
    } else {
        return QItemDelegate::createEditor(parent, option, index);
    }
}

mainwindow.rpc

void MainWindow::on_alarmDialog_close() {
    QList<QStandardItem*> row;

    QString alarmName = alarmDialog->getAlarmName();
    QDateTime alarmDateTime = alarmDialog->getDateTime();
    QString status = "Enabled";

    // Alarm Name
    QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"), alarmName);
    row << alarmItem;

    // Date Time
    QStandardItem* dateTimeItem = new QStandardItem();
    dateTimeItem->setText(alarmDateTime.toString());
    dateTimeItem->setEditable(false);
    row << dateTimeItem;

    // Enabled
    QStandardItem* statusItem = new QStandardItem(status);
    row << statusItem;

    itemModel->appendRow(row);
}
11
demandé sur O'Neil 2013-05-21 04:27:16

2 réponses

tout d'abord, vous devriez avoir une description de vos colonnes modèles:

enum Columns
{
    COL_NAME,
    COL_TIME,
    COL_STATUS
}

Votre délégué ne doit travailler pour la dernière colonne.

Voici un exemple de comment vous pouvez remplir votre modèle:

for (int i = 0; i < 5; ++i)
{
    QStandardItem *itemName = new QStandardItem(QString("name %1").arg(i));
    QStandardItem *itemTime = new QStandardItem(QString("time %1").arg(i));

    QString status;
    if (i % 2 == 0)
    {
        status = "Enabled";
    }
    else
    {
        status = "Disabled";
    }

    QStandardItem *itemStatus = new QStandardItem(status);

    QList<QStandardItem*> row;
    row << itemName << itemTime << itemStatus;

    model->appendRow(row);
}

Comme je l'ai dit, votre délégué ne doit travailler pour la dernière colonne. Donc toutes les méthodes que vous avez reimplementées devraient avoir une colonne de vérification comme ceci:

QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, 
                            const QStyleOptionViewItem &option, 
                            const QModelIndex &index) 
{
    if (index.column() == COL_STATUS)
    {
        QStringList values;
        values << "Enabled" << "Disabled";

        QComboBox* comboBox = new QComboBox(parent);
        comboBox->addItems(values);
        return comboBox;
    }
    else
    {
        return QItemDelegate::createEditor(parent, option, index);
    }
}

Vous devez ajouter cette case pour les autres méthodes: si la colonne n'est pas la colonne de statut, la classe de base (QItemDelegate) la mise en oeuvre devrait être utilisée.

puis vous mettez votre délégué à votre vue:

ui->tableView->setItemDelegate(new ComboBoxDelegate);

Si vous faites tout droit, une liste déroulante apparaît dans la dernière colonne, si vous essayez de modifier ses valeurs.

10
répondu hank 2018-08-30 04:37:14

alors j'ai compris que je n'avais pas outrepassé les prototypes de fonction corrects..! J'ai oublié qu'ils avait const dans le prototype ce qui signifie que je n'ai pas dépassé toutes les fonctions donc il a utilisé les par défaut. Voici les bonnes fonctions virtuelles qui doivent être ré-implémentées:http://qt-project.org/doc/qt-5.0/qtwidgets/qitemdelegate.html

2
répondu arnm 2013-05-21 14:52:00