2011年12月16日金曜日

( Qt C++ )カスタムデリゲートを実装しQTableViewに表示させる


ie9のフォントレンダリング見にくいと思ってるの私だけですかね?gdipp効かせたFireFox使ってるとie9を使った時フォントの汚さに圧倒されます。gdippのメンバー雇ってまともなフォントレンダリング作って欲しいなぁ...。

はいそれでは表題の "カスタムデリゲートの実装しQTableViewに表示させる" をやっていきます。サンプルは "Spin Box Delegate Example" のを一部変更して使用します。C++ GUI Programming with Qt4 244ページにもサンプルは載っていますが長いので使うのをやめました。それではコードを


 (spinboxdelegate.h)
#include <QItemDelegate>

class SpinBoxDelegate : public QItemDelegate
{
    Q_OBJECT//マクロ 
public:
    explicit SpinBoxDelegate(QObject *parent = 0);//コンストラクタ

    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;

    void updateEditorGeometry(QWidget *editor,
                    const QStyleOptionViewItem &option, const QModelIndex &index) const;
};


 (spinboxdelegate.cpp)
#include "spinboxdelegate.h"
#include "QSpinBox"

SpinBoxDelegate::SpinBoxDelegate(QObject *parent) :
    QItemDelegate(parent)//基本クラスにparent渡すだけ
{
}

QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setMinimum(0);
    editor->setMaximum(100);

    return editor;
}//0~100までの値で制限したスピンボックスを返す

void SpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->setValue(value);
}//モデルからデータ読取、整数変換し、editorウィジットに書き込む

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();

    model->setData(index, value, Qt::EditRole);
}//スピンボックスの内容読込、モデルに書き込む

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
                           const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
} //スタイルオプションで指定した情報を元にウィジットのジオメトリを更新

 はい、簡単ですね。ヘッダ部は見てのとおりです。なお、createEditor(), setEditorData(), setModelData(), updateEditorGeometry()はQItemDelegateにあるもののオーバーライドです。
次にcppですがコメントのとおりです。ほとんど設定ばかりで難しいことは行っていません。
ではこれをつかってQTableViewに表示していきます。

#include "spinboxdelegate.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)//uiにGUI部品が定義
{
    ui->setupUi(this);//uiのGUI部品を初期化

   QStandardItemModel *model = new QStandardItemModel(4, 2);//注意!newしてください。
    for (int row = 0; row < 4; ++row)//モデルにデータをセット
    {
        for (int column = 0; column < 2; ++column)
        {
            QModelIndex index = model->index(row, column, QModelIndex());
            model->setData(index, QVariant((row+1) * (column+1)));
        }
    }

    ui->tableView->setModel(model);
   SpinBoxDelegate *delegate = new SpinBoxDelegate;//注意!newしてください。
   ui->tableView->setItemDelegate(delegate);//デリゲートセット
}

ui部はただGUI部品が記述されているだけなので説明しません。QStandardItemModelは
Qt既定のモデルクラスで任意の階層データを格納できます。このモデルにデータを格納したあと、uiのQTableViewにセットしています。その後SpinBoxDelegateの実体を作成し、またuiのQTableViewにデリゲートをセットしています。

実行すると以下のようになります。
 
以上です。