Передача данных с помощью QMimeData в Qt drag and drop - PullRequest
5 голосов
/ 22 февраля 2010

Я пытаюсь понять, как данные передаются при использовании перетаскивания в Qt. Из того, что я понял из примеров, которые я изучал, вы сначала определяете виджет как перетаскиваемый путем переопределения методов, унаследованных от QWidget.

В реализации переопределенного метода в примерах, которые я рассмотрел, создается указатель на объект QMimeData и сохраняется информация в нем путем вызова setText(const QString &text) и setData(const QByteArray &data). Они хранят информацию в объекте QByteArray с оператором <<:

QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);

dataStream << labelText << QPoint(ev->pos() - rect().topLeft());

QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-fridgemagnet", itemData);
mimeData->setText(labelText);

В определении метода dropEvent() в виджете, который принимает отбрасывания, обе эти переменные были получены с помощью оператора >>:

QString text;
QPoint offset;
dataStream >> text >> offset;

В методе setData() application / x-fridgemagnet был передан в качестве аргумента типа MIME. Это было определено где-то еще или это просто то, что вы можете придумать?

Как я могу сохранить и получить пользовательский объект внутри QMimeData объекта? Я попробовал это:

dataStream << labelText << QPoint(ev->pos() - rect().topLeft()) << myObject;

и попытался получить его так:

myClass myObject;
dataStream >> text >> offset >> myObject;

Но это не сработало, говорит theres "нет совпадения с оператором >>". Любые советы, что мне делать?

Ответы [ 2 ]

6 голосов
/ 23 февраля 2010

В методе setData () application / x-fridgemagnet был передан в качестве аргумента типа MIME. Это было определено где-то еще или это просто то, что вы можете придумать?

Если данные представлены в вашем собственном формате, вы можете сделать это. Однако если это что-то стандартизированное, например изображения, вам, вероятно, захочется использовать известный тип mime.

Если вы уже поддерживаете сериализацию в XML, то было бы легко создать свой собственный mime-тип, сериализовать в XML, а затем десериализовать на принимающей стороне.

Как я могу сохранить и получить пользовательский объект внутри объекта QMimeData?

Вам нужно будет создать не являющиеся членами операторы (<< и >>), которые будут записывать данные MyObject о членах способом, поддерживаемым QDataStream. Смотрите документацию QDataStream под заголовком "Чтение и запись другого класса Qt."

Это будет включать создание следующих двух методов:

QDataStream &operator<<(QDataStream &, const MyObject &);
QDataStream &operator>>(QDataStream &, MyObject &);

Поскольку эти операторы не являются членами, они будут определены за пределами вашего класса:

class MyObject { /* ... */ };

QDataStream &operator<<(QDataStream &stream, const MyObject &obj) {
    /* as long as first_member and second_member are types supported
       by QDataStream, I can serialize them directly.  If they're not
       supported, I'd need an operator for them as well unless I can
       convert them to a QString or something else supported by Qt /
       QDataStream */
    stream << obj.first_member;
    stream << obj.second_member;
    /* and so on and so forth */
    return stream;
}
/* and similarly for operator>> */
3 голосов
/ 23 февраля 2010

Да, вы можете создать свой собственный тип MIME для использования в вашем собственном приложении. Очевидно, что никакие внешние приложения не будут иметь понятия, что это такое, поэтому вы не сможете перетаскивать их за пределы своего собственного приложения.

Что касается хранения вашего собственного объекта, вам нужно определить оператор потока, так как Qt ничего не знает о вашем объекте. QDataStream определяет только потоковые операторы для простых встроенных типов. Вам нужно определить что-то вроде

QDataStream& operator<<( QDataStream& ds, const myClass& myObject )
{
    // Use existing QDataStream stream operators or other methods to serialise your object
    // ...
    // ...

    return ds;
}

Аналогично для десериализации вам нужно определить соответствующий operator>>.

...