trackeEditorDelegate例子是《 C++ GUI Programming with Qt 4》中自定义委托的标准例子。
和上一个SpinBox例子相比更完整:它多了自定义Editor、重载Paint()函数、提交数据信号commitData()、关闭控件信号closeEditor()
附件中有源码可以下载。
Main.cpp
#include <QApplication>
#include "trackeditor.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QList<Track> tracks;
tracks << Track("The Flying Dutchman: Overture", 630)
<< Track("The Flying Dutchman: Wie aus der Fern laengst "
"vergangner Zeiten", 374)
<< Track("The Flying Dutchman: Steuermann, lass die Wacht",
152)
<< Track("Die Walkuere: Ride of the Valkyries", 286)
<< Track("Tannhaeuser: Freudig begruessen wir die edle "
"Halle", 384)
<< Track("Tannhaeuser: Wie Todesahnung - O du mein holder "
"Abendstern", 257)
<< Track("Lohengrin: Treulich gefuert ziehet dahnin", 294)
<< Track("Lohengrin: In fernem Land", 383)
<< Track("Die Meistersinger von Nuernberg: Overture", 543)
<< Track("Die Meistersinger von Nuernberg: Verachtet mir "
"die Meister nicht", 200)
<< Track("Die Meistersinger von Nuernberg: Ehrt eure "
"deutschen Meister", 112)
<< Track("Goetterdaemmerung: Funeral Music", 469)
<< Track("Tristan und Isolde: Mild und leise, wie er "
"laechelt", 375);
//自定义编辑控件
TrackEditor editor(&tracks);
editor.resize(600, 300);
editor.show();
return app.exec();
}
TrackEditor.h
#ifndef TRACKEDITOR_H
#define TRACKEDITOR_H
#include <QDialog>
#include <QList>
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<Track> *tracks, QWidget *parent = 0);
void done(int result);
private slots:
void addTrack();
private:
QTableWidget *tableWidget;
QDialogButtonBox *buttonBox;
QList<Track> *tracks;
};
#endif
TrackEditor.cpp
#include <QtGui>
#include "trackdelegate.h"
#include "trackeditor.h"
Track::Track(const QString &title, int duration)
{
this->title = title;
this->duration = duration;
}
TrackEditor::TrackEditor(QList<Track> *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
#include <QItemDelegate>
class 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 <QtGui>
#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<QTimeEdit *>(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<QTimeEdit *>(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<QTimeEdit *>(sender());
//提交该控件的值 否则模型中数据不更改
emit commitData(editor);
//关闭该控件 可以告知委托去代开下一个控件
emit closeEditor(editor);
}