Как преобразовать QGraphicsItem в созданный класс, когда у меня уже есть инициализированные указатели атрибутов? - PullRequest
1 голос
/ 28 марта 2019

У меня есть свой собственный QGraphicsPixmapItem, который состоит из QGraphicsPixmapItem и некоторых дополнительных атрибутов (например, std::string name)

class MyQGraphicsPixmapItem : public QGraphicsPixmapItem {
private:
    std::string name;
    ...
public:
    MyQGraphicsPixmapItem();
    explicit MyQGraphicsPixmapItem(const QPixmap &pixmap, std::string name, QGraphicsItem *parent = nullptr);
    std::string getname() const;
...
};

И конструктор выглядит так:

MyQGraphicsPixmapItem::MyQGraphicsPixmapItem(const QPixmap &pixmap, std::string name, QGraphicsItem *parent) :
QGraphicsPixmapItem(pixmap, parent), name(name){
...
}

Вот проблема: у меня есть куча MyQGraphicsPixmapItem, которые я добавляю в QGraphicsScene. Но когда я использую метод QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const, он возвращает QGraphicsItem* (не MyQGraphicsPixmapItem*). Итак, я полагаю, что я должен использовать право понижения? Но даже после использования броска вниз, как это:

    MyQGraphicsPixmapItem* item = static_cast<MyQGraphicsPixmapItem*>(QGraphicsScene::itemAt(...));
    std::cout << item->getName() << std::endl;

возвращает пустую строку (как не было this.name = name;, как показано в конструкторе).

В заключение я создаю группу MyQGraphicsPixmapItem в QGraphicsScene с правильной name инициализацией (я проверял ее с std::cout во время создания QGraphicsScene), но когда я хочу случайным образом выбрать QGraphicsItem и проверь, как его зовут, я использую QGraphicsScene::itemAt, который каждый раз сбрасывает std::string name, чтобы опустошиться, несмотря на понижение. Кроме того, я очень уверен, что указываю на правильные MyQGraphicsPixmapItem с правильными аргументами (я провел несколько тестов). Я также думал о реализации правильного "itemAt" в моем классе "MyScene" (который, как вы уже догадались, наследует от "QGraphicsScene"), но я бы снова использовал type_casting.

PS: Скажите, правильно ли задан мой вопрос.

С уважением

1 Ответ

1 голос
/ 28 марта 2019

Вы должны иметь возможность использовать dynamic_cast, но Qt также предоставляет свой собственный приведение qgraphicsitem_cast, которое возвращает предмет, приведенный к данному типу, если предмет этого типа или нет 0.

Примечание из документа:

Чтобы эта функция работала правильно с пользовательскими элементами, переопределите функцию type () для каждого пользовательского подкласса QGraphicsItem.

Пример класса:

class MyQGraphicsPixmapItem : public QGraphicsPixmapItem
{
public:
    ...
    enum { Type = UserType + 1 };
    int type() const override { return Type; }
    ...
};

Пример теста:

MyQGraphicsPixmapItem myItem;
qDebug() << &myItem;
QGraphicsItem *item = &myItem;
MyQGraphicsPixmapItem *castedItem = qgraphicsitem_cast<MyQGraphicsPixmapItem*>(item);
if (castedItem) {
    qDebug() << castedItem;
} else {
    qWarning() << "casting failed";
}

Обновление:

QGraphicsScene :: itemAt возвращает самый верхний видимый элементв указанной позиции, или 0, если в этой позиции нет элементов.

Если вы подтвердили с помощью qgraphicsitem_cast, что вы успешно произвели кастование, т.е. он вернул указатель, а не 0, тогда вы действительно получили свой пользовательский элемент, а не некоторыедругой графический элемент.Тогда в нем должно быть определено имя, а не пустая строка, если вы определили имя для всех своих пользовательских элементов.

Для дальнейшей отладки этой проблемы вы можете использовать QGraphicsScene :: items , чтобы вывести список всехпредметы на сцене считаются видимыми QGraphicsScene::itemAt.Выполните приведение в цикле и распечатайте имя всех ваших пользовательских элементов.

Одна вещь, которая приходит мне в голову, это то, что это связано с координатами, которые вы используете при вызове itemAt.Например, вы выполняете кастинг, когда щелкаете мышью, а затем запрашиваете сцену с координатами элемента *1036*, а не с координатами сцены . QGraphicsSceneMouseEvent :: scenePos возвращает положение курсора мыши в координатах сцены.Может быть, вы не получаете заказной предмет, как вы думаете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...