使用memcpy复制从QGraphicsItem派生的类不会创建新对象

Mat*_*ski 0 c++ malloc qt memcpy qgraphicsscene

我有几个不同的类派生自QGraphicsItem或其子(如QGraphicsRectItem).我现在需要复制这些类的选定对象,而不知道我确切地复制了哪一个.

因为QGraphicsScene::selectedItems()我决定使用它返回所选项目的列表,但是我不能复制它,QGraphicsItem因为它是一个抽象类.为了解决这个问题,我试图使用malloc和复制对象memcpy.

  1. MainWindow.cpp

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        scene = new QGraphicsScene();
        item = new QGraphicsRectItem(50,50,50,50);
        item->setFlag(QGraphicsItem::ItemIsSelectable);
        scene->addItem(item);
        item->setSelected(true);
        ui->graphicsView->setScene(scene);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        for(QGraphicsItem *item : scene->selectedItems())
        {
            QGraphicsItem *copiedItem=(QGraphicsItem *)malloc(sizeof(*item));  
            memcpy(copiedItem, item, sizeof(*copiedItem));   
            copiedItem->moveBy(50, 50);
            scene->addItem(copiedItem);
    
            qDebug() << item;
            qDebug() << copiedItem;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. MainWindow.h

    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
        public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        QGraphicsScene *scene;
        QGraphicsRectItem *item;
    
        private slots:
            void on_pushButton_clicked();
    
        private:
            Ui::MainWindow *ui;
    };
    
    Run Code Online (Sandbox Code Playgroud)

包含QGraphicsView和QPushButton的GUI足以满足此示例.

此代码似乎有效,item并且copiedItem具有不同的地址,但具有与qDebug()返回相同的属性.

然而,场景返回以下错误:

QGraphicsScene::addItem: item has already been added to this scene
Run Code Online (Sandbox Code Playgroud)

我不太明白为什么场景认为物品是相同的,而他们有不同的地址.有什么方法可以解决这个问题吗?

编辑:如果可能的话我想这样做而不修改派生类的代码QGraphicsItem,因为这是一个小组工作,我不想错过其他功能.

Rob*_*ieE 5

如果你看一下qgraphicsitem.h中的类定义,你会看到以下内容:

private:
    Q_DISABLE_COPY(QGraphicsItem)
    Q_DECLARE_PRIVATE(QGraphicsItem)
Run Code Online (Sandbox Code Playgroud)

这意味着,根据设计,你不应该复制一个QGraphicsItem,每个对象应该是唯一的.

编辑:我认为你被拒绝复制能力的原因是因为QGraphicsItem遵循复合设计模式.创建具有子项的单个对象的副本将导致子项具有多个父项.为了解决这个问题,你不仅要复制你感兴趣的项目,还要复制子层次结构中的每个孩子.对于非常大的层次结构,这可能会成为非常耗时的操作.

如果您确实觉得需要复制,可以创建一个克隆工厂函数/类,通过遍历所有对象的属性并将它们传输到新创建的QGraphicsItem来创建QGraphicsItem及其所有子元素的克隆.

如果这不可行,或许可以考虑以不同的方式实现目标.