范例展示如何区分可用于拖放操作中的各种 MIME (多用途 Internet 邮件扩展) 格式。
The Drop Site example accepts drops from other applications, and displays the MIME formats provided by the drag object.
There are two classes,
DropArea
and
DropSiteWindow
,和
main()
function in this example. A
DropArea
object is instantiated in
DropSiteWindow
; a
DropSiteWindow
object is then invoked in the
main()
函数。
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
also contains a private instance of
QLabel
and reimplementations of four
QWidget
事件处理程序:
These event handlers are further explained in the implementation of the
DropArea
类。
protected: void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; void dragLeaveEvent(QDragLeaveEvent *event) override; void dropEvent(QDropEvent *event) override; private: QLabel *label; };
在
DropArea
构造函数,设置
最小大小
为 200x200 像素,
框架样式
to both
QFrame::Sunken
and
QFrame::StyledPanel
, and we align its contents to the center.
DropArea::DropArea(QWidget *parent) : QLabel(parent) { setMinimumSize(200, 200); setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); setAlignment(Qt::AlignCenter); setAcceptDrops(true); setAutoFillBackground(true); clear(); }
Also, we enable drop events in
DropArea
by setting the
acceptDrops
特性到
true
. Then, we enable the
autoFillBackground
property and invoke the
clear()
函数。
dragEnterEvent()
event handler is called when a drag is in progress and the mouse enters the
DropArea
对象。对于
DropSite
example, when the mouse enters
DropArea
, we set its text to "<drop content>" and highlight its background.
void DropArea::dragEnterEvent(QDragEnterEvent *event) { setText(tr("<drop content>")); setBackgroundRole(QPalette::Highlight); event->acceptProposedAction(); emit changed(event->mimeData()); }
Then, we invoke
acceptProposedAction()
on
event
, setting the drop action to the one proposed. Lastly, we emit the
changed()
signal, with the data that was dropped and its MIME type information as a parameter.
For dragMoveEvent() , we just accept the proposed QDragMoveEvent 对象, event ,采用 acceptProposedAction() .
void DropArea::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); }
DropArea
class's implementation of
dropEvent()
提取
event
's mime data and displays it accordingly.
void DropArea::dropEvent(QDropEvent *event) { const QMimeData *mimeData = event->mimeData();
mimeData
object can contain one of the following objects: an image, HTML text, Markdown text, plain text, or a list of URLs.
if (mimeData->hasImage()) { setPixmap(qvariant_cast<QPixmap>(mimeData->imageData())); } else if (mimeData->hasFormat(QLatin1String("text/markdown"))) { setText(QString::fromUtf8(mimeData->data(QLatin1String("text/markdown")))); 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 (int i = 0; i < urlList.size() && i < 32; ++i) text += urlList.at(i).path() + QLatin1Char('\n'); setText(text); } else { setText(tr("Cannot display data")); }
mimeData
包含图像,显示它在
DropArea
with
setPixmap()
.
mimeData
包含 HTML,显示它采用
setText()
并设置
DropArea
的文本格式为
Qt::RichText
.
mimeData
contains Markdown, we display it with
setText()
并设置
DropArea
的文本格式为
Qt::MarkdownText
.
mimeData
包含纯文本,显示它采用
setText()
并设置
DropArea
的文本格式为
Qt::PlainText
. In the event that
mimeData
contains URLs, we iterate through the list of URLs to display them on individual lines.
mimeData
contains other types of objects, we set
DropArea
's text, with
setText()
to "Cannot display data" to inform the user.
We then set
DropArea
's
backgroundRole
to
QPalette::Dark
and we accept
event
's proposed action.
setBackgroundRole(QPalette::Dark); event->acceptProposedAction(); }
dragLeaveEvent() event handler is called when a drag is in progress and the mouse leaves the widget.
void DropArea::dragLeaveEvent(QDragLeaveEvent *event) { clear(); event->accept(); }
For
DropArea
's implementation, we clear invoke
clear()
and then accept the proposed event.
clear()
function sets the text in
DropArea
to "<drop content>" and sets the
backgroundRole
to
QPalette::Dark
. Lastly, it emits the
changed()
信号。
void DropArea::clear() { setText(tr("<drop content>")); setBackgroundRole(QPalette::Dark); emit changed(); }
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; };
The class also contains a private instance of
DropArea
,
dropArea
,
QLabel
,
abstractLabel
,
QTableWidget
,
formatsTable
,
QDialogButtonBox
,
buttonBox
, and two
QPushButton
对象,
clearButton
and
quitButton
.
In the constructor of
DropSiteWindow
, we instantiate
abstractLabel
and set its
wordWrap
特性到
true
. We also call the
adjustSize()
function to adjust
abstractLabel
's size according to its contents.
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();
Then we instantiate
dropArea
和连接它的
changed()
signal to
DropSiteWindow
's
updateFormatsTable()
槽。
dropArea = new DropArea; connect(dropArea, &DropArea::changed, this, &DropSiteWindow::updateFormatsTable);
现在设置
QTableWidget
对象,
formatsTable
. Its horizontal header is set using a
QStringList
对象,
labels
. The number of columms are set to two and the table is not editable. Also, the
formatTable
's horizontal header is formatted to ensure that its second column stretches to occupy additional space available.
QStringList labels; labels << tr("Format") << tr("Content"); formatsTable = new QTableWidget; formatsTable->setColumnCount(2); formatsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); formatsTable->setHorizontalHeaderLabels(labels); formatsTable->horizontalHeader()->setStretchLastSection(true);
Three
QPushButton
对象,
clearButton
,
copyButton
,和
quitButton
, are instantiated and added to
buttonBox
- a
QDialogButtonBox
object. We use
QDialogButtonBox
here to ensure that the push buttons are presented in a layout that conforms to the platform's style.
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()
and
close()
,分别。
For the layout, we use a
QVBoxLayout
,
mainLayout
, to arrange our widgets vertically. We also set the window title to "Drop Site" and the minimum size to 350x500 pixels.
QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(abstractLabel); mainLayout->addWidget(dropArea); mainLayout->addWidget(formatsTable); mainLayout->addWidget(buttonBox); setWindowTitle(tr("Drop Site")); setMinimumSize(350, 500); }
We move on to the
updateFormatsTable()
function. This function updates the
formatsTable
, displaying the MIME formats of the object dropped onto the
DropArea
object. First, we set
QTableWidget
's
rowCount
property to 0. Then, we validate to ensure that the
QMimeData
object passed in is a valid object.
void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData) { formatsTable->setRowCount(0); copyButton->setEnabled(false); if (!mimeData) return;
Once we are sure that
mimeData
is valid, we iterate through its supported formats.
注意:
formats()
function returns a
QStringList
object, containing all the formats supported by the
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);
Within each iteration, we create a
QTableWidgetItem
,
formatItem
and we set its
flags
to
Qt::ItemIsEnabled
, and its
文本对齐
to
Qt::AlignTop
and
Qt::AlignLeft
.
A
QString
对象,
text
, is customized to display data according to the contents of
format
. We invoke
QString
's
simplified()
function on
text
, to obtain a string that has no additional space before, after or in between words.
QString text; if (format == QLatin1String("text/plain")) { text = mimeData->text().simplified(); } else if (format == QLatin1String("text/markdown")) { text = QString::fromUtf8(mimeData->data(QLatin1String("text/markdown"))); } else if (format == QLatin1String("text/html")) { text = mimeData->html().simplified(); } else if (format == QLatin1String("text/uri-list")) { QList<QUrl> urlList = mimeData->urls(); for (int i = 0; i < urlList.size() && i < 32; ++i) text.append(urlList.at(i).toString() + QLatin1Char(' ')); } else { QByteArray data = mimeData->data(format); for (int i = 0; i < data.size() && i < 32; ++i) text.append(QStringLiteral("%1 ").arg(uchar(data[i]), 2, 16, QLatin1Char('0')).toUpper()); }
若
format
contains a list of URLs, we iterate through them, using spaces to separate them. On the other hand, if
format
contains an image, we display the data by converting the text to hexadecimal.
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
has been customized to contain the appropriate data, we insert both
format
and
text
into
formatsTable
with
setItem()
. Lastly, we invoke
resizeColumnToContents()
on
formatsTable
's first column.
在
main()
函数,实例化
DropSiteWindow
并援引其
show()
函数。
int main(int argc, char *argv[]) { QApplication app(argc, argv); DropSiteWindow window; window.show(); return app.exec(); }