Cloning Widget in TabWidget
-
Hello, I'm trying in this project to make sure to have the same widgets (Qlabel, qspinbox, qdoublespinbox, ...) as traker 1 when I add a new traker (2, 3 or 4 etc.); but I would like each tracker to be independent (perform the calculations independently of the others). Is it possible to do that with this TabWidget? Thank you !
It's for SolarSizingSoftware !!
Each traker also share the same json file where parameter like modul power, Voc, Isc will be populate on Module Technologie selection. It should behave similary to the Mppt Calculator on Victron Energy Website https://www.victronenergy.com/mppt-calculator
-
I tried to do it with this code but it works only for one add tracker, the third and others are always empty. And I think there are duplicate values like on "Azimut" here (valid for all other elements). I did it by Class to avoid object name conflicts but I think it didn't work.
PS: I'm still a beginner on qtcreator cmake.
void QSS::on_Add_Traker_clicked() { int count = ui->tabWidget->count(); QWidget* newTab = new QWidget(); QWidget* templateWidget = ui->tabWidget->widget(0); // Using the first tab as the template if (templateWidget) { createNewInstance(templateWidget, newTab); } ui->tabWidget->addTab(newTab, "Tracker " + QString::number(count + 1)); ui->tabWidget->setCurrentIndex(count); } void QSS::createNewInstance(QWidget* original, QWidget* parent) { const auto& children = original->children(); for (auto* child : children) { QWidget* childWidget = qobject_cast<QWidget*>(child); if (childWidget) { QWidget* newWidget = createWidgetByClass(childWidget, parent); if (newWidget) { newWidget->setGeometry(childWidget->geometry()); newWidget->setVisible(childWidget->isVisible()); newWidget->setObjectName(childWidget->objectName()); // Recursively create new instances of child widgets createNewInstance(childWidget, newWidget); } } } } QWidget* QSS::createWidgetByClass(QWidget* originalWidget, QWidget* parent) { QWidget* newWidget = nullptr; if (auto* label = qobject_cast<QLabel*>(originalWidget)) { newWidget = new QLabel(label->text(), parent); } else if (auto* spinBox = qobject_cast<QSpinBox*>(originalWidget)) { QSpinBox* newSpinBox = new QSpinBox(parent); newSpinBox->setValue(spinBox->value()); newSpinBox->setMinimum(spinBox->minimum()); newSpinBox->setMaximum(spinBox->maximum()); newWidget = newSpinBox; } else if (auto* DspinBox = qobject_cast<QDoubleSpinBox*>(originalWidget)) { QDoubleSpinBox* newDSpinBox = new QDoubleSpinBox(parent); newDSpinBox->setValue(DspinBox->value()); newDSpinBox->setMinimum(DspinBox->minimum()); newDSpinBox->setMaximum(DspinBox->maximum()); newWidget = newDSpinBox; } else if (auto* checkBox = qobject_cast<QCheckBox*>(originalWidget)) { QCheckBox* newCheckBox = new QCheckBox(checkBox->text(), parent); newCheckBox->setChecked(checkBox->isChecked()); newWidget = newCheckBox; } else if (auto* comboBox = qobject_cast<QComboBox*>(originalWidget)) { QComboBox* newComboBox = new QComboBox(parent); for (int i = 0; i < comboBox->count(); ++i) { newComboBox->addItem(comboBox->itemText(i)); } newComboBox->setCurrentIndex(comboBox->currentIndex()); newWidget = newComboBox; } else if (auto* lineEdit = qobject_cast<QLineEdit*>(originalWidget)) { QLineEdit* newLineEdit = new QLineEdit(lineEdit->text(), parent); newWidget = newLineEdit; } else { // If the widget type is not recognized, just create a generic QWidget. newWidget = new QWidget(parent); } newWidget->setGeometry(originalWidget->geometry()); newWidget->setVisible(originalWidget->isVisible()); newWidget->setObjectName(originalWidget->objectName()); return newWidget; }
-
I tried to do it with this code but it works only for one add tracker, the third and others are always empty. And I think there are duplicate values like on "Azimut" here (valid for all other elements). I did it by Class to avoid object name conflicts but I think it didn't work.
PS: I'm still a beginner on qtcreator cmake.
void QSS::on_Add_Traker_clicked() { int count = ui->tabWidget->count(); QWidget* newTab = new QWidget(); QWidget* templateWidget = ui->tabWidget->widget(0); // Using the first tab as the template if (templateWidget) { createNewInstance(templateWidget, newTab); } ui->tabWidget->addTab(newTab, "Tracker " + QString::number(count + 1)); ui->tabWidget->setCurrentIndex(count); } void QSS::createNewInstance(QWidget* original, QWidget* parent) { const auto& children = original->children(); for (auto* child : children) { QWidget* childWidget = qobject_cast<QWidget*>(child); if (childWidget) { QWidget* newWidget = createWidgetByClass(childWidget, parent); if (newWidget) { newWidget->setGeometry(childWidget->geometry()); newWidget->setVisible(childWidget->isVisible()); newWidget->setObjectName(childWidget->objectName()); // Recursively create new instances of child widgets createNewInstance(childWidget, newWidget); } } } } QWidget* QSS::createWidgetByClass(QWidget* originalWidget, QWidget* parent) { QWidget* newWidget = nullptr; if (auto* label = qobject_cast<QLabel*>(originalWidget)) { newWidget = new QLabel(label->text(), parent); } else if (auto* spinBox = qobject_cast<QSpinBox*>(originalWidget)) { QSpinBox* newSpinBox = new QSpinBox(parent); newSpinBox->setValue(spinBox->value()); newSpinBox->setMinimum(spinBox->minimum()); newSpinBox->setMaximum(spinBox->maximum()); newWidget = newSpinBox; } else if (auto* DspinBox = qobject_cast<QDoubleSpinBox*>(originalWidget)) { QDoubleSpinBox* newDSpinBox = new QDoubleSpinBox(parent); newDSpinBox->setValue(DspinBox->value()); newDSpinBox->setMinimum(DspinBox->minimum()); newDSpinBox->setMaximum(DspinBox->maximum()); newWidget = newDSpinBox; } else if (auto* checkBox = qobject_cast<QCheckBox*>(originalWidget)) { QCheckBox* newCheckBox = new QCheckBox(checkBox->text(), parent); newCheckBox->setChecked(checkBox->isChecked()); newWidget = newCheckBox; } else if (auto* comboBox = qobject_cast<QComboBox*>(originalWidget)) { QComboBox* newComboBox = new QComboBox(parent); for (int i = 0; i < comboBox->count(); ++i) { newComboBox->addItem(comboBox->itemText(i)); } newComboBox->setCurrentIndex(comboBox->currentIndex()); newWidget = newComboBox; } else if (auto* lineEdit = qobject_cast<QLineEdit*>(originalWidget)) { QLineEdit* newLineEdit = new QLineEdit(lineEdit->text(), parent); newWidget = newLineEdit; } else { // If the widget type is not recognized, just create a generic QWidget. newWidget = new QWidget(parent); } newWidget->setGeometry(originalWidget->geometry()); newWidget->setVisible(originalWidget->isVisible()); newWidget->setObjectName(originalWidget->objectName()); return newWidget; }
@Yassor
As @jeremy_k wrote, you really don't want to be doing this by creating/copying a widget and all its sub-widgets. Rather in Designer create a widget/.ui
file containing just the widget+sub-widgets you want another instance of. No more and no less than that. If what you want to copy is presently designed as an individual page on aQTabWidget
, we suggest you create just that page (with its sub-widgets) as its own page/class/.ui
file. That can be added onto aQTabWidget
at runtime.If the class is named
Foo
, then all you have to do to create a copy of the design-time widget is to callnew Foo()
at runtime. If you want you could then copy any runtime values across from an existing instance to a new instance, if that is what you want, but you will not need to create new instances of child widgets (they will be in the newFoo
), and if you have set things like minimum/maximum constraints in Designer (as opposed to at runtime) that will appear in the new instance.