Qtが提供するスピンボックスデリゲートチュートリアルに従って、独自のQItemDelegate
を実装しようとしました。 QComboBox
セルのデータを表すQTableView
を指定するために使用されますが、機能しません。
私の最大の問題は、QItemDelegate
がいつ使用されるかわからないことです。
itemModel->setData()
を使用する場合、またはitemModel->setItem()
を使用する場合。 QItemDelegate
(「アイテム」を強調)を再実装したのでsetItem()
を疑いますが、チュートリアルではsetData()
を使用しており、正常に機能します。
指定したQItemDelegate
が機能しない場合はデフォルトの機能を使用することはわかっていますが、指定した機能が機能しなかった場合はどうすればよいですか?
デリゲートを使用するQTableView
をいつ疑うべきですか。各セルに使用するデリゲートを指定したいと思います。これは可能ですか、またはQTableView
は全体で1つのデリゲートのみを使用しますか?
QComboBox
によって表示された後、QTableView
に入力する項目をどのように指定しますか?
ここにQItemDelegate
を実装しました:
QComboBox
を使用すると想定されるセルを追加しようとする部分は、この投稿のさらに下のmainwindow.cppの「Enabled」というコメントの下にあります。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.cpp
#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.cpp:ここで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:ここで、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);
}
編集1
qcomboboxdelegate.cpp
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.cpp
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);
}
最初に、モデル列の説明が必要です。
enum Columns
{
COL_NAME,
COL_TIME,
COL_STATUS
}
デリゲートは最後の列でのみ機能します。
以下は、モデルを設定する方法の例です。
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);
}
既に述べたように、デリゲートは最後の列でのみ機能します。したがって、再実装したすべてのメソッドには、次のような列チェックが必要です。
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);
}
}
このチェックを他のメソッドに追加する必要があります。現在の列がステータス列でない場合は、基本クラス(QItemDelegate
)実装を使用する必要があります。
次に、デリゲートを自分のビューに設定します。
ui->tableView->setItemDelegate(new ComboBoxDelegate);
すべてを正しく行うと、値を編集しようとすると、最後の列にコンボボックスが表示されます。
だから私は正しい関数プロトタイプを上書きしていないことに気づきました。プロトタイプにconstが含まれていたことを忘れていました。つまり、関数をオーバーライドしていないため、デフォルトの関数を使用していました。再実装する必要がある正しい仮想関数を以下に示します。 http://qt-project.org/doc/qt-5.0/qtwidgets/qitemdelegate.html
さらに簡単です。 QTableView :: setItemDelegateForColumn()が列に対して見事に機能することがわかりました。たとえば、MainWindowでメンバーを作成できます。
_QComboBoxItemDelegate dgtComboDelegate;
_
次に、あなたのctor、またはinit()で、
_ui->tableView->setItemDelegateForColumn(2, dgtComboDelegate);
_
単一のセルでそれを実行したい場合は、index.column()とindex.row()でテストする必要があります。
これを行うためにQTableViewを作成する必要もありません。たとえば、?:
OPはそれがテーブルウィジェットかビューかを指定することはありませんが、どちらでも同じように機能するはずです。
あなたの場合、あなたはui->tableWidget->setItemDelegateForColumn(2, dgtComboDelegate);
を行うことができ、あなた自身のモデルを作る必要はありません。作成したアイテムでsetData()を使用して、その値を初期化するだけです。