Drop-Site-Beispiel
Das Beispiel zeigt, wie die verschiedenen MIME-Formate unterschieden werden können, die bei einem Drag&Drop-Vorgang verfügbar sind.
Das Drop-Site-Beispiel akzeptiert Ablegevorgänge aus anderen Anwendungen und zeigt die MIME-Formate an, die durch das Drag-Objekt bereitgestellt werden.
In diesem Beispiel gibt es zwei Klassen, DropArea
und DropSiteWindow
, und eine Funktion main()
. Ein DropArea
Objekt wird in DropSiteWindow
instanziiert; ein DropSiteWindow
Objekt wird dann in der Funktion main()
aufgerufen.
DropArea-Klassendefinition
Die Klasse DropArea
ist eine Unterklasse von QLabel mit einem öffentlichen Slot, clear()
, und einem Signal changed()
.
class DropArea : public QLabel { Q_OBJECT public: explicit DropArea(QWidget *parent = nullptr); public slots: void clear(); signals: void changed(const QMimeData *mimeData = nullptr);
Darüber hinaus enthält DropArea
Reimplementierungen von vier QWidget Event-Handlern:
Diese Ereignishandler werden in der Implementierung der Klasse DropArea
näher erläutert.
protected: void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; void dragLeaveEvent(QDragLeaveEvent *event) override; void dropEvent(QDropEvent *event) override; };
Implementierung der DropArea-Klasse
Im DropArea
-Konstruktor setzen wir minimum size auf 200x200 Pixel, frame style auf QFrame::Sunken und QFrame::StyledPanel und richten den Inhalt in der Mitte aus.
DropArea::DropArea(QWidget *parent) : QLabel(parent) { setMinimumSize(200, 200); setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); setAlignment(Qt::AlignCenter); setAcceptDrops(true); setAutoFillBackground(true); clear(); }
Außerdem aktivieren wir Drop-Ereignisse in DropArea
, indem wir die Eigenschaft acceptDrops auf true
setzen. Dann aktivieren wir die Eigenschaft autoFillBackground und rufen die Funktion clear()
auf.
Der Event-Handler dragEnterEvent() wird aufgerufen, wenn ein Ziehen im Gange ist und die Maus in das Objekt DropArea
eintritt. Für das Beispiel DropSite
setzen wir, wenn die Maus in DropArea
eintritt, den Text auf "<Inhalt ablegen>" und heben den Hintergrund hervor.
void DropArea::dragEnterEvent(QDragEnterEvent *event) { setText(tr("<drop content>")); setBackgroundRole(QPalette::Highlight); event->acceptProposedAction(); emit changed(event->mimeData()); }
Dann rufen wir acceptProposedAction() auf event auf und setzen die Drop-Aktion auf den vorgeschlagenen Wert. Zum Schluss wird das Signal changed()
mit den abgelegten Daten und den MIME-Typ-Informationen als Parameter ausgegeben.
Für dragMoveEvent() akzeptieren wir einfach das vorgeschlagene QDragMoveEvent Objekt, event, mit acceptProposedAction().
void DropArea::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); }
Die Implementierung von dropEvent() in der Klasse DropArea
extrahiert die MIME-Daten von event und zeigt sie entsprechend an.
void DropArea::dropEvent(QDropEvent *event) { const QMimeData *mimeData = event->mimeData();
Das Objekt mimeData
kann eines der folgenden Objekte enthalten: ein Bild, HTML-Text, Markdown-Text, reinen Text oder eine Liste von URLs.
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")); }
- Wenn
mimeData
ein Bild enthält, wird es inDropArea
mit setPixmap() angezeigt. - Wenn
mimeData
HTML enthält, wird es mit setText() angezeigt und das Textformat vonDropArea
wird auf Qt::RichText gesetzt. - Wenn
mimeData
Markdown enthält, wird es mit setText() angezeigt, und das Textformat vonDropArea
wird auf Qt::MarkdownText gesetzt. - Wenn
mimeData
reinen Text enthält, wird er mit setText() angezeigt und das Textformat vonDropArea
wird auf Qt::PlainText gesetzt. FallsmimeData
URLs enthält, wird die Liste der URLs durchlaufen, um sie in einzelnen Zeilen anzuzeigen. - Wenn
mimeData
andere Arten von Objekten enthält, setzen wir den Text vonDropArea
mit setText() auf "Cannot display data", um den Benutzer zu informieren.
Wir setzen dann DropArea
's backgroundRole auf QPalette::Dark und akzeptieren event
's vorgeschlagene Aktion.
setBackgroundRole(QPalette::Dark); event->acceptProposedAction(); }
Der dragLeaveEvent()-Ereignishandler wird aufgerufen, wenn ein Ziehen stattfindet und die Maus das Widget verlässt.
void DropArea::dragLeaveEvent(QDragLeaveEvent *event) { clear(); event->accept(); }
Für die Implementierung von DropArea
rufen wir clear()
auf und akzeptieren dann das vorgeschlagene Ereignis.
Die Funktion clear()
setzt den Text in DropArea
auf "<Inhalt ablegen>" und setzt backgroundRole auf QPalette::Dark. Schließlich gibt sie das Signal changed()
aus.
void DropArea::clear() { setText(tr("<drop content>")); setBackgroundRole(QPalette::Dark); emit changed(); }
Definition der DropSiteWindow-Klasse
Die Klasse DropSiteWindow
enthält einen Konstruktor und einen öffentlichen Slot, 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; };
Die Klasse enthält außerdem eine private Instanz von DropArea
, dropArea
, QLabel, abstractLabel
, QTableWidget, formatsTable
, QDialogButtonBox, buttonBox
und zwei QPushButton Objekte, clearButton
und quitButton
.
Implementierung der DropSiteWindow-Klasse
Im Konstruktor von DropSiteWindow
instanziieren wir abstractLabel
und setzen die Eigenschaft wordWrap auf true
. Wir rufen auch die Funktion adjustSize() auf, um die Größe von abstractLabel
entsprechend seinem Inhalt anzupassen.
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();
Dann instanziieren wir dropArea
und verbinden sein changed()
-Signal mit dem updateFormatsTable()
-Slot von DropSiteWindow
.
dropArea = new DropArea; connect(dropArea, &DropArea::changed, this, &DropSiteWindow::updateFormatsTable);
Wir richten nun das Objekt QTableWidget ein, formatsTable
. Seine horizontale Kopfzeile wird über ein QStringList Objekt, labels
, festgelegt. Die Anzahl der Spalten wird auf zwei festgelegt und die Tabelle ist nicht editierbar. Außerdem wird die horizontale Kopfzeile von formatTable
so formatiert, dass sich die zweite Spalte ausdehnt, um den zusätzlich verfügbaren Platz zu belegen.
formatsTable = new QTableWidget; formatsTable->setColumnCount(2); formatsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); formatsTable->setHorizontalHeaderLabels({tr("Format"), tr("Content")}); formatsTable->horizontalHeader()->setStretchLastSection(true);
Drei QPushButton Objekte, clearButton
, copyButton
und quitButton
, werden instanziiert und zu buttonBox
- einem QDialogButtonBox Objekt - hinzugefügt. Wir verwenden QDialogButtonBox hier, um sicherzustellen, dass die Drucktasten in einem Layout dargestellt werden, das dem Stil der Plattform entspricht.
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);
Die clicked()-Signale für copyButton
, clearButton
und quitButton
werden mit copy()
, clear()
bzw. close() verbunden.
Für das Layout verwenden wir ein QVBoxLayout, mainLayout
, um unsere Widgets vertikal anzuordnen. Außerdem setzen wir den Fenstertitel auf "Drop Site" und die Mindestgröße auf 350x500 Pixel.
QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(abstractLabel); mainLayout->addWidget(dropArea); mainLayout->addWidget(formatsTable); mainLayout->addWidget(buttonBox); setWindowTitle(tr("Drop Site")); resize(700, 500); }
Weiter geht es mit der Funktion updateFormatsTable()
. Diese Funktion aktualisiert formatsTable
und zeigt die MIME-Formate des Objekts an, das auf das Objekt DropArea
abgelegt wurde. Zuerst setzen wir die Eigenschaft rowCount von QTableWidget auf 0. Dann überprüfen wir, ob das übergebene Objekt QMimeData ein gültiges Objekt ist.
void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData) { formatsTable->setRowCount(0); copyButton->setEnabled(false); if (!mimeData) return;
Sobald wir sicher sind, dass mimeData
gültig ist, gehen wir die unterstützten Formate durch.
Hinweis: Die Funktion formats() gibt ein QStringList Objekt zurück, das alle von mimeData
unterstützten Formate enthält.
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);
In jeder Iteration erstellen wir ein QTableWidgetItem, formatItem
und setzen sein flags auf Qt::ItemIsEnabled und sein text alignment auf Qt::AlignTop und Qt::AlignLeft.
Ein QString -Objekt, text
, wird so angepasst, dass es Daten entsprechend dem Inhalt von format
anzeigt. Wir rufen die Funktion simplified() von QString auf text
auf, um eine Zeichenkette zu erhalten, die keine zusätzlichen Leerzeichen vor, nach oder zwischen den Wörtern enthält.
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(); }
Wenn format
eine Liste von URLs enthält, werden diese durchlaufen und durch Leerzeichen getrennt. Enthält format
dagegen ein Bild, werden die Daten durch Konvertierung des Textes in Hexadezimalzahlen angezeigt.
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 }
Nachdem text
so angepasst wurde, dass es die entsprechenden Daten enthält, fügen wir sowohl format
als auch text
mit setItem() in formatsTable
ein. Schließlich rufen wir resizeColumnToContents() für die erste Spalte von formatsTable
auf.
Die Funktion main()
Innerhalb der Funktion main()
instanziieren wir DropSiteWindow
und rufen die Funktion show() auf.
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.