ドロップサイトの例
この例では、ドラッグ&ドロップ操作で利用可能なさまざまな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
に画像が含まれている場合、setPixmap() でDropArea
に表示します。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のリストが含まれている場合、空白で区切りながら、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
が適切なデータを含むようにカスタマイズされたら、setItem ()を使って、format
とtext
の両方をformatsTable
に挿入する。最後に、formatsTable
の最初の列に対してresizeColumnToContents() を呼び出します。
main()関数
main()
関数内で、DropSiteWindow
をインスタンス化し、show() 関数を呼び出す。
int main(int argc, char *argv[]) { QApplication app(argc, argv); DropSiteWindow window; window.show(); return app.exec(); }
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。