Russian Qt Forum
Ноябрь 22, 2024, 18:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Drag'n'drop из дочернего виджета  (Прочитано 11991 раз)
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« : Июль 10, 2018, 23:42 »

Добрый вечер.
Во всех примерах по перетаскиванию в Qt, которые я видел, создаётся собственный виджет и в нём перекрывается mousePressEvent.
Допустим, у меня есть главное окно (наследник QMainWindow), в нём QTableView и другие виджеты. Я хочу, чтобы у меня работал drag'n'drop из QTableView в другие виджеты. Мне при этом обязательно отказываться от стандартного QTableView, создавать его потомка и там соответственно перекрывать mousePressEvent? Или это можно как-то разрулить в MainWindow?
Создавать потомка QTableView не хочется, поскольку окно создано в дизайнере, не хочется руками тащить в .ui нестандартные объекты.
Записан

Мои проекты на Qt: DoubleContact, LInvert
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Июль 11, 2018, 04:31 »

Я хочу, чтобы у меня работал drag'n'drop из QTableView в другие виджеты. Мне при этом обязательно отказываться от стандартного QTableView, создавать его потомка и там соответственно перекрывать mousePressEvent?
Необязательно, можно фильтр навесить (installEventFilter).  И если перетаскивание чисто "местное", то лучше на фильтре все и сделать, не используя DnD.
Записан
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« Ответ #2 : Июль 11, 2018, 11:08 »

1Необязательно, можно фильтр навесить (installEventFilter).
Спасибо за наводку, копну в эту сторону. Я installEventFilter раньше использовал, но только для обработки событий клавиатуры.
Цитировать
И если перетаскивание чисто "местное", то лучше на фильтре все и сделать, не используя DnD.
Да, местное, с одного QTableView на другой.
Записан

Мои проекты на Qt: DoubleContact, LInvert
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Июль 11, 2018, 11:41 »

Using Drag and Drop with Item Views

И если перетаскивание чисто "местное", то лучше на фильтре все и сделать, не используя DnD.
Вот зачем вы советуете человеку, явно не искушенному в этих вопросах, заниматься сексом?
« Последнее редактирование: Июль 11, 2018, 11:45 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июль 11, 2018, 12:02 »

Вот зачем вы советуете человеку, явно не искушенному в этих вопросах, заниматься сексом?
По-моему так проще чем ковыряться в событиях DbD
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Июль 11, 2018, 12:06 »

Т.е. самому городить мышиные грабы, установку курсора, иконки и чтобы всё было портабельно - это проще?
Записан

Qt 5.11/4.8.7 (X11/Win)
zhbr
Гость
« Ответ #6 : Июль 12, 2018, 06:56 »

имхо проще делать стандартными средствами DnD Qt. Не так давно как раз делал это с QTableView - помогли следующие доки: http://doc.qt.io/qt-5/dnd.html и http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views
правда надо иметь ввиду один баг (https://bugreports.qt.io/browse/QTBUG-67155), присутствующий во всех версиях.
если док не достаточно, могу попробовать сделать выжимку
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Июль 13, 2018, 06:57 »

Т.е. самому городить мышиные грабы, установку курсора, иконки и чтобы всё было портабельно - это проще?
Да, и намного. И причем тут портабельность - ну фильтруем 3 события мыши вместо 1, как она может пострадать? 
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #8 : Июль 13, 2018, 10:32 »

Велосипед... Но зачем?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« Ответ #9 : Июль 13, 2018, 11:47 »

Спасибо за наводку, я даже не предположил, что подобные вопросы могут на уровне модели решаться (и вроде как-то это не в духе Model-View вообще...).
Буду пробовать.
Записан

Мои проекты на Qt: DoubleContact, LInvert
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« Ответ #10 : Сентябрь 13, 2018, 18:40 »

GreatSnake: ещё раз спасибо.

Прочитал эту доку, сделал решение через mimeData/dropMimeData. Из одного table view в другой данные внутри одной программы таскаются на ура.
Сначала сделал, как и в примерах, через QDataStream.

Потом, поскольку формат у меня, в общем-то, текстовый (известен как text/vcard), решил попробовать QTextStream. Тоже заработало. Только в конце записи строк в поток обязательно надо вызвать flush(), иначе итоговый QByteArray получится пустым. Да, я знаю о наличии QMimeData::setText(), но он, к сожалению, даёт записанным данным фиксированный тип text/plain, а это не совсем мой случай.

И ещё остался вопрос, что мне делать в случае Qt::MoveAction для удаления записи в источнике. Делать специальный сигнал, который отсылается из dropMimeData, или есть стандартный механизм? Вообще, в доке есть такая фраза:
Цитировать
Although any combination of values from Qt::DropActions can be given, the model needs to be written to support them. For example, to allow Qt::MoveAction to be used properly with a list model, the model must provide an implementation of QAbstractItemModel::removeRows(), either directly or by inheriting the implementation from its base class.
Я правильно понял, что мне надо перекрыть removeRows(), и он при необходимости вызовется? У меня, правда, не list, а table...
Записан

Мои проекты на Qt: DoubleContact, LInvert
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« Ответ #11 : Сентябрь 28, 2018, 15:07 »

Я правильно понял, что мне надо перекрыть removeRows(), и он при необходимости вызовется?
К сожалению, на этом вопросе так и застрял. Вроде бы в кутешном примере puzzle removeRows() вызывается автоматом. У меня - нет.

Набросал простейший пример (да, код небрежный) с list model. В главном окне два list view. Класс DraggedModel - наследник QAbstractListModel, выводит строки из списка ss (QStringList).
Фрагмент конструктора главного окна:
Код
C++ (Qt)
   DraggedModel* m1 = new DraggedModel(QStringList() << "One" << "Two" << "Three");
   ui->listView->setModel(m1);
   DraggedModel* m2 = new DraggedModel();
   ui->listView_2->setModel(m2);
 
   ui->listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
   ui->listView->setDragEnabled(true);
   ui->listView->setAcceptDrops(true);
   ui->listView->setDropIndicatorShown(true);
   ui->listView_2->setSelectionMode(QAbstractItemView::ExtendedSelection);
   ui->listView_2->setDragEnabled(true);
   ui->listView_2->setAcceptDrops(true);
   ui->listView_2->setDropIndicatorShown(true);
 

Методы модели:
Код
C++ (Qt)
DraggedModel::DraggedModel(const QStringList &strings)
   :ss(strings)
{
}
 
int DraggedModel::rowCount(const QModelIndex &) const
{
   return ss.count();
}
 
QVariant DraggedModel::headerData(int section, Qt::Orientation orientation, int role) const
{
   if ((role == Qt::DisplayRole) && (orientation==Qt::Horizontal))
       return "Burkhumm";
   else
       return QAbstractItemModel::headerData(section, orientation, role);
}
 
QVariant DraggedModel::data(const QModelIndex &index, int role) const
{
   if (!index.isValid())
         return QVariant();
     if (index.row() >= ss.count())
         return QVariant();
   if (role==Qt::DisplayRole)
       return ss[index.row()];
   else return QVariant();
}
 
Qt::DropActions DraggedModel::supportedDropActions() const
{
   return Qt::CopyAction | Qt::MoveAction;
}
 
Qt::ItemFlags DraggedModel::flags(const QModelIndex &index) const
{
   Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
    if (index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
    else
        return Qt::ItemIsDropEnabled | defaultFlags;
}
 
QStringList DraggedModel::mimeTypes() const
{
   return QStringList() << "text/plain";
}
 
QMimeData *DraggedModel::mimeData(const QModelIndexList &indexes) const
{
   QMimeData *mimeData = new QMimeData();
   if (!indexes.isEmpty())
       mimeData->setText(ss[indexes[0].row()]);
   return mimeData;
}
 
bool DraggedModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
   if (action == Qt::IgnoreAction)
        return true;
    if (!data->hasFormat("text/plain"))
        return false;
    if (column > 0)
        return false;
    beginResetModel();
    ss << data->text();
    endResetModel();
    return true;
}
#include <iostream>
bool DraggedModel::removeRows(int row, int count, const QModelIndex &parent)
{
   std::cout << "DraggedModel::removeRows" << std:: endl;
   beginResetModel();
   ss.removeAt(row);
   endResetModel();
   return true;
}
 
Запускаю - removeRows() не вызывается. Чего ему может не хватать? Копирование работает, нареканий нет.
« Последнее редактирование: Сентябрь 28, 2018, 15:20 от DarkHobbit » Записан

Мои проекты на Qt: DoubleContact, LInvert
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #12 : Сентябрь 28, 2018, 15:28 »

При переопределении removeRows внутри метода надо вызывать пару beginRemoveRows/endRemoveRows, а не beginResetModel/endResetModel.
Записан
DarkHobbit
Самовар
**
Offline Offline

Сообщений: 197


Просмотр профиля
« Ответ #13 : Октябрь 01, 2018, 01:09 »

Э... Согласен, здесь погорячился, исправлю.
Но главную проблему это не решает. Сам-то removeRows() не вызывается, и тут уже не так важно, что я внутри него написал...
Записан

Мои проекты на Qt: DoubleContact, LInvert
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #14 : Октябрь 01, 2018, 03:41 »

http://doc.qt.io/qt-5/qabstractitemview.html#DragDropMode-enum ?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.211 секунд. Запросов: 23.