Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt Creator and other tools
  4. Cloning Widget in TabWidget

Cloning Widget in TabWidget

Scheduled Pinned Locked Moved Unsolved Qt Creator and other tools
5 Posts 3 Posters 331 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    Yassor
    wrote on last edited by Yassor
    #1

    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 !!
    8d1cc404-9fb0-4395-83a5-c76b08dc1d08-image.png

    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

    1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      Don't approach the problem as cloning an existing widget, but rather creating a second instance in the same manner as the first. If the tab content is defined in the same .ui file as the tab widget, extract the content into its own .ui file.

      Asking a question about code? http://eel.is/iso-c++/testcase/

      1 Reply Last reply
      2
      • Y Offline
        Y Offline
        Yassor
        wrote on last edited by Yassor
        #3

        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.

        image.png

        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;
        }
        
        
        JonBJ 1 Reply Last reply
        0
        • Y Yassor

          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.

          image.png

          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;
          }
          
          
          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @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 a QTabWidget, we suggest you create just that page (with its sub-widgets) as its own page/class/.ui file. That can be added onto a QTabWidget 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 call new 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 new Foo), and if you have set things like minimum/maximum constraints in Designer (as opposed to at runtime) that will appear in the new instance.

          1 Reply Last reply
          0
          • Y Offline
            Y Offline
            Yassor
            wrote on last edited by
            #5

            Hi ! It Work perfectly !! Thank you very much !!

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved