Auf dieser Seite

Beispiel für eine Ablagefläche

Das Beispiel zeigt, wie die verschiedenen MIME-Formate bei einem Drag-and-Drop-Vorgang unterschieden werden können.

Screenshot des Beispiels „Drop Site“

Das Beispiel „Drop Site“ akzeptiert Drag-and-Drop-Vorgänge aus anderen Anwendungen und zeigt die vom gezogenen Objekt bereitgestellten MIME-Formate an.

In diesem Beispiel gibt es zwei Klassen, „ DropArea “ und „ DropSiteWindow “, sowie eine Funktion „ main() “. Ein „ DropArea “-Objekt wird in „ DropSiteWindow “ instanziiert; ein „ DropSiteWindow “-Objekt wird anschließend in der Funktion „ main() “ aufgerufen.

Definition der Klasse „DropArea“

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 “ Neuimplementierungen von vier Ereignisbehandlungsroutinen von „ QWidget “:

  1. dragEnterEvent()
  2. dragMoveEvent()
  3. dragLeaveEvent()
  4. dropEvent()

Diese Ereignisbehandler 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 Klasse „DropArea“

Im Konstruktor von „ DropArea “ legen wir die Größe „ minimum size “ auf 200 × 200 Pixel fest, die „ frame style “ auf sowohl „ QFrame::Sunken “ als auch „ QFrame::StyledPanel “ und richten den Inhalt mittig 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. Anschließend aktivieren wir die Eigenschaft „ autoFillBackground “ und rufen die Funktion „ clear() “ auf.

Der Ereignisbehandler „ dragEnterEvent()“ wird aufgerufen, wenn ein Drag-Vorgang läuft und die Maus in das Objekt „ DropArea “ eintritt. Im Beispiel „ DropSite “ setzen wir, sobald die Maus in „ DropArea “ eintritt, dessen Text auf „<drop content>“ und heben den Hintergrund hervor.

void DropArea::dragEnterEvent(QDragEnterEvent *event)
{
    setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Highlight);

    event->acceptProposedAction();
    emit changed(event->mimeData());
}

Anschließend rufen wir ` acceptProposedAction()` auf ` event` auf und legen die Ablegeaktion auf die vorgeschlagene fest. Zuletzt senden wir das Signal ` changed() ` mit den abgelegten Daten und deren MIME-Typ-Informationen als Parameter.

Für ` dragMoveEvent()` nehmen wir einfach das vorgeschlagene ` QDragMoveEvent `-Objekt ` event` mit ` acceptProposedAction()` an.

void DropArea::dragMoveEvent(QDragMoveEvent *event)
{
    event->acceptProposedAction();
}

Die Implementierung von ` dropEvent()` in der Klasse ` DropArea ` extrahiert die MIME-Daten des ` event` und zeigt sie entsprechend an.

void DropArea::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();

Das mimeData -Objekt kann eines der folgenden Objekte enthalten: ein Bild, HTML-Text, Markdown-Text, Klartext oder eine Liste von URLs.

    if (mimeData->hasImage()) {
        setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));
    } else if (mimeData->hasColor()) {
        const auto color = mimeData->colorData().value<QColor>();
        setText(tr("Color: %1").arg(color.name()));
        setPalette(QPalette(color));
        setBackgroundRole(QPalette::Button);
    } 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, zeigen wir es in „ DropArea “ mit „ setPixmap()“ an.
  • Wenn „ mimeData “ HTML enthält, zeigen wir es mit „ setText()“ an und legen das Textformat von „ DropArea “ auf „ Qt::RichText “ fest.
  • Wenn mimeData Markdown enthält, zeigen wir es mit setText() an und legen das Textformat von DropArea als Qt::MarkdownText fest.
  • Wenn mimeData reinen Text enthält, zeigen wir ihn mit setText() an und legen das Textformat von DropArea als Qt::PlainText fest. Falls mimeData URLs enthält, durchlaufen wir die Liste der URLs, um sie in einzelnen Zeilen anzuzeigen.
  • Wenn „ mimeData “ andere Objekttypen enthält, setzen wir den Text von „ DropArea “ mithilfe von „ setText()“ auf „Daten können nicht angezeigt werden“, um den Benutzer darüber zu informieren.

Anschließend setzen wir den Text von „ backgroundRole “ in „ DropArea “ auf „ QPalette::Dark “ und akzeptieren die von „ event “ vorgeschlagene Aktion.

    if (!mimeData->hasColor()) {
        setPalette({});
        setBackgroundRole(QPalette::Dark);
    }
    event->acceptProposedAction();
}

Der Ereignis-Handler dragLeaveEvent() wird aufgerufen, wenn ein Drag-Vorgang im Gange ist 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 anschließend das vorgeschlagene Ereignis.

Die Funktion „ clear() “ setzt den Text in „ DropArea “ auf „<drop content>“ und die „ backgroundRole “ auf „ QPalette::Dark “. Zuletzt wird das Signal „ changed() “ ausgelöst.

void DropArea::clear()
{
    setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Dark);

    emit changed();
}

Definition der Klasse „DropSiteWindow“

Die Klasse „ DropSiteWindow “ enthält einen Konstruktor und einen öffentlichen Slot namens „ 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 “ sowie zwei „ QPushButton “-Objekte: „ clearButton “ und „ quitButton “.

Implementierung der Klasse „DropSiteWindow“

Im Konstruktor von ` DropSiteWindow` instanziieren wir ` abstractLabel ` und setzen dessen Eigenschaft ` wordWrap ` auf ` true`. Außerdem rufen wir 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();

Anschließend instanziieren wir ` dropArea ` und verbinden dessen Signal ` changed() ` mit dem Slot ` updateFormatsTable() ` von ` DropSiteWindow`.

    dropArea = new DropArea;
    connect(dropArea, &DropArea::changed,
            this, &DropSiteWindow::updateFormatsTable);

Nun richten wir das „ QTableWidget “-Objekt „ formatsTable “ ein. Seine horizontale Kopfzeile wird mithilfe eines „ QStringList “-Objekts („ labels “) festgelegt. Die Anzahl der Spalten wird auf zwei festgelegt, und die Tabelle ist nicht bearbeitbar. Außerdem wird die horizontale Kopfzeile von „ formatTable “ so formatiert, dass sich die zweite Spalte über den verfügbaren zusätzlichen Platz erstreckt.

    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 hier „ QDialogButtonBox “, 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 Signale „ clicked()“ für „ copyButton “, „ clearButton “ und „ quitButton “ werden jeweils mit „ copy() “, „ clear() “ und „ close()“ verbunden.

Für das Layout verwenden wir ein „ QVBoxLayout “ ( mainLayout), um unsere Widgets vertikal anzuordnen. Außerdem legen wir den Fenstertitel auf „Drop Site“ und die Mindestgröße auf 350 × 500 Pixel fest.

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(abstractLabel);
    mainLayout->addWidget(dropArea);
    mainLayout->addWidget(formatsTable);
    mainLayout->addWidget(buttonBox);

    setWindowTitle(tr("Drop Site"));
    resize(700, 500);
}

Wir wenden uns nun der Funktion „ updateFormatsTable() “ zu. Diese Funktion aktualisiert das „ formatsTable “ und zeigt die MIME-Formate des Objekts an, das auf das „ DropArea “-Objekt abgelegt wurde. Zunächst setzen wir die Eigenschaft „ rowCount “ von „ QTableWidget “ auf 0. Anschließend überprüfen wir, ob das übergebene „ QMimeData “-Objekt gültig 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, durchlaufen wir die unterstützten Formate.

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);

Innerhalb jeder Iteration erstellen wir ein ` QTableWidgetItem`, ` formatItem ` und setzen dessen ` flags ` auf ` Qt::ItemIsEnabled` sowie dessen ` 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 weder vor noch nach den Wörtern noch zwischen ihnen zusätzliche Leerzeichen 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, durchlaufen wir diese, wobei wir Leerzeichen als Trennzeichen verwenden. Enthält format hingegen ein Bild, zeigen wir die Daten an, indem wir den Text in Hexadezimalzahlen umwandeln.

        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
}

Sobald text so angepasst wurde, dass es die entsprechenden Daten enthält, fügen wir sowohl format als auch text mit setItem() in formatsTable ein. Zuletzt rufen wir resizeColumnToContents() für die erste Spalte von formatsTable auf.

Die Funktion `main()`

Innerhalb der Funktion ` main() ` instanziieren wir ` DropSiteWindow ` und rufen dessen Funktion ` show()` auf.

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    DropSiteWindow window;
    window.show();
    return app.exec();
}

Beispielprojekt @ code.qt.io

© 2026 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.