基于QItemDelegate的例子2 trackeEditorDelegate

 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);
}

你可能感兴趣的:(例子)