Я реализую небольшой интерфейс с Qt
, На этапе, над которым я сейчас работаю, у меня есть Scores (пользовательский класс), который я могу перемещать в Docks (опять же, в пользовательский класс), который может содержать только один счет.
Я вдохновил себя (очень) этим примером: Магниты на холодильник.
В этой конфигурации информация о перетаскиваемом объекте переносится благодаря QByteArray
, хранящиеся в данных MIME, благодаря сериализации QDataStream
,
Я хотел бы, чтобы при падении на оккупированную док-стану балл «проживал», чтобы он занял свое первоначальное место. Я думал, что смогу сделать это, имея атрибут, содержащий адрес оригинальной док-станции, но я не могу сохранить этот указатель в потоке данных.
Здесь следует часть моего кода:
/* Part of the definition of my classes */
class Score : public QLabel
{
Q_OBJECT
protected:
QString labelText;
Dock * dock;
QImage * click;
};
class Dock : public QFrame
{
Q_OBJECT
protected:
Score * score;
};/* And the 4 methods allowing the drag and drop */
void Dock::mousePressEvent(QMouseEvent *event)
{
Score * child = dynamic_cast<Score *>(childAt(event->pos()));
if (!child)
return;
QPoint hotSpot = event->pos() - child->pos();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << child->getLabelText() << child->getClick() << QPoint(hotSpot);
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-score", itemData);
mimeData->setText(child->getLabelText());
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(QPixmap::fromImage(*child->getClick()));
drag->setHotSpot(hotSpot);
child->hide();
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
child->close();
else
child->show();
}
void Dock::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-score"))
{
if (children().contains(event->source()))
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
event->acceptProposedAction();
}
else
event->ignore();
}
void Dock::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("application/x-score"))
{
if (children().contains(event->source()))
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
event->acceptProposedAction();
}
else
event->ignore();
}
void Dock::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("application/x-score"))
{
const QMimeData *mime = event->mimeData();
QByteArray itemData = mime->data("application/x-score");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QString text;
QImage * img;
QPoint offset;
dataStream >> text >> img >> offset;
Score * newScore = new Score(text, this);
newScore->show();
newScore->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
event->acceptProposedAction();
}
else
event->ignore();
static_cast<FrameCC *>(parentWidget())->calcTotal();
}
Я не мог перегрузить << и оператор >> для QDataStream
и Dock *, потому что единственный способ сделать это с указателем — это хранить реальные данные. Но проблема в том, что я не хочу данных, мне просто нужен указатель!
Если у вас есть идея, даже если это означает, что мне нужно переосмыслить способ сделать это, я бы с удовольствием ее услышал. Спасибо!
Если я правильно понял, вы хотите сериализовать указатель на док? Я не очень понимаю, почему вы делаете это трудным путем.
Как насчет этого:
itemData.fromRawData(reinterpret_cast<char*>(&score, sizeof(Score*)));
union {char chr[8]; Score *score} scorecast;
memcpy(scorecast.chr, itemData.data(), sizeof(Score*));
, затем получите доступ к вашему счету очков через Scorecast.scoreЭто также спасло бы вас от отправки всех данных в Score-to-drop …
Просто последняя мысль: QByteArray.data () дает const char * для данных, составляющих ваш указатель. Как насчет * reinterpret_cast<Гол * *>(imageData.data ()) чтобы вернуть указатель обратно?
И, наконец, появился последний, читающий мой собственный код сортировки QDataStream:
QDataStream & operator << (QDataStream & s, const Score * scoreptr)
{
qulonglong ptrval(*reinterpret_cast<qulonglong *>(&scoreptr));
return s << ptrval;
}
QDataStream & operator >> (QDataStream & s, Score *& scoreptr)
{
qulonglong ptrval;
s >> ptrval;
scoreptr = *reinterpret_cast<Score **>(&ptrval);
return s;
}