trackeEditorDelegate例子是《 C++ GUI Programming with Qt 4》中自定义委托的标准例子。
和上一个SpinBox例子相比更完整:它多了自定义Editor、重载Paint()函数、提交数据信号commitData()、关闭控件信号closeEditor()
附件中有源码可以下载。
Main.cpp
#include#include "trackeditor.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QList
TrackEditor.h
#ifndef TRACKEDITOR_H #define TRACKEDITOR_H #include#include class QDialogButtonBox; class QTableWidget; class Track { public: Track(const QString &title = "", int duration = 0); QString title; int duration; }; class TrackEditor : public QDialog { Q_OBJECT public: TrackEditor(QList
TrackEditor.cpp
#include#include "trackdelegate.h" #include "trackeditor.h" Track::Track(const QString &title, int duration) { this->title = title; this->duration = duration; } TrackEditor::TrackEditor(QList *tracks, QWidget *parent) : QDialog(parent) { this->tracks = tracks; //视图控件 tableWidget = new QTableWidget(tracks->count(), 2); //设置委托 tableWidget->setItemDelegate(new TrackDelegate(1)); //设置视图列头 tableWidget->setHorizontalHeaderLabels( QStringList() << tr("Track") << tr("Duration")); //初始化视图内容 for (int row = 0; row < tracks->count(); ++row) { Track track = tracks->at(row); QTableWidgetItem *item0 = new QTableWidgetItem(track.title); //设置第0列中所有项 tableWidget->setItem(row, 0, item0); QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(track.duration)); item1->setTextAlignment(Qt::AlignRight); //设置第1列所有项 tableWidget->setItem(row, 1, item1); } //根据委托的SizeHint,重新设置视图大小 tableWidget->resizeColumnToContents(0); buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); QPushButton *addTrackButton = buttonBox->addButton(tr("&Add Track"), QDialogButtonBox::ActionRole); connect(addTrackButton, SIGNAL(clicked()), this, SLOT(addTrack())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(tableWidget); mainLayout->addWidget(buttonBox); setLayout(mainLayout); setWindowTitle(tr("Track Editor")); } void TrackEditor::done(int result) { //ok if (result == QDialog::Accepted) { tracks->clear(); for (int row = 0; row < tableWidget->rowCount(); ++row) { QString title = tableWidget->item(row, 0)->text(); QTableWidgetItem *item = tableWidget->item(row, 1); int duration = item ? item->text().toInt() : 0; tracks->append(Track(title, duration)); } } QDialog::done(result); } void TrackEditor::addTrack() { //在最后新插入一行 tableWidget->insertRow(tableWidget->rowCount()); }
TrackDelegate.h
#ifndef TRACKDELEGATE_H #define TRACKDELEGATE_H #includeclass TrackDelegate : public QItemDelegate { Q_OBJECT public: TrackDelegate(int durationColumn, QObject *parent = 0); //重新绘制 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 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; private slots: void commitAndCloseEditor(); private: int durationColumn; }; #endif
TrackDelegate.cpp
#include#include "trackdelegate.h" TrackDelegate::TrackDelegate(int durationColumn, QObject *parent) : QItemDelegate(parent) { this->durationColumn = durationColumn; } void TrackDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { //保存音轨的列 if (index.column() == durationColumn) { //获得索引对应Model中的数据 int secs = index.model()->data(index, Qt::DisplayRole).toInt(); //设置时间格式字符串 分:秒 QString text = QString("%1:%2") .arg(secs / 60, 2, 10, QChar('0')) .arg(secs % 60, 2, 10, QChar('0')); //获取项风格设置 QStyleOptionViewItem myOption = option; myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; //绘制文本 drawDisplay(painter, myOption, myOption.rect, text); //如果当前有焦点,就绘制一个焦点矩形,否则什么都不做 drawFocus(painter, myOption, myOption.rect); } else{ //否则默认 QItemDelegate::paint(painter, option, index); } } QWidget *TrackDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { //音轨时间列 if (index.column() == durationColumn) { //时间编辑控件 QTimeEdit *timeEdit = new QTimeEdit(parent); //时间编辑控件文本格式 timeEdit->setDisplayFormat("mm:ss"); //如果编辑结束,激活提交和关闭槽 connect(timeEdit, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); return timeEdit; } else { //否则使用默认委托处理 return QItemDelegate::createEditor(parent, option, index); } } //设置控件值 void TrackDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { //音轨时间列 if (index.column() == durationColumn) { //获得当前索引在Model中的值 int secs = index.model()->data(index, Qt::DisplayRole).toInt(); //设置时间控件的值 QTimeEdit *timeEdit = qobject_cast (editor); timeEdit->setTime(QTime(0, secs / 60, secs % 60)); } else { QItemDelegate::setEditorData(editor, index); } } //设置Model值 void TrackDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { //音轨列 if (index.column() == durationColumn) { //获得时间控件值 QTimeEdit *timeEdit = qobject_cast (editor); QTime time = timeEdit->time(); int secs = (time.minute() * 60) + time.second(); //设置模型值 model->setData(index, secs); } else { //否则使用默认委托处理 QItemDelegate::setModelData(editor, model, index); } } //自定义 提交和关闭 槽函数 void TrackDelegate::commitAndCloseEditor() { QTimeEdit *editor = qobject_cast (sender()); //提交该控件的值 否则模型中数据不更改 emit commitData(editor); //关闭该控件 可以告知委托去代开下一个控件 emit closeEditor(editor); }