Send parameters with dynamically generated QComboBox - c++

I want to insert a QComboBox inside a QTableWidget. When I change the Index of the CB I'll call a methode to change the status in the sqlite table. But for this, I need do pass two parameters to the methode. The ID(First element of the row), and the current index of the CB.
I generate the QTableWidget like that:
...
for(int i = 0; i < dbModel->rowCount();i++){
row = dbModel->record(i);
ui->tW_Services->setItem(i,0,new QTableWidgetItem(row.field(0).value().toString()));
ui->tW_Services->setItem(i,1,new QTableWidgetItem(row.field(1).value().toString()));
ui->tW_Services->setItem(i,2,new QTableWidgetItem(row.field(2).value().toString()));
ui->tW_Services->setItem(i,3,new QTableWidgetItem(row.field(3).value().toString()));
ui->tW_Services->setItem(i,4,new QTableWidgetItem(row.field(4).value().toString() + "€"));
ui->tW_Services->setItem(i,5,new QTableWidgetItem(row.field(5).value().toString() + "€"));
//ui->tW_Services->setItem(i,6,new QTableWidgetItem(row.field(6).value().toString()));
QComboBox* combo = new QComboBox();
combo->addItem("open");
combo->addItem("paid");
if(row.field(6).value().toString() != "paid") combo->setCurrentIndex(0);
else combo->setCurrentIndex(1);
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboChanged(int)));
ui->tW_Services->setCellWidget(i,6,combo);
}
...
and the slot looks like that:
void MainWindow::onComboChanged(int ID)
{
qDebug() << "ID:" << QString::number(ID);
}
But when I try to create the method with 2 args:
void MainWindow::onComboChanged(int ID,int index)
{
qDebug() << "ID:" << QString::number(ID);
}
and attach a second parameter and calling the slot like:
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboChanged(row.field(0).value().toInt(),int)));
I get:
qt.core.qobject.connect: QObject::connect: No such slot MainWindow::onComboChanged(row.field(0).value().toInt(),int)
A minimal reproducible example:
There's just a single pushbutton and a qtablewidget
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void onComboChanged(int ID, int index);
void onComboChanged2(int index);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QComboBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->tableWidget->setColumnCount(4);
ui->tableWidget->setRowCount(3);
for(int i = 0; i < 3;i++){
ui->tableWidget->setItem(i,0,new QTableWidgetItem(QString::number(i)));
ui->tableWidget->setItem(i,1,new QTableWidgetItem("Test"));
ui->tableWidget->setItem(i,2,new QTableWidgetItem("Test 2"));
QComboBox* combo = new QComboBox();
combo->addItem("open");
combo->addItem("paid");
combo->setCurrentIndex(0);
int j = i+1;
//NOT WORKING
//connect(combo, SIGNAL(currentIndexChanged(int)),this,
// [=](int index) {this->onComboChanged(j, index);});
//WORKING
//connect(combo, SIGNAL(currentIndexChanged(int)),SLOT(onComboChanged2(int)));
ui->tableWidget->setCellWidget(i,3,combo);
}
}
void MainWindow::onComboChanged(int ID, int index)
{
qDebug() << "ID: " << ID << "index: "<< index;
}
void MainWindow::onComboChanged2(int index)
{
qDebug() << "ID: " << index;
}

Since currentIndexChanged only has one parameter, your slot cannot capture more than that. But, since the row ID does not change on emission, you can wrap onComboChanged into a lambda as shown here, which captures the row by copy:
connect(combo, &QComboBox::currentIndexChanged,
this, [=](int index) {this->onComboChanged(i, index);});
Since your code is not a minimal reproducible example, I could not test this. Let me know, if it doesn't work.

Related

QSignalMapper doesn't work when connecting QAbstractButton::clicked to map()

I want to make the MainWindow receive the signals emitted from QToolButtons, and then do something in the slot function according to the index sent from QToolButtons. When I compiled the project, no error occurred. But when I clicked these toolbuttons, nothing happened and the log didn't get printed. I think there's something wrong with the signal or slot, but the program runs with no errors, so I don't know how to find the solution.
MainWindow.cpp:
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle(MainWindowTitle);
setWindowIcon(QIcon(":/res/icons/logo.ico"));
signalMapper = new QSignalMapper(this);
initLayout();
}
void MainWindow::initLayout()
{
// initialize sidebar buttons
initSideBar();
// initialize QStackedWidget
/* initialize CodePage */
codePage = new CodePage(this);
ui->stackedWidget->addWidget(codePage);
ui->stackedWidget->setCurrentWidget(codePage);
/* initialize Charts */
qCharts = new ThemeWidget();
ui->stackedWidget->addWidget(qCharts);
// ui->stackedWidget->setCurrentWidget(qCharts);
}
void MainWindow::initSideBar()
{
QStringList btn_bgImages;
QStringList btn_names;
btn_bgImages << ":res/sidebar/code.png" << ":res/sidebar/pencil.png" << ":res/sidebar/visualize.png" << ":res/sidebar/graph.png";
btn_names << "Editor" << "Designer" << "Visualize" << "Charts";
for(int i = 0; i < btn_bgImages.size(); i++)
{
cTabButton* ctBtn = new cTabButton(btn_bgImages.at(i));
ctBtn->setText(btn_names.at(i));
connect(ctBtn, SIGNAL(&QAbstractButton::clicked), signalMapper, SLOT(&QSignalMapper::map));
signalMapper->setMapping(ctBtn, i);
ui->sidebar->addWidget(ctBtn, 0, Qt::AlignTop);
}
QObject::connect(signalMapper, SIGNAL(map), this, SLOT(MainWindow::switchPage));
}
void MainWindow::switchPage(int index)
{
qDebug() << "switchPage() triggered";
switch(index)
{
case 0:
qStackedWidget->setCurrentWidget(codePage);
break;
case 1:
break;
case 2:
break;
case 3:
qStackedWidget->setCurrentWidget(qCharts);
break;
default:
break;
}
}
MainWindow.h:
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
private slots:
void switchPage(int);
private:
Ui::MainWindow* ui;
CodeEditor* configEditor;
QListView* sidebar;
QStackedWidget* qStackedWidget;
CodePage* codePage;
ThemeWidget* qCharts;
QSignalMapper* signalMapper;
void initSideBar();
void initLayout();
};
cTabButton.h
class cTabButton : public QToolButton{
Q_OBJECT
public:
cTabButton(const QString& path, QWidget *parent=0);
~cTabButton();
protected:
QString path;
bool m_mousePressed;
bool m_mouseHover;
void doPaintStuff(int topColor, int centerColor, int bottomColor);
void setButtonPressed(bool isPressed);
void enterEvent(QEnterEvent *);
void leaveEvent(QEvent *);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
};
It looks like you are connecting to the wrong signal of QSignalMapper. Since you map to an integer, you want to connect to QSignalMapper::mappedInt:
QObject::connect(signalMapper, &QSignalMapper::mappedInt, this, &MainWindow::switchPage);

Qt, C++, XML reader crashes/freezes when I try parsing deeper data values

In an earlier Question I asked about why my program/QTcpServer was crashing all the time, and I really appreciate the help I got from everyone.
However, I have decided to try and rebuild the Program from scratch in order to see why it crashes, and I may have found something.
Allow me to post the new Code below:
//mainwindow.h
#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>
#include <QStandardItemModel>
#include <QTcpServer>
#include <QTcpSocket>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void startServer();
void handleConnection();
void readMessage();
void ReadXML(QString XMLString);
private:
QPushButton *SServer;
QTextEdit * ContainerView; //not changing to QTableView just yet
int Pallet_Number;
QTcpServer *tcpServer;
QTcpSocket *tcpSocket;
};
//mainwindow.cpp
#include "mainwindow.h"
#include <QLabel>
#include <QLayout>
#include <QDebug>
#include <QDomDocument>
#include <QRegularExpression>
static QRegularExpression Box_Code("B");
static QRegularExpression Cylinder_Code("C");
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
SServer(new QPushButton("Start Listening")),
ContainerView(new /*QTableView*/QTextEdit),
tcpServer(new QTcpServer),
tcpSocket(new QTcpSocket)
{
QStringList HeaderRow;
HeaderRow.append("Pallet");
HeaderRow.append("Container");
HeaderRow.append("Code");
HeaderRow.append("Height");
HeaderRow.append("Breadth/Diameter");
HeaderRow.append("Length");
HeaderRow.append("Weight");
resize(800,300);
connect(SServer, &QPushButton::clicked, this, &MainWindow::startServer);
connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::handleConnection);
connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::handleConnection);
QLabel *Lab1(new QLabel("Listening on Port 6164"));
QHBoxLayout *HB(new QHBoxLayout);
QVBoxLayout *VB(new QVBoxLayout);
HB->addWidget(SServer);
HB->addWidget(Lab1);
VB->addItem(HB);
VB->addWidget(ContainerView);
QWidget *window(new QWidget);
window->setLayout(VB);
setCentralWidget(window);
}
MainWindow::~MainWindow()
{
}
void MainWindow::startServer()
{
if(!tcpServer->listen(QHostAddress::LocalHost, 6164)){
qDebug() << "Error connecting to Server";
tcpServer->close();
return;
} else {
qDebug() << "Started Successfully";
}
}
void MainWindow::handleConnection()
{
tcpSocket = tcpServer->nextPendingConnection();
qDebug() << "New Connection!";
connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::readMessage);
}
void MainWindow::readMessage()
{
ContainerView->clear(); //clear table to prepare for new XMLString
QByteArray buffer = tcpSocket->readAll();
QString FromContainer = QString::fromUtf8(buffer);
ReadXML(FromContainer);
}
void MainWindow::ReadXML(QString XMLString)
{
ContainerView->append(XMLString);
QDomDocument Xml_String;
Xml_String.setContent(XMLString);
QDomElement Xml_Root = Xml_String.documentElement();
if(Xml_Root.tagName() == "Pallets")
{
QDomElement Xml_Pallet = Xml_Root.firstChildElement();
while(!Xml_Pallet.isNull())
{
if(Xml_Pallet.tagName() == "Pallet")
{
int PN = Xml_Pallet.attribute("Number").toInt(nullptr,10);
QDomElement Box_Cyl = Xml_Pallet.firstChildElement();
while(!Box_Cyl.isNull())
{
if(Box_Cyl.tagName() == "Box")
{
QString BC = Box_Cyl.tagName();
ContainerView->append("Pallet No. " + QString::number(PN) + "\nContainer: " + BC);
// QDomElement Box_Info = Box_Cyl.firstChildElement();
// while(!Box_Info.isNull())
// {
// ...more code
// Box_Info = Box_Info.nextSiblingElement();
// }
} else if(Box_Cyl.tagName() == "Cylinder")
{
QString BC = Box_Cyl.tagName();
ContainerView->append("Pallet No. " + QString::number(PN) + "\nContainer: " + BC);
}
Box_Cyl = Box_Cyl.nextSiblingElement();
}
}
Xml_Pallet = Xml_Pallet.nextSiblingElement();
}
}
}
The XML String I am trying to read is shown below:
When I include the commented code to read the Elements within 'Box' or 'Cylinder' (I altered the code to check both sides), the program freezes.
This hasn't happened to me before, so I have no idea what to do.

QLabel show images like a video

I try to let a QLabel show images like a video.
I want this display my images from f0000.png to f0039.png slowly so I can see progress.
For some reason my for loop starts with 50.
When I see the program run it only show one image or it change too fast I can't see the progress.
How to fix it let it show images like video.
you can use a Qtimer and set the speed as faster as you need
header:
#include <QMainWindow>
#include <QTimer>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
public slots:
void updateLabel();
private:
Ui::MainWindow *ui;
QTimer* _timer;
int index{0};
QString pixResource{};
};
and impl.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
_timer = new QTimer(parent);
connect(_timer, SIGNAL(timeout()), this, SLOT(updateLabel()));
_timer->start(1000);
}
MainWindow::~MainWindow()
{
delete ui;
_timer->stop();
delete _timer;
}
void MainWindow::updateLabel()
{
if (index >= 10)
{
index = 0;
}
qDebug() << "index: " << index;
pixResource = "res/foo/image/" + QString::number(index) + ".png";
qDebug() << "now the res: " << pixResource;
index++;
}

How to override a signal in qt?

I have a question how to override the signal in Qt?
I have redefined QCheckBox() and changed stateChanged signal.
The project is bilding and working. It does not output in the "application output" errors or messages of the " signal with the slot is not connected"
BUT it doesn't link to the slot. I can't figure out what's wrong.
This code works :
connect(test_checkbox[i], SIGNAL(stateChanged(int)), two_cl , SLOT(run_NEW()));
I need to emit string in addition to the number :
connect(test_checkbox[i], SIGNAL(stateChanged(int, QString)), two_cl , SLOT(run_NEW(int, QString)));
override QCheckBox
.h
#ifndef MYDIMASCHECKBOX_H
#define MYDIMASCHECKBOX_H
#include <QCheckBox>
class MyDimasCheckBox : public QCheckBox
{
Q_OBJECT
public:
MyDimasCheckBox(QWidget *parent =0);
~MyDimasCheckBox();
QString stroka;
signals:
void stateChanged(int, QString);
};
#endif // MYDIMASCHECKBOX_H
.cpp
#include "mydimascheckbox.h"
MyDimasCheckBox::MyDimasCheckBox(QWidget *parent)
{
stroka = "dimasik :3";
emit stateChanged(int(), stroka);
}
MyDimasCheckBox::~MyDimasCheckBox()
{
}
And here is where challenge
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <iostream>
#include <vector>
#include "mydimascheckbox.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
int glob_i ;
int glob_flow;
int vector_schet;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void start_sending(bool);
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QThread *thread = new QThread();
QVector<QThread*> vector_thread;
QList<MyDimasCheckBox*> test_checkbox;
MyDimasCheckBox *checkBox = new MyDimasCheckBox();
QWidget *checkBoxWidget = new QWidget();
QHBoxLayout *layoutCheckBox = new QHBoxLayout(checkBoxWidget);
};
class NewsThread: public QThread
{
Q_OBJECT
public slots:
void run_NEW();
void run_NEW(int, QString);
signals:
void otprawka (int);
};
#endif // MAINWINDOW_H
.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
glob_i=0;
glob_flow =0;
vector_schet =0;
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
test_checkbox.clear();
}
void MainWindow::on_pushButton_clicked()
{
glob_i++;
checkBoxWidget = new QWidget();
checkBox = new MyDimasCheckBox();
layoutCheckBox = new QHBoxLayout(checkBoxWidget);
test_checkbox.append(checkBox);
connect(checkBox, SIGNAL(toggled(bool)),this, SLOT(start_sending(bool)));
checkBox->setText(QString::number(glob_i));
layoutCheckBox->addWidget(checkBox);
layoutCheckBox->setAlignment(Qt::AlignCenter);
layoutCheckBox->setContentsMargins(0,0,0,0);
ui->tW_test->insertRow(ui->tW_test->rowCount());
ui->tW_test->setCellWidget(ui->tW_test->rowCount()-1, 1, checkBoxWidget);
qDebug() << "glob_i: " << glob_i;
}
void MainWindow::start_sending(bool Value)
{
qDebug() << "start_sending " ;
// когда нажата отрабатывает, отжата то не отрабатывает
if (Value == true)
{
NewsThread *two_cl = new NewsThread();
qDebug() << "chekbocks: "<< " TRUE" ;
for (int i =0;i < test_checkbox.length();i++ )
{
if(test_checkbox[i]->isChecked() ==Value)
{
glob_flow++;
// connect(test_checkbox[i], SIGNAL(stateChanged(int)), two_cl , SLOT(run_NEW()));
connect(test_checkbox[i], SIGNAL(stateChanged(int, QString)), two_cl , SLOT(run_NEW(int, QString)));
thread = new QThread();
vector_thread.append(thread);
vector_schet++;
qDebug() << "vector_schet : " << vector_schet ;
two_cl->moveToThread(vector_thread[vector_schet-1]);
vector_thread[vector_schet-1]->start();
}
}
}
else {
qDebug() << "chekbocks:" << " False";
glob_flow--;
qDebug() << "vector_schet : " << vector_schet ;
vector_thread[vector_schet-1]->exit();
}
}
void NewsThread::run_NEW()
{
qDebug() << "run_NEW()";
for(;;){
for (int i=0; i<500; i++){
qDebug()<< "Число :" << i <<"number \"flow\" :" ;
usleep(100000);
}
}
}
void NewsThread::run_NEW(int i, QString str){
qDebug() << "run_NEW(int i, QString str) ";
for(;;){
for (int i=0; i<500; i++){
qDebug() << " i : " << i;
qDebug() << " str : " << str;
qDebug()<< "Число :" << i <<"number \"flow\" :" ;
usleep(100000);
}
}
}
You cannot replace a signal with another signal in a subclass. You can, however, emit an additional signal with the original signal in a self-connected slot:
class MyDimasCheckBox : public QCheckBox
{
Q_OBJECT
public:
MyDimasCheckBox(QWidget *parent =0);
~MyDimasCheckBox();
QString stroka;
private slots:
// Emits the new signal
void doEmitStateChanged(int i);
signals:
void stateChanged(int, QString);
};
MyDimasCheckBox::MyDimasCheckBox(QWidget *parent) : QCheckBox(parent) {
// Connect original signal to slot
connect(this, SIGNAL(stateChanged(int)), this, SLOT(doEmitStateChanged(int)));
}
void MyDimasCheckBox::doEmitStateChanged(int i) {
emit stateChanged(i, stroka);
}
With the new connection syntax, you can omit the slot and use a lambda:
connect(this, qOverload<int>(&QCheckBox::stateChanged),
// "this" context-object for QThread-Affinity
this, [=](int i) { emit this->stateChanged(i, this->stroka); });
Overriding signal is a bad practice [1]:
"APIs with overridden signals are hard to use, unexpected and bug-prone. To make it worse, Qt even allows you to override a signal with a non-signal, and vice-versa."
https://www.kdab.com/nailing-13-signal-slot-mistakes-clazy-1-3/

How to use automatically added Qt-elements

My programm can add new QLabels and QLineEdits to a QScrollArea after a button is clicked. The idea is to create a grocery list. My problem is when a second Button is clicked I want to get the text of all the QLineEdits. But I don't know how to use those elements, because every new QLineEdit-variable has the same name and I don't know how to change that.
Below is a small example:
my MainWindow.h:
#ifndef MainWINDOW_H
#define MainWINDOW_H
#include <QMainWindow>
#include <string>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int i;
private:
Ui::MainWindow *ui;
private slots:
void on_create_clicked();
read_text();
};
#endif // MainWINDOW_H
my MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(on_create_clicked()));
connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(read_text()));
i = 1;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_create_clicked()
{
if(i < 10)
{
i ++;
QLabel *label_2 = new QLabel();
QString s = QString::number(zaehlerHeight) + ". ";
label_2->setText(s);
ui->scrollArea->widget()->layout()->addWidget(label_2);
QLineEdit *lineEdit = new QLineEdit();
ui->scrollArea_2->widget()->layout()->addWidget(lineEdit);
}
else{
ui->label->setText("already 10");
}
}
void MainWindow::read_text()
{
QString mytext = ui->lineEdit->text();
}
I would simply store the pointer to each QLineEdit in a QVector, and then loop in this vector to get the text of each.
Header:
#ifndef MainWINDOW_H
#define MainWINDOW_H
#include <QMainWindow>
#include <string>
#include <QVector>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int i;
private:
Ui::MainWindow *ui;
QVector<QLineEdit *> m_VecLineEdits;
private slots:
void on_create_clicked();
private:
void read_text();
void GetAllTextEdit();
};
#endif // MainWINDOW_H
In Cpp file, change the following:
void MainWindow::on_create_clicked()
{
if(i < 10)
{
i ++;
QLabel *label_2 = new QLabel();
QString s = QString::number(zaehlerHeight) + ". ";
label_2->setText(s);
ui->scrollArea->widget()->layout()->addWidget(label_2);
QLineEdit *lineEdit = new QLineEdit();
m_VecLineEdits.push_back(lineEdit); // <-- Line added here to save the pointers in a QVector.
ui->scrollArea_2->widget()->layout()->addWidget(lineEdit);
}
else{
ui->label->setText("already 10");
}
}
void MainWindow::GetAllTextEdit()
{
for(int j = 0; j<m_VecLineEdits.size(); ++j)
{
QString lineEditText = m_VecLineEdits.at(j)->text();
/* Do anything with this value */
}
}
If you delete your QLineEdit, remember to also remove them from the QVector.
If you want to change the name of the variable ( ie the pointer to the QLineEdit ) each time you slot is called, and provided that i will stay small ( < 10 ), you can use switch(i) for example and choose a different variable name for each case, but you will have to store all those variables as members of your class. So it's better to store the pointers in a QList or a QVector and loop over those containers to access the text() method on each QLineEdit.
you can't, because you don't have any pointer or reference to those objects, one solution would be having a array of QLabel in your class definition.
ex:
QVector<QLabel*> _labels;
and adding and instantiating one by one with the press of the button and then you will have the whole list of objects, thus their names