Меняются координаты только у одного круга, а должны у всех

Хотел добавить в свою программу возможность пользователю выбирать количество кругов на радаре через spinbox, далее выбранное количество кругов становится переменной, по которой идет цикл отрисовки кругов, но дальше все круги должны менять свои координаты, но у меня их меняет только один круг. Я подумал, что нужно сделать список из кругов, но у меня возникает ошибка:

'QGraphicsEllipseItem::QGraphicsEllipseItem(const QGraphicsEllipseItem&)' is private Q_DISABLE_COPY(QGraphicsEllipseItem)

я пытался сделать их public, но это не помогло. Вообще, я не уверен, что нужно делать именно так, потому что потом как-то надо будет для элемента списка вызывать команду setpos. Не могли бы вы мне помочь?

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtCore>
#include <QtGui>
#include <QTimer>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QGraphicsScene *scene;
    QGraphicsLineItem *line;
    QGraphicsEllipseItem *ellipse;
    QList<QGraphicsEllipseItem> widget; //лист с кругами

private slots:
        void onTimeout();
        void onTimeout1();

        void on_pushButton_clicked();

        void on_pushButton_2_clicked();

        void on_pushButton_3_clicked();

private:
        int angle,R,R2,R3,n;
        QTimer timer,timer1;
        static int random(int low, int high) //случайные координаты для круга
        {
            return (qrand() % ((high + 1) - low) + low);
        }
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "QTimer"
#include "QtCore"
#include "QtGui"


Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    this->setWindowFlags (windowFlags() & ~Qt::WindowContextHelpButtonHint);

    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);
    scene->setSceneRect(-300,-250,600,600);

    angle = 0;
    n = 0;
    connect(&timer,SIGNAL(timeout()), this, SLOT(onTimeout())); //таймер для линии
    connect(&timer1,SIGNAL(timeout()), this, SLOT(onTimeout1())); //таймер для круга

    QPen black(Qt::black);

    R = int(1.6*qMin(width()/2,height()/2));
    R2 = int(R/1.3);
    R3 = int(R/1.8);
    scene->addEllipse(-R/2, -R/2, R, R,black); //большой круг
    scene->addEllipse(-R2/2, -R2/2, R2, R2,black); //средний круг
    scene->addEllipse(-R3/2, -R3/2, R3, R3,black); //маленький круг

    scene->addLine(0, -R/2, 0, R/2,black);//вертикальная линия
    scene->addLine(-R/2, 0, R/2, 0,black);//горизонтальная линия

    line = scene->addLine(0,0,0,-R/2,black);//линия радара
    angle = (angle >= 0 && angle <= 350) ? angle+10 : 0;

}

Dialog::~Dialog()
{
    delete ui;
}
void Dialog::onTimeout() //поворот линии
{
    line->rotate(angle);
    this->update(this->rect());
}

void Dialog::onTimeout1() //изменение положения кругов
{
    for (int i =0; i<n; i++)
    {
    if(qPow(random(-230,180),2)+qPow(random(-220,180),2)<=qPow(R,2)) //формула для расположения цели
    {
    ellipse->setPos(this->random(-230,180),this->random(-230,180));
    }
    }
    this->update(this->rect());
}

void Dialog::on_pushButton_clicked()
{
    timer.start(50);
    timer1.start(3000);
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(true);
}


void Dialog::on_pushButton_2_clicked()
{
    timer.stop();
    timer1.stop();
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
}


void Dialog::on_pushButton_3_clicked()
{
    QPen nopen(Qt::NoPen);
    QBrush red(Qt::red);
    n = ui->spinBox->value();
    for (int i =0; i<n; i++)
    {
     ellipse = scene->addEllipse(random(-230,180),random(-230,180), 30, 30,nopen,red);
     widget.push_back(ellipse);
    }
}

Ответы (1 шт):

Автор решения: Alexander Chernin

Немного исправил ваш код.

файл pro:

CONFIG += c++11

Dialog.h:

// Вместо qrand лучше использовать std::rand()
// n - не нужен, потому что у нас есть список отметок, а в нем есть size()

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTimer>

namespace Ui {
class Dialog;
}

class QGraphicsScene;
class QGraphicsLineItem;
class QGraphicsEllipseItem;

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QGraphicsScene *scene;
    QGraphicsLineItem *line;
    QList<QGraphicsEllipseItem*> spots; //лист с кругами

private slots:
        void onTimeout();
        void onTimeout1();

        void on_pushButton_clicked();

        void on_pushButton_2_clicked();

        void on_pushButton_3_clicked();

private:
        // Очистка списка отметок
        void clearSpots();

        int angle,R,R2,R3;
        QTimer timer,timer1;
        static int random(int low, int high) //случайные координаты для круга
        {
            return (std::rand() % ((high + 1) - low) + low);
        }
};

#endif // DIALOG_H

Dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

#include <QGraphicsScene>
#include <QGraphicsLineItem>
#include <QGraphicsEllipseItem>
#include <QtMath>

#include "QTimer"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    this->setWindowFlags (windowFlags() & ~Qt::WindowContextHelpButtonHint);

    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);
    scene->setSceneRect(-300,-250,600,600);

    angle = 0;
    connect(&timer,SIGNAL(timeout()), this, SLOT(onTimeout())); //таймер для линии
    connect(&timer1,SIGNAL(timeout()), this, SLOT(onTimeout1())); //таймер для круга

    QPen black(Qt::black);

    R = int(1.6*qMin(width()/2,height()/2));
    R2 = int(R/1.3);
    R3 = int(R/1.8);
    scene->addEllipse(-R/2, -R/2, R, R,black); //большой круг
    scene->addEllipse(-R2/2, -R2/2, R2, R2,black); //средний круг
    scene->addEllipse(-R3/2, -R3/2, R3, R3,black); //маленький круг

    scene->addLine(0, -R/2, 0, R/2,black);//вертикальная линия
    scene->addLine(-R/2, 0, R/2, 0,black);//горизонтальная линия

    line = scene->addLine(0,0,0,-R/2,black);//линия радара
    angle = (angle >= 0 && angle <= 350) ? angle+10 : 0;

}

Dialog::~Dialog()
{
    delete ui;
}
void Dialog::onTimeout() //поворот линии
{
    // Для Qt5.14+
    // line->setTransform(QTransform().rotate(angle), true);
    line->rotate(angle);
    this->update(this->rect());
}

void Dialog::onTimeout1() //изменение положения кругов
{
    for (auto* item: spots)
    {
        if(qPow(random(-230,180),2)+qPow(random(-220,180),2)<=qPow(R,2)) //формула для расположения цели
        {
            item->setPos(this->random(-230,180),this->random(-230,180));
        }
    }
    this->update(this->rect());
}

void Dialog::on_pushButton_clicked()
{
    timer.start(50);
    timer1.start(3000);
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(true);
}


void Dialog::on_pushButton_2_clicked()
{
    timer.stop();
    timer1.stop();
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
}


void Dialog::on_pushButton_3_clicked()
{
    // Очищаем список, а уже потом добавляем в него новые объекты
    // хотя, если вам надо именно добавлять новые отметки список,
    // то вызов этого метода можно удалить/закомментировать
    clearSpots();
    QPen nopen(Qt::NoPen);
    QBrush red(Qt::red);
    int n = ui->spinBox->value();
    for (int i = 0; i < n; i++)
    {
        auto* ellipse = scene->addEllipse(random(-230,180),random(-230,180), 30, 30,nopen,red);
        spots.push_back(ellipse);
    }
    update();
}

void Dialog::clearSpots()
{
    for(auto* item: spots) { // qAsConst(spots) Qt5.14+
        ui->graphicsView->scene()->removeItem(item);
    }
    qDeleteAll(spots);
    spots.clear();
}

Проверено, работает. (Qt5.14.1, Qt6.1.0) MinGW64 Windows 10

→ Ссылка