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.
Mon plus gros problème est que je ne sais pas quand mon QItemDelegate
va être utilisé.
quand
itemModel->setData()
est utilisé ou lorsqueitemModel->setItem()
. Je soupçonnesetItem()
parce que j'ai réimplementé unQItemDelegate
(accent sur le "Point"), mais le tutoriel utilisesetData()
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);
}
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.
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