如何在转换后访问我的自定义 QGraphicsItem 的数据 属性 的内容
How to access the contents of the data property of my custom QGraphicsItem after a cast
我有一个 自定义 class,它 继承 来自 QGraphicsRectItem
(基本上是 QGraphicsItem
) .一开始我有属性以及相应的getter和setter。一切都很好,直到我 从场景中获取项目 并 尝试调用 setters (或 getters): properties 没有不再存在。所以我对从场景中检索到的元素进行了转换,正如预期的那样.. 程序崩溃(因为元素不再存在......我觉得)。为了解决问题我使用了基础class(QGraphicsItem
)提供的data
属性我认为既然它是一个已经实施 属性 即使在演员表之后我也不应该有任何问题。 但问题仍然存在。为什么以及如何解决它?我脑海中还有其他解决方案,但我想了解原因
这是代表我的问题的简化代码
MyItem.h
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QObject>
#include <QDebug>
class MyItem :public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
enum {Type = UserType + 200};
MyItem();
QString getTestProperty() const;
void setTestProperty(QString p_newValue);
private:
QGraphicsTextItem* test_txt;
};
#endif // MYITEM_H
MyItem.cpp
#include "myitem.h"
MyItem::MyItem(): QGraphicsRectItem(0,0,100,100)
{
setFlag(QGraphicsItem::ItemIsMovable);
test_txt = new QGraphicsTextItem(this);
setData(0,QVariant("hi there"));
}
void MyItem::setTestProperty(QString p_newValue) {
setData(0,p_newValue);
qDebug()<<data(0).toString()<<endl;
test_txt->setPlainText(data(0).toString());
}
QString MyItem::getTestProperty() const {
return data(0).toString();
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtDebug>
#include <myitem.h>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QGraphicsScene* m_scene;
QGraphicsView* m_view;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setMinimumSize(800,600);
m_scene = new QGraphicsScene;
m_view = new QGraphicsView;
m_view->setScene(m_scene);
MyItem* item1 = new MyItem();
m_scene->addItem(item1);
setCentralWidget(m_view);
item1->setTestProperty("hello there :)");
MyItem* supposedPointerToItem1 = new MyItem;
supposedPointerToItem1 = qgraphicsitem_cast<MyItem*> (m_scene->items().first());
supposedPointerToItem1->setTestProperty("Another test that may fail");//Failed
}
MainWindow::~MainWindow()
{
}
最后这是我得到的结果的屏幕截图
The program ended suddenly
能失败的终将失败。
所以还是检查一下比较好。 QGraphicsScene::items() returns 所有项目,因此它也将 return QGraphicsTextItem,这就是您的情况:第一个项目不是 MyItem,而是 QGraphicsTextItem。
另一方面,您不必要地创建了第二个 MyItem,而且我认为没有必要使用 Q_OBJECT 或继承自 QObject。
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsRectItem>
class QGraphicsTextItem;
class MyItem :public QGraphicsRectItem
{
public:
enum {Type = QGraphicsItem::UserType + 200};
MyItem(QGraphicsItem *parent = nullptr);
QString getTestProperty() const;
void setTestProperty(const QString &p_newValue);
int type() const override;
private:
QGraphicsTextItem* test_txt;
};
#endif // MYITEM_H
#include "myitem.h"
#include <QDebug>
MyItem::MyItem(QGraphicsItem *parent): QGraphicsRectItem(0,0,100,100, parent)
{
setFlag(QGraphicsTextItem::ItemIsMovable);
test_txt = new QGraphicsTextItem(this);
setData(0,QVariant("hi there"));
}
void MyItem::setTestProperty(const QString & p_newValue) {
setData(0,p_newValue);
qDebug()<<data(0).toString();;
test_txt->setPlainText(data(0).toString());
}
QString MyItem::getTestProperty() const {
return data(0).toString();
}
int MyItem::type() const
{
return Type;
}
#include "mainwindow.h"
#include "myitem.h"
#include <QGraphicsScene>
#include <QGraphicsView>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
setMinimumSize(800,600);
m_scene = new QGraphicsScene;
m_view = new QGraphicsView;
m_view->setScene(m_scene);
MyItem* item1 = new MyItem();
m_scene->addItem(item1);
setCentralWidget(m_view);
item1->setTestProperty("hello there :)");
QList<QGraphicsItem*> items = m_scene->items();
for(QGraphicsItem *item : qAsConst(items)){
if(MyItem* myitem = qgraphicsitem_cast<MyItem *>(item)){
myitem->setTestProperty("Another test that may fail");
}
}
}
我有一个 自定义 class,它 继承 来自 QGraphicsRectItem
(基本上是 QGraphicsItem
) .一开始我有属性以及相应的getter和setter。一切都很好,直到我 从场景中获取项目 并 尝试调用 setters (或 getters): properties 没有不再存在。所以我对从场景中检索到的元素进行了转换,正如预期的那样.. 程序崩溃(因为元素不再存在......我觉得)。为了解决问题我使用了基础class(QGraphicsItem
)提供的data
属性我认为既然它是一个已经实施 属性 即使在演员表之后我也不应该有任何问题。 但问题仍然存在。为什么以及如何解决它?我脑海中还有其他解决方案,但我想了解原因
这是代表我的问题的简化代码
MyItem.h
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QObject>
#include <QDebug>
class MyItem :public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
enum {Type = UserType + 200};
MyItem();
QString getTestProperty() const;
void setTestProperty(QString p_newValue);
private:
QGraphicsTextItem* test_txt;
};
#endif // MYITEM_H
MyItem.cpp
#include "myitem.h"
MyItem::MyItem(): QGraphicsRectItem(0,0,100,100)
{
setFlag(QGraphicsItem::ItemIsMovable);
test_txt = new QGraphicsTextItem(this);
setData(0,QVariant("hi there"));
}
void MyItem::setTestProperty(QString p_newValue) {
setData(0,p_newValue);
qDebug()<<data(0).toString()<<endl;
test_txt->setPlainText(data(0).toString());
}
QString MyItem::getTestProperty() const {
return data(0).toString();
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtDebug>
#include <myitem.h>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QGraphicsScene* m_scene;
QGraphicsView* m_view;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setMinimumSize(800,600);
m_scene = new QGraphicsScene;
m_view = new QGraphicsView;
m_view->setScene(m_scene);
MyItem* item1 = new MyItem();
m_scene->addItem(item1);
setCentralWidget(m_view);
item1->setTestProperty("hello there :)");
MyItem* supposedPointerToItem1 = new MyItem;
supposedPointerToItem1 = qgraphicsitem_cast<MyItem*> (m_scene->items().first());
supposedPointerToItem1->setTestProperty("Another test that may fail");//Failed
}
MainWindow::~MainWindow()
{
}
最后这是我得到的结果的屏幕截图
The program ended suddenly
能失败的终将失败。
所以还是检查一下比较好。 QGraphicsScene::items() returns 所有项目,因此它也将 return QGraphicsTextItem,这就是您的情况:第一个项目不是 MyItem,而是 QGraphicsTextItem。
另一方面,您不必要地创建了第二个 MyItem,而且我认为没有必要使用 Q_OBJECT 或继承自 QObject。
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsRectItem>
class QGraphicsTextItem;
class MyItem :public QGraphicsRectItem
{
public:
enum {Type = QGraphicsItem::UserType + 200};
MyItem(QGraphicsItem *parent = nullptr);
QString getTestProperty() const;
void setTestProperty(const QString &p_newValue);
int type() const override;
private:
QGraphicsTextItem* test_txt;
};
#endif // MYITEM_H
#include "myitem.h"
#include <QDebug>
MyItem::MyItem(QGraphicsItem *parent): QGraphicsRectItem(0,0,100,100, parent)
{
setFlag(QGraphicsTextItem::ItemIsMovable);
test_txt = new QGraphicsTextItem(this);
setData(0,QVariant("hi there"));
}
void MyItem::setTestProperty(const QString & p_newValue) {
setData(0,p_newValue);
qDebug()<<data(0).toString();;
test_txt->setPlainText(data(0).toString());
}
QString MyItem::getTestProperty() const {
return data(0).toString();
}
int MyItem::type() const
{
return Type;
}
#include "mainwindow.h"
#include "myitem.h"
#include <QGraphicsScene>
#include <QGraphicsView>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
setMinimumSize(800,600);
m_scene = new QGraphicsScene;
m_view = new QGraphicsView;
m_view->setScene(m_scene);
MyItem* item1 = new MyItem();
m_scene->addItem(item1);
setCentralWidget(m_view);
item1->setTestProperty("hello there :)");
QList<QGraphicsItem*> items = m_scene->items();
for(QGraphicsItem *item : qAsConst(items)){
if(MyItem* myitem = qgraphicsitem_cast<MyItem *>(item)){
myitem->setTestProperty("Another test that may fail");
}
}
}