Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

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

Podobne prezentacje


Prezentacja na temat: "Rozdział 9. Drag and drop. Seminarium 2008. Informatyka Prowadzący dr Grzegorz Wójcik."— Zapis prezentacji:

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

2 Plan Omówienie działania drag & dropu Implementacja drag & dropu 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 QTextBoxa, co skutkuje wczytaniem pliku i odpowiednio ustawieniem tytułu Widgeta.

5 File reader Definicja głównego okna 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; };

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

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

8 File reader dropEvent. void MainWindow::dropEvent(QDropEvent *event) { QList 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"))); }

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

10 Choose project Definicja klasy 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; };

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

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

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

14 Choose project Rozpoczęcie draga. 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; }

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

16 Choose project Akcja draga na widgetie. void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event) { ProjectListWidget *source = qobject_cast (event->source()); if (source && source != this) { event->setDropAction(Qt::MoveAction); event->accept(); }

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

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 widgetie konwertuje je i wyświetla w odpowiednim formacie.

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

22 QTableWidget – I wersja 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(); }

23 QTableWidget – I wersja 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; }

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

25 QTableWidget – I wersja RedGreenBlue//plainText CyanYellow Magenta "Red", "Green", "Blue//CSV "Cyan", "Yellow", "Magenta" //HTML (prawie jak :-) Red Green Blue Cyan Yellow Magenta

26 QTableWidget – I wersja 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(); }

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 QTableWidget – II wersja 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; };

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

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

33 QTableWidget – II wersja 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); } Zwracamy dane w odpowiednim formacie.

34 QTableWidget – II wersja void MyTableWidget::dropEvent(QDropEvent *event) { const TableMimeData *tableData = qobject_cast (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); }

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

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


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

Podobne prezentacje


Reklamy Google