放置点示例
该示例展示了如何在拖放操作中区分可用的各种MIME格式。
放置点示例能够接受来自其他应用的拖放,并显示拖放对象提供的MIME格式。
本例中有两个类,DropArea
和 DropSiteWindow
,以及一个 main()
函数。在 DropSiteWindow
中实例化一个 DropArea
对象;然后,在 main()
函数中调用 DropSiteWindow
对象。
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
包含了四个 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
构造函数中,我们将最小尺寸设置为 200x200 像素,框架样式设置为 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()
函数。
当拖动正在进行且鼠标进入 DropArea
对象时,将调用 dragEnterEvent() 事件处理程序。对于 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,我们只通过调用 acceptProposedAction() 接受提议的 QDragMoveEvent 对象event。
void DropArea::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); }
DropArea
类对 dropEvent() 的实现提取事件的 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
包含其他类型的对象,我们使用setText
()将DropArea
的文本设置为"无法显示数据",以通知用户。
然后我们将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
,以及两个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
设置。列数设置为两列,该表不可编辑。同时,formatTable
的水平标题已格式化,以确保第二列扩展以占据额外空间。
formatsTable = new QTableWidget; formatsTable->setColumnCount(2); formatsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); formatsTable->setHorizontalHeaderLabels({tr("Format"), tr("Content")}); formatsTable->horizontalHeader()->setStretchLastSection(true);
实例化了三个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);
clicked() 信号用于 copyButton
、clearButton
和 quitButton
,分别连接到 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() 函数返回一个 QStringList 对象,包含 mimeData
支持的所有格式。
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
的内容进行了定制。我们在 text
上调用 QString 的 simplified() 函数,以获取一个前后和字间没有额外空格的字符串。
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
包含一个图像,我们通过将文本转换为十六进制来显示数据。
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()
函数中,我们实例化 DropSiteWindow
并调用它的 show() 函数。
int main(int argc, char *argv[]) { QApplication app(argc, argv); DropSiteWindow window; window.show(); return app.exec(); }
© 2024 The Qt Company Ltd. 本文件包含的文档贡献归相应所有者所有。本文件提供的文档在自由软件基金会的 GNU 自由文档许可版本 1.3 条件下提供。Qt及其相关标志是 The Qt Company Ltd. 在芬兰以及全球其他国家的商标。所有其他商标属于其各自所有者。