1 / 39

Rozdział 9. Drag and drop.

Rozdział 9. Drag and drop. Seminarium 2008. Informatyka Prowadzący dr Grzegorz Wójcik. Plan. Omówienie działania drag & drop’u Implementacja drag & drop’u „File reader” „Choose project” Drag & drop + niestandardowe obiekty Drag & drop + schowek. Zasada Drag & Dropu.

allayna
Télécharger la présentation

Rozdział 9. Drag and drop.

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Rozdział 9.Drag and drop. Seminarium 2008. Informatyka Prowadzący dr Grzegorz Wójcik

  2. Plan • Omówienie działania drag & drop’u • Implementacja drag & drop’u • „File reader” • „Choose project” • Drag & drop + niestandardowe obiekty • Drag & drop + schowek

  3. Zasada Drag & Dropu • Przeciągnięcie obiektu i upuszczenie go na Widget, bądź jego komponenty. • Źródło: • Komponent tej samej aplikacji • Zewnętrzna aplikacja

  4. File reader Aplikacja umożliwia przeciągnięcie listy URI (czyli najprościej mówiąc zaznaczonego pliku/ów) na QTextBox’a, co skutkuje wczytaniem pliku i odpowiednio ustawieniem tytułu Widgeta.

  5. class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); private: bool readFile(const QString &fileName); QTextEdit *textEdit; }; File reader Definicja głównego okna

  6. MainWindow::MainWindow() { textEdit = new QTextEdit; setCentralWidget(textEdit); textEdit->setAcceptDrops(false); setAcceptDrops(true); setWindowTitle(tr("Text Editor")); } File reader Konstruktor. Ustawienie TextBoxa w centrum. Ustawienie (nie)akceptowanych akcji.

  7. void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/uri-list")) event->acceptProposedAction(); } File reader dragEnterEvent. Sprawdzenie formatu przeciąganego obiektu. Pozwolenie na wykonanie akcji.

  8. void MainWindow::dropEvent(QDropEvent *event) { QList<QUrl> urls = event->mimeData()->urls(); if (urls.isEmpty()) return; QString fileName = urls.first().toLocalFile(); if (fileName.isEmpty()) return; if (readFile(fileName)) setWindowTitle(tr("%1 - %2").arg(fileName) .arg(tr("Drag File"))); } File reader dropEvent.

  9. Choose project Aplikacja umożliwia przeciągnięcie pracowników, aby pracowali przy odpowiednich projektach.

  10. class ProjectListWidget : public QListWidget { Q_OBJECT public: ProjectListWidget(QWidget *parent = 0); protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); private: void startDrag(); QPoint startPos; }; Choose project Definicja klasy

  11. ProjectListWidget::ProjectListWidget(QWidget *parent) : QListWidget(parent) { setAcceptDrops(true); } Choose project Konstruktor.

  12. void ProjectListWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) startPos = event->pos(); QListWidget::mousePressEvent(event); } Choose project Akcja wciśnięcia przycisku myszy na widget’ie.

  13. void ProjectListWidget::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if (distance >= QApplication::startDragDistance()) startDrag(); } QListWidget::mouseMoveEvent(event); } Choose project Akcja przesuwania myszy po widget’ie.

  14. void ProjectListWidget::startDrag() { QListWidgetItem *item = currentItem(); if (item) { QMimeData *mimeData = new QMimeData; mimeData->setText(item->text()); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(QPixmap(":/images/person.png")); if (drag->start(Qt::MoveAction) == Qt::MoveAction) delete item; } } Choose project Rozpoczęcie drag’a.

  15. void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event) { ProjectListWidget *source = qobject_cast<ProjectListWidget *>(event->source()); if (source && source != this) { event->setDropAction(Qt::MoveAction); event->accept(); } } Choose project Akcja rozpoczęcia drag’a na widget’ie.

  16. void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event) { ProjectListWidget *source = qobject_cast<ProjectListWidget *>(event->source()); if (source && source != this) { event->setDropAction(Qt::MoveAction); event->accept(); } } Choose project Akcja drag’a na widget’ie.

  17. void ProjectListWidget::dropEvent(QDropEvent *event) { ProjectListWidget *source = qobject_cast<ProjectListWidget *>(event->source()); if (source && source != this) { addItem(event->mimeData()->text()); event->setDropAction(Qt::MoveAction); event->accept(); } } Choose project Akcja drop’u na widget’ie.

  18. Drag & drop + niestandardowe obiekty Dlaczego? • QMimeData nie wystarcza • Typowe dane • Pliki • Zwykły tekst • Chcemy przeciągać niestandardowe dane

  19. Drag & drop + niestandardowe obiekty Jak to zrobić? • Możemy kodować nasz dane np. do QByteArray, a następnie używać QMimeData::setData() i QMimeData::data() • Możemy stworzyć podklase QMimeData i nadpisać formats() i retrieveData() • W przypadku akcji w obrębie jednej aplikacji, możemy stworzyć podklase QMimeData i trzymać dane w jakiejkolwiek strukturze

  20. QTableWidget Widget ma możliwość konwertowania przeciągania danych. W przypadku przeciągania danych zaznaczanych na widget’ie konwertuje je i wyświetla w odpowiednim formacie.

  21. void MyTableWidget::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if (distance >= QApplication::startDragDistance()) startDrag(); } QTableWidget::mouseMoveEvent(event); } QTableWidget – I wersja

  22. void MyTableWidget::startDrag() { QString plainText = selectionAsPlainText(); //analogicznie jak w Rozdziale 4. copy() if (plainText.isEmpty()) return; QMimeData *mimeData = new QMimeData; mimeData->setText(plainText); mimeData->setHtml(toHtml(plainText)); mimeData->setData("text/csv", toCsv(plainText).toUtf8()); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); if (drag->start(Qt::CopyAction | Qt::MoveAction) == Qt::MoveAction) deleteSelection(); } QTableWidget – I wersja

  23. QString MyTableWidget::toCsv(const QString &plainText) { QString result = plainText; result.replace("\\", "\\\\"); result.replace("\"", "\\\""); result.replace("\t", "\", \""); result.replace("\n", "\"\n\""); result.prepend("\""); result.append("\""); return result; } QTableWidget – I wersja

  24. QString MyTableWidget::toHtml(const QString &plainText) { QString result = Qt::escape(plainText); result.replace("\t", "<td>"); result.replace("\n", "\n<tr><td>"); result.prepend("<table>\n<tr><td>"); result.append("\n</table>"); return result; } QTableWidget – I wersja

  25. QTableWidget – I wersja RedGreenBlue //plainText CyanYellow Magenta "Red", "Green", "Blue„ //CSV "Cyan", "Yellow", "Magenta" <table> //HTML (prawie jak :-) <tr><td>Red<td>Green<td>Blue <tr><td>Cyan<td>Yellow<td>Magenta </table>

  26. void MyTableWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasFormat("text/csv")) { QByteArray csvData = event->mimeData()- >data("text/csv"); QString csvText = QString::fromUtf8(csvData); ... event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("text/plain")) { QString plainText = event->mimeData()->text(); ... event->acceptProposedAction(); } } QTableWidget – I wersja

  27. QTableWidget – I wersja Akceptujemy tylko 2 formaty. HTML – możemy przeciągnąć poza QTableWidget, ale na QTableWidget już nie przyjmujemy.

  28. QTableWidget – II wersja Potencjalnie szybsza. W I wersji kosztowna może być konwersja na QByteArray. W II tworzymy podklasę QMimeData.

  29. class TableMimeData : public QMimeData { Q_OBJECT public: TableMimeData(const QTableWidget *tableWidget, const QTableWidgetSelectionRange &range); const QTableWidget *tableWidget() const { return myTableWidget; } QTableWidgetSelectionRange range() const { return myRange; } QStringList formats() const; protected: QVariant retrieveData(const QString &format, QVariant::Type preferredType) const; private: static QString toHtml(const QString &plainText); static QString toCsv(const QString &plainText); QString text(int row, int column) const; QString rangeAsPlainText() const; const QTableWidget *myTableWidget; QTableWidgetSelectionRange myRange; QStringList myFormats; }; QTableWidget – II wersja

  30. QTableWidget – II wersja Przechowujemy wskaźnik do naszej tabeli oraz zakres, czyli zbiór komórek. Ponadto, jak wspomniano powyżej, musimy ponownie zaimplementować funkcje formats() i retrieveData().

  31. TableMimeData::TableMimeData(const QTableWidget *tableWidget, const QTableWidgetSelectionRange &range) { myTableWidget = tableWidget; myRange = range; myFormats << "text/csv" << "text/html" << "text/plain"; } QTableWidget – II wersja Przepisujemy i przypisujemy odpowiednie dane.

  32. QStringList TableMimeData::formats() const { return myFormats; } QTableWidget – II wersja

  33. QVariant TableMimeData::retrieveData(const QString &format, QVariant::Type preferredType) const { if (format == "text/plain") { return rangeAsPlainText(); } else if (format == "text/csv") { return toCsv(rangeAsPlainText()); } else if (format == "text/html") { return toHtml(rangeAsPlainText()); } else { return QMimeData::retrieveData(format, preferredType); } } QTableWidget – II wersja Zwracamy dane w odpowiednim formacie.

  34. void MyTableWidget::dropEvent(QDropEvent *event) { const TableMimeData *tableData = qobject_cast<const TableMimeData *>(event->mimeData()); if (tableData) { const QTableWidget *otherTable = tableData->tableWidget(); QTableWidgetSelectionRange otherRange = tableData->range(); ... event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("text/csv")) { QByteArray csvData = event->mimeData()->data("text/csv"); QString csvText = QString::fromUtf8(csvData); ... event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("text/plain")) { QString plainText = event->mimeData()->text(); ... event->acceptProposedAction(); } QTableWidget::mouseMoveEvent(event); } QTableWidget – II wersja

  35. Drag & drop + schowek • Znajdziemy pod QApplication::clipboard(). • QClipboard posiada metody: • setPixmap(), pixmap() • setText(), text() • setImage(), image() • QTextEdit posiada metody: • cut() • copy() • paste()

  36. Drag & drop + schowek Czasem nie wystarcza nam zwykły schowek, gdy np. mamy dane nie będące tekstem, ani obrazem. Problem rozwiązujemy podobnie jak przed kilkoma slajdami. Tworzymy podklasę QClipboard i implementujemy odpowiednie metody, np. setMimedata(), mimedata()

  37. Drag & drop + schowek • Selection • Supportowane tylko na X11 • Aby uzyskać dostęp do zaznaczonego tekstu należy: • sprawdzić czy Selection jest supportowane • przekazać w parametrze QClipboard::Selection

  38. void MyTextEditor::mouseReleaseEvent(QMouseEvent *event) { QClipboard *clipboard = QApplication::clipboard(); if (event->button() == Qt::MidButton && clipboard->supportsSelection()) { QString text = clipboard->text(QClipboard::Selection); pasteText(text); } } Drag & drop + schowek

  39. Rozdział 9. Drag and drop. Dziękuje

More Related