이 페이지에서

드롭 사이트 예시

이 예제는 드래그 앤 드롭 작업에서 사용할 수 있는 다양한 MIME 형식을 구별하는 방법을 보여줍니다.

‘드롭 사이트’ 예시의 스크린샷

이 드롭 사이트 예제는 다른 애플리케이션에서 드롭된 항목을 받아들이며, 드래그된 객체가 제공하는 MIME 형식을 표시합니다.

이 예제에는 두 개의 클래스( DropArea 및 DropSiteWindow)와 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 `에는 다음 네 가지 ` QWidget ` 이벤트 핸들러가 재구현되어 있습니다:

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

이러한 이벤트 핸들러에 대한 자세한 설명은 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()의 경우, acceptProposedAction()을 통해 제안된 QDragMoveEvent 객체인 event 를 그대로 받아들입니다.

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

DropArea 클래스의 dropEvent() 구현은 event 의 MIME 데이터를 추출하여 그에 따라 표시합니다.

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

mimeData 객체는 이미지, HTML 텍스트, 마크다운 텍스트, 일반 텍스트 또는 URL 목록 중 하나를 포함할 수 있습니다.

    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"));
    }
  • mimeData 에 이미지가 포함되어 있는 경우, DropArea 에서 setPixmap()을 사용하여 이를 표시합니다.
  • mimeData 에 HTML이 포함되어 있으면 setText()을 사용하여 표시하고, DropArea 의 텍스트 형식을 Qt::RichText 로 설정합니다.
  • mimeData 에 마크다운이 포함되어 있으면, setText()을 사용하여 표시하고 DropArea 의 텍스트 형식을 Qt::MarkdownText 로 설정합니다.
  • mimeData 에 일반 텍스트가 포함되어 있으면, setText()을 사용하여 이를 표시하고 DropArea 의 텍스트 형식을 Qt::PlainText 로 설정합니다. mimeData 에 URL이 포함되어 있는 경우, URL 목록을 순차적으로 처리하여 각 URL을 별도의 줄에 표시합니다.
  • mimeData 에 다른 유형의 객체가 포함된 경우, 사용자에게 알리기 위해 setText()을 사용하여 DropArea 의 텍스트를 "데이터를 표시할 수 없습니다"로 설정합니다.

그런 다음 DropArea 의 backgroundRole 을 QPalette::Dark 로 설정하고, event 가 제안한 동작을 수락합니다.

    if (!mimeData->hasColor()) {
        setPalette({});
        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 을 사용하여 설정됩니다. 열 수는 2개로 설정되며, 이 테이블은 편집이 불가능합니다. 또한, 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() 함수는 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 의 내용에 따라 데이터를 표시하도록 맞춤 설정되었습니다. 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 목록이 포함되어 있다면, 공백으로 구분하여 해당 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();
}

예제 프로젝트 @ 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.