Обеспечение поддержки технологии «drag-and-drop»
Обеспечение поддержки технологии «drag-and-drop»
Технология «drag-and-drop» состоит из двух действий: перетаскивание «захваченных» объектов и их «освобождение». Виджеты в Qt могут использоваться в качестве переносимых объектов, в качестве места отпускания этих объектов или в обоих качествах.
В нашем первом примере мы показываем, как приложение Qt принимает объект, перенесенный из другого приложения. Приложение Qt представляет собой главное окно, использующее текстовый редактор QTextEdit в качестве центрального виджета. Когда пользователь переносит текстовый файл с рабочего стола компьютера или из проводника файловой системы и оставляет его в окне этого приложения, оно загружает файл в QTextEdit.
Ниже приводится пример определения класса MainWindow:
01 class MainWindow : public QMainWindow
02 {
03 Q_OBJECT
04 public:
05 MainWindow();
06 protected:
07 void dragEnterEvent(QDragEnterEvent *event);
08 void dropEvent(QDropEvent *event);
09 private:
10 bool readFile(const QString &fileName);
11 QTextEdit *textEdit;
12 }
Класс MainWindow переопределяет функции dragEnterEvent() и dropEvent() класса QWidget. Поскольку целью примера является демонстрация механизма «drag-and-drop», большая часть функциональности класса главного окна здесь не рассматривается.
01 MainWindow::MainWindow()
02 {
03 textEdit = new QTextEdit;
04 setCentralWidget(textEdit);
05 textEdit->setAcceptDrops(false);
06 setAcceptDrops(true);
07 setWindowTitle(tr("Text Editor"));
08 }
В конструкторе мы создаем QTextEdit и назначаем его в качестве центрального виджета. По умолчанию QTextEdit принимает переносимые текстовые объекты из других приложений, и если пользователь отпускает на этом виджете файл, имя этого файла будет вставлено в текст. Поскольку события отпускания объектов передаются от дочерних виджетов к родительским, отключая возможность отпускать переносимый объектв области отображения QTextEdit и включая ее для главного окна, мы получаем события отпускания объектов в MainWindow для всего главного окна.
01 voidMainWindow::dragEnterEvent(QDragEnterEvent *event)
02 {
03 if (event->mimeData()->hasFormat("text/uri-list"))
04 event->acceptProposedAction();
05 }
Функция dragEnterEvent() вызывается всякий раз, когда пользователь переносит объект на какой-нибудь виджет. Если мы вызываем функцию acceptProposedAction() при обработке этого события, мы указываем, что пользователь может отпустить переносимый объект в данном виджете. По умолчанию виджет не смог бы принять переносимый объект. Qt автоматически изменяет форму курсора для уведомления пользователя о возможности или невозможности приема объекта виджетом.
Здесь мы хотим позволить пользователю переносить файлы, но не более того. Для этого мы проверяем MIME—тип переносимого объекта. MIME—тип text/uri-list используется для хранения списка универсальных идентификаторов ресурсов (URI — universal resource identifier), в качестве которых могут выступать имена файлов, адреса URL (например, адресные пути HTTP и FTP) или идентификаторы других глобальных ресурсов. Стандартные типы MIME определяются Агентством по выделению имен и уникальных параметров протоколов сети Интернет (Internet Assigned Numbers Authority — IANA). Они состоят из типа и подтипа, разделенных слешем. Типы MIME используются буфером обмена и механизмом «drag-and-drop» для идентификации различных типов данных. Официальный список MIME—типов доступен по адресу http://www.iana.org/assignments/media-types/.
01 void MainWindow::dropEvent(QDropEvent *event)
02 {
03 QList<QUrl> urls = event->mimeData()->urls();
04 if (urls.isEmpty())
05 return;
06 QString fileName = urls.first().toLocalFile();
07 if (fileName.isEmpty())
08 return;
09 if (readFile(fileName))
10 setWindowTitle(tr("%1 -%2").arg(fileName)
11 .arg(tr("Drag File")));
12 }
Функция dropEvent() вызывается, когда пользователь отпускает объект на виджете. Мы вызываем функцию QMimeData::urls() для получения списка адресов QUrl. Обычно пользователи переносят одновременно только один файл, но возможен также перенос сразу нескольких выделенных файлов. Если имеется несколько URL или полученный URL оказывается нелокальным, мы немедленно возвращаем управление.
QWidget содержит также функции dragMoveEvent() и dragLeaveEvent(), но для большинства приложений не потребуется их переопределять.
Второй пример показывает, как следует инициировать перетаскивание объекта и принимать его после отпускания. Мы создадим подкласс QListWidget, который будет поддерживать механизм «drag-and-drop» и входить в приложение Project Chooser (составитель проектов), показанное на рис. 9.1.
Рис. 9.1. Приложение Project Chooser.
Приложение Project Chooser предоставляет пользователю два виджета со списками имен людей. Каждый список представляет проект. Пользователь может с помощью механизма «drag-and-drop» перевести человека из одного проекта в другой.
Программный код по обеспечению механизма «drag-and-drop» находится в подклассе QListWidget. Ниже приводится определение класса:
01 class ProjectListWidget : public QListWidget
02 {
03 Q_OBJECT
04 public:
05 ProjectListWidget(QWidget *parent= 0);
06 protected:
07 void mousePressEvent(QMouseEvent *event);
08 void mouseMoveEvent(QMouseEvent *event);
09 void dragEnterEvent(QDragEnterEvent *event);
10 void dragMoveEvent(QDragMoveEvent *event);
11 void dropEvent(QDropEvent *event);
12 private:
13 void startDrag();
14 QPoint startPos;
15 };
ProjectListWidget переопределяет пять обработчиков событий, которые объявлены в QWidget.
01 ProjectListWidget::ProjectListWidget(QWidget *parent)
02 : QListWidget(parent)
03 {
04 setAcceptDrops(true);
05 }
В конструкторе мы обеспечиваем возможность приема переносимого объекта в виджете со списком.
01 void ProjectListWidget::mousePressEvent(QMouseEvent *event)
02 {
03 if (event->button() == Qt::LeftButton)
04 startPos = event->pos();
05 QListWidget::mousePressEvent(event);
06 }
Когда пользователь нажимает левую кнопку мышки, мы сохраняем позицию мышки в закрытой переменной startPos. Мы вызываем определенную в классе QListWidget функцию mousePressEvent() для обеспечения обработки в QListWidget обычным образом события нажатия кнопкй мышки.
01 void ProjectListWidget::mouseMoveEvent(QMouseEvent *event)
02 {
03 if (event->buttons() & Qt::LeftButton) {
04 int distance = (event->pos() - startPos).manhattanLength();
05 if (distance >= QApplication::startDragDistance())
06 startDrag();
07 }
08 QListWidget::mouseMoveEvent(event);
09 }
Действие, при котором пользователь перемещает курсор мышки и одновременно держит нажатой левую кнопку, мы рассматриваем как начало перетаскивания объекта. Мы вычисляем расстояние между текущей позицией мышки и позицией нажатия левой кнопки мышки. Если это расстояние превышает рекомендованное в QApplication расстояние для регистрации начала перетаскивания (обычно 4 пикселя), мы вызываем закрытую функцию startDrag() для запуска процесса перетаскивания объекта. Это предотвращает инициирование процесса перетаскивания из-за дрожания руки пользователя.
01 void ProjectListWidget::startDrag()
02 {
03 QListWidgetItem *item = currentItem();
04 if (item) {
05 QMimeData *mimeData = new QMimeData;
06 mimeData->setText(item->text());
07 QDrag *drag = new QDrag(this);
08 drag->setMimeData(mimeData);
09 drag->setPixmap(QPixmap(":/images/реrson.png"));
10 if (drag->start(Qt::MoveAction) == Qt::MoveAction)
11 delete item;
12 }
13 }
В функции startDrag() мы создаем объект типа QDrag с указанием this в качестве родительского элемента. Объект QDrag хранит данные в объекте QMimeData. В нашем примере мы обеспечиваем данные типа text/plain, используя функцию QMimeData::setText(). Класс QMimeData содержит несколько функций, предназначенных для обработки наиболее распространенных типрв объектов переноса (изображений, адресов URL, цветов и т.д.); он может обрабатывать произвольные типы MIME, представленные массивами QByteArray. Вызов QDrag::setPixmap() задает пиктограмму, которая следует за курсором в процессе перетаскивания объекта.
Вызов функции QDrag::start() запускает операцию перетаскивания объекта и ждет, пока пользователь не отпустит перетаскиваемый объект или не отменит перетаскивание. В аргументе этой функции задается перечень поддерживаемых «операций перетаскивания» (Qt::CopyAction, Qt::MoveAction и Qt::LinkAction); она возвращает ту операцию перетаскивания, которая была выполнена (или Qt::IgnoreAction, если не было выполнено никакой операции). Тип выполняемой операции зависит от того, какие операции допускаются исходным виджетом, какие операции поддерживает целевой виджет и какие клавиши—модификаторы нажаты в момент отпуска переносимого объекта. После вызова этой функции Qt становится владельцем переносимого объекта и удалит его, когда он станет ненужным.
01 void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event)
02 {
03 ProjectListWidget *source =
04 qobject_cast<ProjectListWidget *>(event->source());
05 if (source && source != this) {
06 event->setDropAction(Qt::MoveAction);
07 event->accept();
08 }
09 }
Виджет ProjectListWidget не только инициирует перенос объектов, он также является местом приема таких объектов, если они приходят от другого виджета ProjectListWidget того же самого приложения. QDragEnterEvent::source() возвращает указатель на виджет, который инициирует перенос, если этот виджет принадлежит тому же самому приложению; в противном случае он возвращает нулевой указатель. Мы используем qobject_cast<T>(), чтобы убедиться в инициировании переноса виджетом ProjectListWidget. Если все верно, мы указываем Qt на нашу готовность восприятия данного действия как переноса.
01 void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event)
02 {
03 ProjectListWidget *source =
04 qobject_cast<ProjectListWidget *>(event->source());
05 if (source && source != this) {
07 event->setDropAction(Qt::MoveAction);
08 event->accept();
09 }
10 }
Программный код функции dragMoveEvent() идентичен тому, что мы делали в функции dragEnterEvent(). Он необходим, потому что нам приходится переопределять реализацию этой функции в классе QListWidget (в действительности в классе QAbstractItemView).
01 void ProjectListWidget::dropEvent(QDropEvent *event)
02 {
03 ProjectListWidget *source =
04 qobject_cast<ProjectListWidget *>(event->source());
05 if (source && source != this) {
06 addItem(event->mimeData()->text());
07 event->setDropAction(Qt::MoveAction);
08 event->accept();
09 }
10 }
В DropEvent() мы используем функцию QMimeData::text() для получения перенесенного текста и создаем элемент с этим текстом. Нам также необходимо воспринять данное событие как «операцию перетаскивания», чтобы указать исходному виджету на то, что он может теперь удалить первоначальную версию перенесенного элемента.
«Drag-and-drop» — мощный механизм передачи данных между приложениями. Однако в некоторых случаях его можно реализовать, не используя предусмотренные в Qt средства механизма «drag-and-drop». Если нам требуется переносить данные внутри одного виджета некоторого приложения, во многих случаях мы можем просто переопределить функции mousePressEvent() и mouseReleaseEvent().
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Программное обеспечение для поддержки SSH
Программное обеспечение для поддержки SSH Существуют два основных пакета SSH, предназначенных для работы в системе Linux: коммерческий продукт SSH (http://www.ssh.com/products/ssh/), разработанный компанией SSH, и пакет OpenSSH, распространяемый в исходных кодах (http://www.openssh.org). Пакет OpenSSH входит в
6.5.3. Действие DROP
6.5.3. Действие DROP Данное действие просто «сбрасывает» пакет и iptables «забывает» о его существовании. «Сброшенные» пакеты прекращают свое движение полностью, т.е. они не передаются в другие таблицы, как это происходит в случае с действием ACCEPT. Следует помнить, что данное
Глава 9. Технология «drag-and-drop»
Глава 9. Технология «drag-and-drop» Технология «drag-and-drop» («перетащить и отпустить») является современным и интуитивным способом передачи информации внутри одного приложения или между разными приложениями. Она часто является дополнением к операциям с буфером обмена по
Удаление таблиц и индексов с помощью предложения DROP
Удаление таблиц и индексов с помощью предложения DROP Удалять элементы базы данных можно с помощью предложения DROP. Например, чтобы удалить таблицу, используйте приведенную ниже команду SQL.DROP TABLE tblRegionС помощью предложения DROP можно также удалить индекс в таблице, как
Drop Shadow (Отбрасывать тень)
Drop Shadow (Отбрасывать тень) Drop Shadow (Отбрасывать тень) – эффект, позволяющий имитировать тень, отбрасываемую элементом, находящимся на текущем слое. Выберите данный эффект в списке эффектов, после чего появляется окно настройки тени (рис. 8.2), где мы можем задать такие
5.2.3. Синтаксис DROP PROCEDURE и DROP FUNCTION
5.2.3. Синтаксис DROP PROCEDURE и DROP FUNCTION DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_nameЭта инструкция используется, чтобы удалить сохраненную процедуру или функцию. То есть определенная подпрограмма будет удалена с сервера. Начиная с MySQL 5.0.3, Вы должны иметь привилегию ALTER ROUTINE для подпрограммы. Такая
6.2. Синтаксис DROP TRIGGER
6.2. Синтаксис DROP TRIGGER DROP TRIGGER [ schema_name .] trigger_nameЭто уничтожает триггер. Имя базы данных опционально. Если оно не задано, триггер удаляется из заданной по умолчанию базы данных, Вызов DROP TRIGGER был добавлен в MySQL 5.0.2. Использование требует привилегии SUPER.Обратите внимание: До MySQL
7.3. Синтаксис DROP VIEW
7.3. Синтаксис DROP VIEW DROP VIEW [IF EXISTS]view_name [, view_name] …[RESTRICT | CASCADE]DROP VIEW удаляет один или большее количество view. Вы должны иметь привилегию DROP для каждого view. Если любой из view, именованных в списке параметров не существует, MySQL возвращает индикацию ошибки с именем, которые не
Обеспечение поддержки подписывания объектов в ваших классах
Обеспечение поддержки подписывания объектов в ваших классах Традиционно при необходимости доступа к объектам, содержащимся в коллекциях — например, массивах и словарях, — программисту требовалось получить доступ к методу в словаре или массиве, чтобы получить или
DROP TABLE
DROP TABLE Используйте оператор DROP TABLE для удаления таблицы и ее данных из базы данных.Это полное удаление, оно не может быть отменено после подтверждения транзакции.DROP TABLE имя;Следующий оператор удаляет таблицу PERSONNEL:DROP TABLE
ТЕХНОЛОГИИ: 2G, 3G, 3.5G, 3.75G… Технологии мобильной связи дробятся и множатся
ТЕХНОЛОГИИ: 2G, 3G, 3.5G, 3.75G… Технологии мобильной связи дробятся и множатся Автор: Родион НасакинНи один аналитик не возьмется со стопроцентной уверенностью указать технологию, по которой будет работать подавляющее большинство сетей мобильной связи через пять-десять лет.
Включение поддержки ZFS
Включение поддержки ZFS Для практического использования ZFS on Linux перво-наперво необходимо обеспечить её поддержку в вашем дистрибутиве – ибо по причинам, описанным в предыдущей статье, сама собой она не поддержится ни в одном Linux’е.Как это сделать, зависит от дистрибутива.
Отображение тени ("Drop Shadow")
Отображение тени ("Drop Shadow") С помощью этого эффекта мы можем добавить к выделенному фрагменту тень. Правда, она будет статичной, не анимированной.Чтобы применить этот эффект к выделенному фрагменту изображения, нужно выбрать пункт Drop Shadow подменю Effects подменю Timeline Effects меню
Обеспечение безопасности с помощью технологии, тренировки и процедуры
Обеспечение безопасности с помощью технологии, тренировки и процедуры Компании, которые проводят тесты на возможность проникновения, сообщают, что их попытки проникнуть в компьютерную систему компании с помощью методов социнженерии практически в 100% случаев удаются.
ТЕХНОЛОГИИ: Контроллер контроллеру рознь: Паровозные технологии XXI века
ТЕХНОЛОГИИ: Контроллер контроллеру рознь: Паровозные технологии XXI века Автор: Анатолий СорокинВ своей предыдущей статье «IT-технологии Бога Войны» («КТ» #644-645) автор попытался сделать анализ применения и применимости современного хайтека к реалиям современной