ドロップサイトの例
この例では、ドラッグ&ドロップ操作で利用可能なさまざまなMIMEフォーマットを区別する方法を示します。
ドロップ・サイトの例では、他のアプリケーションからのドロップを受け付け、ドラッグ・オブジェクトが提供するMIMEフォーマットを表示します。
この例では、DropArea
とDropSiteWindow
の2つのクラスと、main()
関数があります。DropArea
オブジェクトがDropSiteWindow
でインスタンス化され、DropSiteWindow
オブジェクトがmain()
関数で呼び出されます。
DropAreaクラスの定義
DropArea
クラスはQLabel のサブクラスで、パブリック・スロットclear()
とchanged()
シグナルを持ちます。
class DropArea : public QLabel { Q_OBJECT public: explicit DropArea(QWidget *parent = nullptr); public slots: void clear(); signals: void changed(const QMimeData *mimeData = nullptr);
さらに、DropArea
には、4つのQWidget イベント・ハンドラの再実装が含まれています:
これらのイベント・ハンドラについては、DropArea
クラスの実装で詳しく説明します。
protected: void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; void dragLeaveEvent(QDragLeaveEvent *event) override; void dropEvent(QDropEvent *event) override; };
DropAreaクラスの実装
DropArea
コンストラクタでは、minimum size を 200x200 ピクセルに設定し、frame style をQFrame::Sunken とQFrame::StyledPanel の両方に設定し、その内容を中央に揃えます。
DropArea::DropArea(QWidget *parent) : QLabel(parent) { setMinimumSize(200, 200); setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); setAlignment(Qt::AlignCenter); setAcceptDrops(true); setAutoFillBackground(true); clear(); }
また、acceptDrops プロパティをtrue
に設定することで、DropArea
のドロップ・イベントを有効にします。次に、autoFillBackground プロパティを有効にし、clear()
関数を呼び出します。
dragEnterEvent() イベント・ハンドラは、ドラッグが進行中で、マウスがDropArea
オブジェクトに入ると呼び出されます。DropSite
の例では、マウスがDropArea
に入ると、そのテキストを "<drop content>" に設定し、その背景をハイライトします。
void DropArea::dragEnterEvent(QDragEnterEvent *event) { setText(tr("<drop content>")); setBackgroundRole(QPalette::Highlight); event->acceptProposedAction(); emit changed(event->mimeData()); }
次に、event でacceptProposedAction() を呼び出し、ドロップ・アクションを提案されたものに設定します。最後に、ドロップされたデータとそのMIMEタイプ情報をパラメータとして、changed()
シグナルを発信する。
dragMoveEvent()については、提案されたQDragMoveEvent オブジェクト、event をacceptProposedAction()で受け入れるだけである。
void DropArea::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); }
DropArea
クラスの実装であるdropEvent() は、event の MIME データを抽出し、それに応じて表示する。
void DropArea::dropEvent(QDropEvent *event) { const QMimeData *mimeData = event->mimeData();
mimeData
オブジェクトには、画像、HTMLテキスト、Markdownテキスト、プレーン・テキスト、URLリストのいずれかを含めることができます。
if (mimeData->hasImage()) { setPixmap(qvariant_cast<QPixmap>(mimeData->imageData())); } else if (mimeData->hasFormat(u"text/markdown"_s)) { setText(QString::fromUtf8(mimeData->data(u"text/markdown"_s))); setTextFormat(Qt::MarkdownText); } else if (mimeData->hasHtml()) { setText(mimeData->html()); setTextFormat(Qt::RichText); } else if (mimeData->hasText()) { setText(mimeData->text()); setTextFormat(Qt::PlainText); } else if (mimeData->hasUrls()) { QList<QUrl> urlList = mimeData->urls(); QString text; for (qsizetype i = 0, count = qMin(urlList.size(), qsizetype(32)); i < count; ++i) text += urlList.at(i).path() + u'\n'; setText(text); } else { setText(tr("Cannot display data")); }
mimeData
に画像が含まれている場合、DropArea
にsetPixmap() で表示します。mimeData
にHTMLが含まれている場合は、setText() で表示し、DropArea
のテキスト・フォーマットをQt::RichText に設定する。mimeData
にMarkdownが含まれている場合は、setText() で表示し、DropArea
のテキスト・フォーマットをQt::MarkdownText とします。mimeData
にプレーン・テキストが含まれている場合、setText() で表示し、DropArea
のテキスト・フォーマットをQt::PlainText に設定します。mimeData
に URL が含まれている場合は、URL のリストを繰り返し、個々の行に表示する。mimeData
に他の種類のオブジェクトが含まれている場合、DropArea
のテキストを、setText() を "Cannot display data" に設定して、ユーザーに通知する。
次に、DropArea
'のbackgroundRole をQPalette::Dark に設定し、event
'のアクション案を受け入れる。
setBackgroundRole(QPalette::Dark); event->acceptProposedAction(); }
dragLeaveEvent() イベント・ハンドラは、ドラッグ中にマウスがウィジェットから離れると呼び出される。
void DropArea::dragLeaveEvent(QDragLeaveEvent *event) { clear(); event->accept(); }
DropArea
'の実装では、clear()
をクリアしてから、提案されたイベントを受け入れます。
clear()
関数は、DropArea
のテキストを "<drop content>" に設定し、backgroundRole をQPalette::Dark に設定します。最後に、changed()
シグナルを発信します。
void DropArea::clear() { setText(tr("<drop content>")); setBackgroundRole(QPalette::Dark); emit changed(); }
DropSiteWindowクラスの定義
DropSiteWindow
クラスはコンストラクタとパブリック スロットupdateFormatsTable()
を含んでいます。
class DropSiteWindow : public QWidget { Q_OBJECT public: DropSiteWindow(); public slots: void updateFormatsTable(const QMimeData *mimeData); void copy(); private: DropArea *dropArea; QLabel *abstractLabel; QTableWidget *formatsTable; QPushButton *clearButton; QPushButton *copyButton; QPushButton *quitButton; QDialogButtonBox *buttonBox; };
また、DropArea
、dropArea
、QLabel 、abstractLabel
、QTableWidget 、formatsTable
、QDialogButtonBox 、buttonBox
、2つのQPushButton オブジェクト、clearButton
、quitButton
のプライベート・インスタンスも含まれています。
DropSiteWindowクラスの実装
DropSiteWindow
のコンストラクタでは、abstractLabel
をインスタンス化し、そのwordWrap プロパティをtrue
に設定します。また、adjustSize() 関数を呼び出して、abstractLabel
のサイズをその内容に応じて調整します。
DropSiteWindow::DropSiteWindow() { abstractLabel = new QLabel(tr("This example accepts drags from other " "applications and displays the MIME types " "provided by the drag object.")); abstractLabel->setWordWrap(true); abstractLabel->adjustSize();
次に、dropArea
をインスタンス化し、そのchanged()
シグナルをDropSiteWindow
のupdateFormatsTable()
スロットに接続する。
dropArea = new DropArea; connect(dropArea, &DropArea::changed, this, &DropSiteWindow::updateFormatsTable);
次に、QTableWidget オブジェクト、formatsTable
をセットアップします。水平ヘッダーはQStringList オブジェクトlabels
を使って設定します。列の数は2つに設定され、表は編集できない。また、formatTable
の水平ヘッダーは、2列目が伸びるようにフォーマットされ、追加のスペースが確保されます。
formatsTable = new QTableWidget; formatsTable->setColumnCount(2); formatsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); formatsTable->setHorizontalHeaderLabels({tr("Format"), tr("Content")}); formatsTable->horizontalHeader()->setStretchLastSection(true);
3つのQPushButton オブジェクト、clearButton
、copyButton
、quitButton
がインスタンス化され、buttonBox
-QDialogButtonBox オブジェクトに追加される。ここでは、QDialogButtonBox を使用して、プッシュボタンがプラットフォームのスタイルに適合したレイアウトで表示されるようにしている。
clearButton = new QPushButton(tr("Clear")); copyButton = new QPushButton(tr("Copy")); quitButton = new QPushButton(tr("Quit")); buttonBox = new QDialogButtonBox; buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole); buttonBox->addButton(copyButton, QDialogButtonBox::ActionRole); #if !QT_CONFIG(clipboard) copyButton->setVisible(false); #endif buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); connect(clearButton, &QAbstractButton::clicked, dropArea, &DropArea::clear); connect(copyButton, &QAbstractButton::clicked, this, &DropSiteWindow::copy);
copyButton
、clearButton
、quitButton
のclicked() シグナルは、それぞれcopy()
、clear()
、close() に接続されている。
レイアウトには、QVBoxLayout 、mainLayout
を使い、ウィジェットを縦に並べる。また、ウィンドウのタイトルを "Drop Site "に設定し、最小サイズを350x500ピクセルに設定します。
QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(abstractLabel); mainLayout->addWidget(dropArea); mainLayout->addWidget(formatsTable); mainLayout->addWidget(buttonBox); setWindowTitle(tr("Drop Site")); resize(700, 500); }
次に、updateFormatsTable()
関数に進みます。この関数は、formatsTable
を更新し、DropArea
にドロップされたオブジェクトの MIME フォーマットを表示します。まず、QTableWidget のrowCount プロパティを 0 に設定します。次に、渡されたQMimeData オブジェクトが有効なオブジェクトであることを確認します。
void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData) { formatsTable->setRowCount(0); copyButton->setEnabled(false); if (!mimeData) return;
mimeData
が有効であることを確認したら、サポートされている形式を繰り返します。
注: formats ()関数は、mimeData
がサポートするすべてのフォーマットを含むQStringList オブジェクトを返します。
const QStringList formats = mimeData->formats(); for (const QString &format : formats) { QTableWidgetItem *formatItem = new QTableWidgetItem(format); formatItem->setFlags(Qt::ItemIsEnabled); formatItem->setTextAlignment(Qt::AlignTop | Qt::AlignLeft);
各反復の中で、QTableWidgetItem 、formatItem
を作成し、flags をQt::ItemIsEnabled に、text alignment をQt::AlignTop とQt::AlignLeft に設定する。
QString オブジェクト、text
は、format
の内容に従ってデータを表示するようにカスタマイズされる。QString'のsimplified ()関数をtext
に呼び出して、単語の前後や間にスペースが追加されていない文字列を取得する。
QString text; if (format == u"text/plain") { text = mimeData->text().simplified(); } else if (format == u"text/markdown") { text = QString::fromUtf8(mimeData->data(u"text/markdown"_s)); } else if (format == u"text/html") { text = mimeData->html().simplified(); } else if (format == u"text/uri-list") { QList<QUrl> urlList = mimeData->urls(); for (qsizetype i = 0, count = qMin(urlList.size(), qsizetype(32)); i < count; ++i) text.append(urlList.at(i).toString() + u' '); } else { QByteArray data = mimeData->data(format); if (data.size() > 32) data.truncate(32); text = QString::fromLatin1(data.toHex(' ')).toUpper(); }
format
にURLのリストが含まれている場合は、空白で区切って繰り返し表示する。一方、format
に画像が含まれている場合は、テキストを16進数に変換してデータを表示する。
int row = formatsTable->rowCount(); formatsTable->insertRow(row); formatsTable->setItem(row, 0, new QTableWidgetItem(format)); formatsTable->setItem(row, 1, new QTableWidgetItem(text)); } formatsTable->resizeColumnToContents(0); #if QT_CONFIG(clipboard) copyButton->setEnabled(formatsTable->rowCount() > 0); #endif }
text
が適切なデータを含むようにカスタマイズされたら、format
とtext
の両方をsetItem() でformatsTable
に挿入する。最後に、formatsTable
の最初の列に対してresizeColumnToContents() を呼び出します。
main()関数
main()
関数内で、DropSiteWindow
をインスタンス化し、show() 関数を呼び出す。
int main(int argc, char *argv[]) { QApplication app(argc, argv); DropSiteWindow window; window.show(); return app.exec(); }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.