Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Dynamic QWidget for QStackedWidget using ID
QtWS25 Last Chance

Dynamic QWidget for QStackedWidget using ID

Scheduled Pinned Locked Moved Unsolved General and Desktop
qstackedwidgetqwidget
8 Posts 3 Posters 1.4k 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.
  • H Offline
    H Offline
    hobbyProgrammer
    wrote on 12 Dec 2019, 15:29 last edited by
    #1

    I have an application with a mainwindow and a stackedwidget.
    I like to create a widget that displays all the information about a formula 1 circuit, but it needs to be dynamic. I don't want to create a widget for each circuit, but I want it to retreive the data from the database using its ID.
    I promoted the first index of the stacked widget to Circuit and already tried this:

    Circuit.h:

        explicit Circuit(int ID,QWidget *parent = nullptr);
    

    Circuit.cpp:

    Circuit::Circuit(int ID, QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Circuit)
    {
        ui->setupUi(this);
    }
    

    but it gives me this error:

    no matching function for call to 'Circuit::Circuit()'
    no matching constructor for initialization of 'Circuit'
    
            page = new Circuit();
            page->setObjectName(QString::fromUtf8("page"));
            stackedWidget->addWidget(page);
    

    Is there anyone who knows what the proper way to do this is?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 12 Dec 2019, 15:56 last edited by mrjj 12 Dec 2019, 15:58
      #2

      @hobbyProgrammer said in Dynamic QWidget for QStackedWidget using ID:

      page = new Circuit();

      Hi
      You have to give it the int in the ctor
      page = new Circuit(666);
      ( ps. do you store it in the Circuit class, the code dont show that at all )

      H 1 Reply Last reply 13 Dec 2019, 11:18
      0
      • M mrjj
        12 Dec 2019, 15:56

        @hobbyProgrammer said in Dynamic QWidget for QStackedWidget using ID:

        page = new Circuit();

        Hi
        You have to give it the int in the ctor
        page = new Circuit(666);
        ( ps. do you store it in the Circuit class, the code dont show that at all )

        H Offline
        H Offline
        hobbyProgrammer
        wrote on 13 Dec 2019, 11:18 last edited by hobbyProgrammer
        #3

        @mrjj Hi, I don't store it yet. I'd like to create a good setup before starting into the actual coding.

        From the MainWindow how do I call this?

            QSqlQuery query(db);
            query.prepare("SELECT DISTINCT(name) FROM circuit WHERE circuit_id = :circuitID");
            query.bindValue(":circuitID", circuitID);
            query.exec();
        
            QSqlQueryModel *model = new QSqlQueryModel();
            model->setQuery(query);
        
            for(int i = 0; i < model->rowCount(); i++)
            {
                QString strCircuitName = model->data(model->index(i,0)).toString();
                const char* charCircuitName = strCircuitName.toStdString().c_str();
                QAction *circuitAct = new QAction(tr(charCircuitName));
                ui->menuCircuits->addAction(circuitAct);
                connect(circuitAct, &QAction::triggered, this, &MainWindow::goToCircuit);
            }
        
        void MainWindow::goToCircuit()
        {
            qDebug() << "circuitID: " << circuitID;
            Circuit *circuit = new Circuit(circuitID);
            ui->stackedWidget->setCurrentWidget(circuit);
        }
        

        When I start the app it goes straight to the page with index 0 (because of the code below, that was causing the error previously).
        Whenever I press either Circuit 1 or Circuit 2, it doesn't seem to do anything. I suspect that my connect isn't the proper way to do this, but how should I do this?

        page = new Circuit(0);
        page->setObjectName(QString::fromUtf8("page"));
        stackedWidget->addWidget(page);
        
        J 1 Reply Last reply 13 Dec 2019, 13:23
        0
        • H hobbyProgrammer
          13 Dec 2019, 11:18

          @mrjj Hi, I don't store it yet. I'd like to create a good setup before starting into the actual coding.

          From the MainWindow how do I call this?

              QSqlQuery query(db);
              query.prepare("SELECT DISTINCT(name) FROM circuit WHERE circuit_id = :circuitID");
              query.bindValue(":circuitID", circuitID);
              query.exec();
          
              QSqlQueryModel *model = new QSqlQueryModel();
              model->setQuery(query);
          
              for(int i = 0; i < model->rowCount(); i++)
              {
                  QString strCircuitName = model->data(model->index(i,0)).toString();
                  const char* charCircuitName = strCircuitName.toStdString().c_str();
                  QAction *circuitAct = new QAction(tr(charCircuitName));
                  ui->menuCircuits->addAction(circuitAct);
                  connect(circuitAct, &QAction::triggered, this, &MainWindow::goToCircuit);
              }
          
          void MainWindow::goToCircuit()
          {
              qDebug() << "circuitID: " << circuitID;
              Circuit *circuit = new Circuit(circuitID);
              ui->stackedWidget->setCurrentWidget(circuit);
          }
          

          When I start the app it goes straight to the page with index 0 (because of the code below, that was causing the error previously).
          Whenever I press either Circuit 1 or Circuit 2, it doesn't seem to do anything. I suspect that my connect isn't the proper way to do this, but how should I do this?

          page = new Circuit(0);
          page->setObjectName(QString::fromUtf8("page"));
          stackedWidget->addWidget(page);
          
          J Offline
          J Offline
          JonB
          wrote on 13 Dec 2019, 13:23 last edited by
          #4

          @hobbyProgrammer
          I'm sorry I don't have time to answer the signal/slot/connect part, you'll perhaps want to use a C++ lambda for that, there are various ways but you need your slot to gain access to which circuit ID the action is for, in some shape or form.

          But I couldn't help noticing:

                  QString strCircuitName = model->data(model->index(i,0)).toString();
                  const char* charCircuitName = strCircuitName.toStdString().c_str();
                  QAction *circuitAct = new QAction(tr(charCircuitName));
          

          You don't want to do it this way. At minimum from docs use:

          Similarly, you can pass a QString to a function that takes a const char * argument using the qPrintable() macro which returns the given QString as a const char *. This is equivalent to calling <QString>.toLocal8Bit().constData().

          Separately

              Circuit *circuit = new Circuit(circuitID);
              ui->stackedWidget->setCurrentWidget(circuit);
          

          https://doc.qt.io/qt-5/qstackedwidget.html#setCurrentWidget

          Sets the current widget to be the specified widget. The new current widget must already be contained in this stacked widget.

          You're going to need a https://doc.qt.io/qt-5/qstackedwidget.html#addWidget.

          H 1 Reply Last reply 17 Dec 2019, 07:57
          1
          • J JonB
            13 Dec 2019, 13:23

            @hobbyProgrammer
            I'm sorry I don't have time to answer the signal/slot/connect part, you'll perhaps want to use a C++ lambda for that, there are various ways but you need your slot to gain access to which circuit ID the action is for, in some shape or form.

            But I couldn't help noticing:

                    QString strCircuitName = model->data(model->index(i,0)).toString();
                    const char* charCircuitName = strCircuitName.toStdString().c_str();
                    QAction *circuitAct = new QAction(tr(charCircuitName));
            

            You don't want to do it this way. At minimum from docs use:

            Similarly, you can pass a QString to a function that takes a const char * argument using the qPrintable() macro which returns the given QString as a const char *. This is equivalent to calling <QString>.toLocal8Bit().constData().

            Separately

                Circuit *circuit = new Circuit(circuitID);
                ui->stackedWidget->setCurrentWidget(circuit);
            

            https://doc.qt.io/qt-5/qstackedwidget.html#setCurrentWidget

            Sets the current widget to be the specified widget. The new current widget must already be contained in this stacked widget.

            You're going to need a https://doc.qt.io/qt-5/qstackedwidget.html#addWidget.

            H Offline
            H Offline
            hobbyProgrammer
            wrote on 17 Dec 2019, 07:57 last edited by
            #5

            @JonB Hi,
            thanks for your help.
            I really need to know how to load these Circuits in the menu dynamically tho. Is there anyone else who might know how to help me?

            I thought it could be done using QSignalMap, but I can't seem to find the solution anywhere

            1 Reply Last reply
            0
            • H Offline
              H Offline
              hobbyProgrammer
              wrote on 17 Dec 2019, 08:25 last edited by
              #6
              This post is deleted!
              1 Reply Last reply
              0
              • H Offline
                H Offline
                hobbyProgrammer
                wrote on 17 Dec 2019, 08:33 last edited by
                #7

                Allright, I got it working. It might not be the most beautiful solution so any feedback on how to improve the code is always welcome, but this is what I got so far:

                void MainWindow::fillCircuitMenu()
                {
                    QSqlQuery query(db);
                    query.prepare("SELECT DISTINCT(name), id FROM circuit WHERE circuit_id = :circuitID");
                    query.bindValue(":circuitID", circuitID);
                    query.exec();
                
                    QSqlQueryModel *model = new QSqlQueryModel();
                    model->setQuery(query);
                
                    for(int i = 0; i < model->rowCount(); i++)
                    {
                        QString strCircuitName = model->data(model->index(i,0)).toString();
                        const char* charCircuitName = strCircuitName.toStdString().c_str();
                
                        QAction *circuitAct = new QAction(tr(charCircuitName));
                        this->circuitID = model->data(model->index(i,1)).toInt();
                        ui->menuCircuits->addAction(circuitAct);
                
                        Circuit *circuit = new Circuit(circuitID);
                        qvCircuitMenu.insert(i, circuit);
                
                        QSignalMapper *signalMapper = new QSignalMapper(this);
                        connect(circuitAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
                        signalMapper->setMapping(circuitAct, circuitID);
                        connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(goToCircuit(int)));
                    }
                }
                
                void MainWindow::goToCircuit(int index)
                {
                    qDebug() << "goToCircuit: " << index;
                    Circuit *circuit = new Circuit(index);
                    ui->stackedWidget->addWidget(circuit);
                    ui->stackedWidget->setCurrentWidget(circuit);
                }
                
                J 1 Reply Last reply 17 Dec 2019, 09:09
                0
                • H hobbyProgrammer
                  17 Dec 2019, 08:33

                  Allright, I got it working. It might not be the most beautiful solution so any feedback on how to improve the code is always welcome, but this is what I got so far:

                  void MainWindow::fillCircuitMenu()
                  {
                      QSqlQuery query(db);
                      query.prepare("SELECT DISTINCT(name), id FROM circuit WHERE circuit_id = :circuitID");
                      query.bindValue(":circuitID", circuitID);
                      query.exec();
                  
                      QSqlQueryModel *model = new QSqlQueryModel();
                      model->setQuery(query);
                  
                      for(int i = 0; i < model->rowCount(); i++)
                      {
                          QString strCircuitName = model->data(model->index(i,0)).toString();
                          const char* charCircuitName = strCircuitName.toStdString().c_str();
                  
                          QAction *circuitAct = new QAction(tr(charCircuitName));
                          this->circuitID = model->data(model->index(i,1)).toInt();
                          ui->menuCircuits->addAction(circuitAct);
                  
                          Circuit *circuit = new Circuit(circuitID);
                          qvCircuitMenu.insert(i, circuit);
                  
                          QSignalMapper *signalMapper = new QSignalMapper(this);
                          connect(circuitAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
                          signalMapper->setMapping(circuitAct, circuitID);
                          connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(goToCircuit(int)));
                      }
                  }
                  
                  void MainWindow::goToCircuit(int index)
                  {
                      qDebug() << "goToCircuit: " << index;
                      Circuit *circuit = new Circuit(index);
                      ui->stackedWidget->addWidget(circuit);
                      ui->stackedWidget->setCurrentWidget(circuit);
                  }
                  
                  J Offline
                  J Offline
                  JonB
                  wrote on 17 Dec 2019, 09:09 last edited by JonB
                  #8

                  @hobbyProgrammer
                  I don't know what is going on here, but I note that for a given circuitID you do two new Circuit(circuitID)s, one in fillCircuitMenu() and another any time slot goToCircuit(int index) is invoked. I don't know if that is correct, no re-use of same Circuit instance?

                  Separately, I don't think there is any need to use deprecated QSignalMapper any longer. You can replace with new signal/slot syntax (you should get away from SIGNAL/SLOT() macros in all new code) plus a lambda. See e.g. https://doc.qt.io/qt-5/qsignalmapper.html#details for an example of this.

                  1 Reply Last reply
                  3

                  5/8

                  17 Dec 2019, 07:57

                  • Login

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