【保存版】Qtプログラミング チュートリアル:QTreeWidget::mimeData()でドラッグ&ドロップを自由自在に操る


QTreeWidget::mimeData() は、ドラッグ & ドロップ操作におけるデータ転送をサポートするために使用される、QTreeWidget クラスの保護された仮想関数です。この関数は、ドラッグ対象となる QTreeWidgetItem のリストを受け取り、そのアイテムに関連する MIME データを生成して返します。

機能

QTreeWidget::mimeData() は、以下の機能を提供します。

  • 生成された MIME データは、ドラッグ & ドロップ操作におけるデータ転送に使用されます。
  • ドラッグ対象となる QTreeWidgetItem のリストに基づいて MIME データを生成します。

使用方法

QTreeWidget::mimeData() 関数は、以下の手順で使用できます。

  1. ドラッグ & ドロップ操作が発生したことを検出します。
  2. QTreeWidgetItem のリストを取得します。
  3. QTreeWidget::mimeData() 関数を呼び出して、ドラッグ対象となるアイテムに基づいて MIME データを生成します。
  4. 生成された MIME データをドラッグ & ドロップ操作におけるデータ転送に使用します。

以下の例は、QTreeWidget からアイテムをドラッグしたときに、そのアイテムのテキストを MIME データとして生成する方法を示しています。

void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
        event->acceptProposedAction(Qt::CopyAction);
    }
}

QMimeData *MyWidget::mimeData() const
{
    QList<QTreeWidgetItem *> selectedItems = selectionModel()->selectedItems();
    if (selectedItems.isEmpty()) {
        return nullptr;
    }

    QMimeData *mimeData = new QMimeData;
    QStringList textList;
    for (QTreeWidgetItem *item : selectedItems) {
        textList << item->text(0);
    }
    mimeData->setTextList(textList);
    return mimeData;
}

この例では、dragEnterEvent() 関数は、ドラッグされたデータが application/x-qabstractitemmodeldatalist という形式であるかどうかを確認します。この形式は、QAbstractItemModel によって生成された MIME データを表します。形式が一致する場合、acceptProposedAction() 関数を使用して、コピー操作を許可します。

mimeData() 関数は、選択された QTreeWidgetItem のリストを取得し、そのアイテムのテキストを QStringList に格納します。その後、QMimeData オブジェクトを作成し、そのテキストリストを設定して返します。



アイテムのテキストを MIME データとして生成する

void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
        event->acceptProposedAction(Qt::CopyAction);
    }
}

QMimeData *MyWidget::mimeData() const
{
    QList<QTreeWidgetItem *> selectedItems = selectionModel()->selectedItems();
    if (selectedItems.isEmpty()) {
        return nullptr;
    }

    QMimeData *mimeData = new QMimeData;
    QStringList textList;
    for (QTreeWidgetItem *item : selectedItems) {
        textList << item->text(0);
    }
    mimeData->setTextList(textList);
    return mimeData;
}

アイテムのアイコンを MIME データとして生成する

void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
        event->acceptProposedAction(Qt::CopyAction);
    }
}

QMimeData *MyWidget::mimeData() const
{
    QList<QTreeWidgetItem *> selectedItems = selectionModel()->selectedItems();
    if (selectedItems.isEmpty()) {
        return nullptr;
    }

    QMimeData *mimeData = new QMimeData;
    QStringList textList;
    QIconList iconList;
    for (QTreeWidgetItem *item : selectedItems) {
        textList << item->text(0);
        iconList << item->icon(0);
    }
    mimeData->setTextList(textList);
    mimeData->setIconList(iconList);
    return mimeData;
}

この例は、上記の例を拡張して、アイテムのアイコンを MIME データに含める方法を示しています。mimeData() 関数は、選択された QTreeWidgetItem のリストを取得し、そのアイテムのテキストとアイコンをそれぞれ QStringListQIconList に格納します。その後、QMimeData オブジェクトを作成し、そのテキストリストとアイコンリストを設定して返します。

void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-my-custom-format")) {
        event->acceptProposedAction(Qt::CopyAction);
    }
}

QMimeData *MyWidget::mimeData() const
{
    QList<QTreeWidgetItem *> selectedItems = selectionModel()->selectedItems();
    if (selectedItems.isEmpty()) {
        return nullptr;
    }

    QMimeData *mimeData = new QMimeData;
    QDataStream stream(mimeData);
    QStringList textList;
    QIconList iconList;
    for (QTreeWidgetItem *item : selectedItems) {
        textList << item->text(0);
        iconList << item->icon(0);
    }

    stream << textList;
    stream << iconList;

    return mimeData;
}

bool MyWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-my-custom-format")) {
        QDataStream stream(event->mimeData());
        QStringList textList;
        QIconList iconList;

        stream >> textList;
        stream >> iconList;

        // カスタムデータ処理

        return true;
    }

    return QTreeWidget::dropEvent(event);
}


代替方法

主に以下の 2 つの代替方法があります。

シグナルスロット接続

QTreeWidget クラスは、ドラッグ & ドロップ操作に関連するいくつかのシグナルを提供しています。これらのシグナルにスロットを接続することで、ドラッグ & ドロップ操作が発生したときにデータ転送処理を実行できます。

  • dragLeaveEvent() シグナル: ドラッグ中のマウスカーソルがウィジェット領域から出たときに発生します。
  • dragEnterEvent() シグナル: ドラッグ中のマウスカーソルがウィジェット領域に入ったときに発生します。
  • dragMoveEvent() シグナル: ドラッグ中のマウスカーソルが移動したときに発生します。
  • itemsDropped() シグナル: アイテムがドロップされたときに発生します。

これらのシグナルにスロットを接続することで、ドラッグ & ドロップ操作の各段階でデータ転送処理を実行できます。

以下の例は、itemsDropped() シグナルにスロットを接続して、アイテムがドロップされたときにデータ転送処理を実行する方法を示しています。

connect(treeWidget, &QTreeWidget::itemsDropped, this, &MyWidget::handleItemsDropped);

void MyWidget::handleItemsDropped(const QList<QTreeWidgetItem *> &items)
{
    // データ転送処理
}

QAbstractItemModel::itemData() を使用する

QTreeWidgetQAbstractItemModel を使用してデータを表示します。QAbstractItemModel クラスは、itemData() メンバ関数を提供しており、アイテムに関連するデータをを取得できます。この関数を用いて、ドラッグ & ドロップ操作におけるデータ転送に必要なデータを取得することができます。

以下の例は、itemData() メンバ関数を使用して、アイテムのテキストを MIME データとして生成する方法を示しています。

QMimeData *MyWidget::mimeData() const
{
    QList<QTreeWidgetItem *> selectedItems = selectionModel()->selectedItems();
    if (selectedItems.isEmpty()) {
        return nullptr;
    }

    QMimeData *mimeData = new QMimeData;
    QStringList textList;
    for (QTreeWidgetItem *item : selectedItems) {
        QVariant data = model()->itemData(item->index(), Qt::DisplayRole);
        if (data.canConvert<QString>()) {
            textList << data.toString();
        }
    }
    mimeData->setTextList(textList);
    return mimeData;
}
  • QAbstractItemModel::itemData() を使用する場合は、アイテムに関連するデータが取得できることを確認する必要があります。
  • シグナルスロット接続を使用する場合は、適切なシグナルを選択する必要があります。
  • QTreeWidget::mimeData() は保護されたメンバー関数であるため、直接呼び出すことはできません。代わりに、上記の代替方法を使用する必要があります。