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 Handling of Hundreds of UI elements
QtWS25 Last Chance

Dynamic Handling of Hundreds of UI elements

Scheduled Pinned Locked Moved Unsolved General and Desktop
ui object
16 Posts 4 Posters 4.8k 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.
  • M Offline
    M Offline
    mrsurge
    wrote on 8 Feb 2016, 00:12 last edited by
    #1

    Ok so here is what I've got... doubleSpinBox - doubleSpinBox_312. I made them all read only, I only want them the to be edited from within 1 dialog. Ive made one of them clickable through an eventFilter:

    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->doubleSpinBox->installEventFilter(this);
        QObjectList o_list = ui->doubleSpinBox->children();
        for(int i = 0; i < o_list.length(); i++)
        {
            QLineEdit *cast = qobject_cast<QLineEdit*>(o_list[i]);
            if(cast)
                cast->installEventFilter(this);
        }
    
    }
    
    

    and

    
    bool MainWindow::eventFilter(QObject *obj, QEvent *event)
    {
        if(event->type() == QEvent::MouseButtonPress)
        {
            Dialog mdialog;
            mdialog.setModal(true);
            mdialog.exec();
        }
        return false;
    }
    
    

    I am wondering if its possible to automate this part

    ui->doubleSpinBox->installEventFilter(this);
          //~~~~~~~~^
    QObjectList o_list = ui->doubleSpinBox->children();
                              // ~~~~~~~~^
    

    and to make sure I can return a value to a function that corresponds to what spinbox has been selected so that the dialog can return the new value to the appropriate field.

    I really like the parameters and the look that the spinbox with no arrows gives so that's how I arrived at this juncture. Perhaps this more a C++ question than a Qt question, in any event IDK cause I'm a n00b.

    Qt 5

    preemptive thank you

    1 Reply Last reply
    0
    • J Offline
      J Offline
      JordanHarris
      wrote on 8 Feb 2016, 05:47 last edited by
      #2

      I can't really think of any way to do this unless you stored them all in a container so you could iterate over the container and apply the operations to all of them. I can't see a way of doing that without manually adding them to a container since you're using the UI designer, which defeats the point. If you created them in code, you could create them in a loop and store a pointer to them in a container or something.

      Maybe there's a way to get a list of all child widgets that you can iterate over and test of they are the type of widget you're wanting. Not too sure about that. Maybe someone will have an answer.

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 8 Feb 2016, 13:15 last edited by kshegunov 2 Aug 2016, 14:10
        #3

        @mrsurge
        Hello,
        For one you could make Qt do the casting for you:

        QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>();
        foreach (QLineEdit * item, list)
            item->installEventFilter(this);
        

        And then in your event filter you could connect the dialog's accepted signal to the line edit:

        bool MainWindow::eventFilter(QObject * obj, QEvent * event)
        {
            if(event->type() == QEvent::MouseButtonPress)
            {
                Dialog mdialog;
        
                QSignalMapper mapper(&mdialog);
                mapper.setMapping(qobject_cast<QWidget *>(obj));
                QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map()));
                QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *)));
        
                mdialog.exec();
            }
            return false;
        }
        
        void MainWindow::saveDataToLineEdit(QWidget * widget)
        {
            QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget);
            Dialog * dialog = qobject_cast<Dialog *>(sender()->parent());
            // ... Transfer data between the dialog and the line edit here ...
        }
        

        Is this what you were asking for?

        Kind regards.

        EDIT:
        I've moved the mapper to the stack, as it's not necessary to create it with new (since you're using a modal dialog).

        Read and abide by the Qt Code of Conduct

        M 1 Reply Last reply 9 Feb 2016, 05:19
        1
        • M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 8 Feb 2016, 13:43 last edited by
          #4

          also be sure to check
          http://www.qtcentre.org/threads/65146-Dynamic-Handling-of-Hundreds-of-UI-elements

          1 Reply Last reply
          0
          • K kshegunov
            8 Feb 2016, 13:15

            @mrsurge
            Hello,
            For one you could make Qt do the casting for you:

            QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>();
            foreach (QLineEdit * item, list)
                item->installEventFilter(this);
            

            And then in your event filter you could connect the dialog's accepted signal to the line edit:

            bool MainWindow::eventFilter(QObject * obj, QEvent * event)
            {
                if(event->type() == QEvent::MouseButtonPress)
                {
                    Dialog mdialog;
            
                    QSignalMapper mapper(&mdialog);
                    mapper.setMapping(qobject_cast<QWidget *>(obj));
                    QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map()));
                    QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *)));
            
                    mdialog.exec();
                }
                return false;
            }
            
            void MainWindow::saveDataToLineEdit(QWidget * widget)
            {
                QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget);
                Dialog * dialog = qobject_cast<Dialog *>(sender()->parent());
                // ... Transfer data between the dialog and the line edit here ...
            }
            

            Is this what you were asking for?

            Kind regards.

            EDIT:
            I've moved the mapper to the stack, as it's not necessary to create it with new (since you're using a modal dialog).

            M Offline
            M Offline
            mrsurge
            wrote on 9 Feb 2016, 05:19 last edited by mrsurge 2 Sept 2016, 05:21
            #5

            @kshegunov

            QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>();
            foreach (QLineEdit * item, list)
                item->installEventFilter(this);
            

            returns

            **error: 'QLineEdit' does not refer to a value
            QList<QLineEdit > list = ui->doubleSpinBox->children<QLineEdit >();

            in my compiler. Remember I may be doing something really stupid, I'm new at qt

            K 1 Reply Last reply 9 Feb 2016, 05:27
            0
            • M mrsurge
              9 Feb 2016, 05:19

              @kshegunov

              QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>();
              foreach (QLineEdit * item, list)
                  item->installEventFilter(this);
              

              returns

              **error: 'QLineEdit' does not refer to a value
              QList<QLineEdit > list = ui->doubleSpinBox->children<QLineEdit >();

              in my compiler. Remember I may be doing something really stupid, I'm new at qt

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 9 Feb 2016, 05:27 last edited by
              #6

              @mrsurge
              No, the problem is with my code, it happens sometimes when I don't double-check my examples. The proper function to use would be QObject::findChildren. I usually use it similarly to this:

              QList<QLineEdit *> list = ui->doubleSpinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
              

              This should compile fine.

              Kind regards.

              Read and abide by the Qt Code of Conduct

              M 1 Reply Last reply 9 Feb 2016, 06:14
              0
              • K kshegunov
                9 Feb 2016, 05:27

                @mrsurge
                No, the problem is with my code, it happens sometimes when I don't double-check my examples. The proper function to use would be QObject::findChildren. I usually use it similarly to this:

                QList<QLineEdit *> list = ui->doubleSpinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                

                This should compile fine.

                Kind regards.

                M Offline
                M Offline
                mrsurge
                wrote on 9 Feb 2016, 06:14 last edited by mrsurge 2 Sept 2016, 06:15
                #7

                @kshegunov
                your right that did compile just fine, but it only works for doubleSpinBox not doubleSpinBox_2 - doubleSpinBox_312

                K 1 Reply Last reply 9 Feb 2016, 06:25
                0
                • M mrsurge
                  9 Feb 2016, 06:14

                  @kshegunov
                  your right that did compile just fine, but it only works for doubleSpinBox not doubleSpinBox_2 - doubleSpinBox_312

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 9 Feb 2016, 06:25 last edited by kshegunov 2 Sept 2016, 06:28
                  #8

                  @mrsurge

                  Just apply the same principle:

                  MainWindow::MainWindow(QWidget *parent)
                      : QMainWindow(parent), ui(new Ui::MainWindow)
                  {
                      ui->setupUi(this);
                  
                      QList<QSpinBox *> sbList = findChildren<QSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
                      foreach (QSpinBox * spinBox, sbList)  {
                              spinBox->installEventFilter(this);  //< Do you need this??
                  
                              QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                              foreach (QLineEdit * lineEdit, leList)
                                  lineEdit->installEventFilter(this);
                      }
                  }
                  

                  Read and abide by the Qt Code of Conduct

                  M 1 Reply Last reply 9 Feb 2016, 18:41
                  1
                  • K kshegunov
                    9 Feb 2016, 06:25

                    @mrsurge

                    Just apply the same principle:

                    MainWindow::MainWindow(QWidget *parent)
                        : QMainWindow(parent), ui(new Ui::MainWindow)
                    {
                        ui->setupUi(this);
                    
                        QList<QSpinBox *> sbList = findChildren<QSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
                        foreach (QSpinBox * spinBox, sbList)  {
                                spinBox->installEventFilter(this);  //< Do you need this??
                    
                                QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                                foreach (QLineEdit * lineEdit, leList)
                                    lineEdit->installEventFilter(this);
                        }
                    }
                    
                    M Offline
                    M Offline
                    mrsurge
                    wrote on 9 Feb 2016, 18:41 last edited by mrsurge 2 Sept 2016, 18:46
                    #9

                    @kshegunov
                    This worked :

                    QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString());
                    foreach (QDoubleSpinBox * spinBox, sbList)  {
                                //spinBox->installEventFilter(this);  //< Do you need this??//<-no I don't
                    
                       QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                       foreach (QLineEdit * lineEdit, leList)
                                    lineEdit->installEventFilter(this);
                    }
                    

                    many thanks for steering me in the right direction.

                    now on to saving the item to the specific line item

                    K 1 Reply Last reply 9 Feb 2016, 18:54
                    0
                    • M mrsurge
                      9 Feb 2016, 18:41

                      @kshegunov
                      This worked :

                      QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString());
                      foreach (QDoubleSpinBox * spinBox, sbList)  {
                                  //spinBox->installEventFilter(this);  //< Do you need this??//<-no I don't
                      
                         QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                         foreach (QLineEdit * lineEdit, leList)
                                      lineEdit->installEventFilter(this);
                      }
                      

                      many thanks for steering me in the right direction.

                      now on to saving the item to the specific line item

                      K Offline
                      K Offline
                      kshegunov
                      Moderators
                      wrote on 9 Feb 2016, 18:54 last edited by
                      #10

                      @mrsurge
                      Yes, of course, I forgot we're in a main window. Anyway, I'm glad it worked. One note, though, if possible use the QObject::findChildren with Qt::FindDirectChildrenOnly so Qt will not go about recursively looking for all. If your spin boxes are in layouts, but not inside other widgets, this should also work:

                      QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
                      

                      Kind regards.

                      Read and abide by the Qt Code of Conduct

                      M 1 Reply Last reply 9 Feb 2016, 23:18
                      0
                      • K kshegunov
                        9 Feb 2016, 18:54

                        @mrsurge
                        Yes, of course, I forgot we're in a main window. Anyway, I'm glad it worked. One note, though, if possible use the QObject::findChildren with Qt::FindDirectChildrenOnly so Qt will not go about recursively looking for all. If your spin boxes are in layouts, but not inside other widgets, this should also work:

                        QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
                        

                        Kind regards.

                        M Offline
                        M Offline
                        mrsurge
                        wrote on 9 Feb 2016, 23:18 last edited by
                        #11

                        @kshegunov

                        ok now how do I return a value from the dialog box to the doubleSpinBox that was clicked?

                        K 1 Reply Last reply 9 Feb 2016, 23:25
                        0
                        • M mrsurge
                          9 Feb 2016, 23:18

                          @kshegunov

                          ok now how do I return a value from the dialog box to the doubleSpinBox that was clicked?

                          K Offline
                          K Offline
                          kshegunov
                          Moderators
                          wrote on 9 Feb 2016, 23:25 last edited by
                          #12

                          @mrsurge
                          I've provided some guidelines here.
                          If this is working,

                          QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                          

                          then the line edit has a QSpinBox for a parent. You have the line edit that'd been clicked here:

                          void MainWindow::saveDataToLineEdit(QWidget * widget)
                          {
                              QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget);
                              // ... Then the line edit parent is ...
                              QSpinBox * spinBox = qobject_cast<QSpinBox *>(lineEdit->parent());
                              // ... and so on ...
                          }
                          

                          Read and abide by the Qt Code of Conduct

                          M 1 Reply Last reply 9 Feb 2016, 23:43
                          0
                          • K kshegunov
                            9 Feb 2016, 23:25

                            @mrsurge
                            I've provided some guidelines here.
                            If this is working,

                            QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
                            

                            then the line edit has a QSpinBox for a parent. You have the line edit that'd been clicked here:

                            void MainWindow::saveDataToLineEdit(QWidget * widget)
                            {
                                QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget);
                                // ... Then the line edit parent is ...
                                QSpinBox * spinBox = qobject_cast<QSpinBox *>(lineEdit->parent());
                                // ... and so on ...
                            }
                            
                            M Offline
                            M Offline
                            mrsurge
                            wrote on 9 Feb 2016, 23:43 last edited by mrsurge 2 Sept 2016, 23:43
                            #13

                            @kshegunov said:

                            bool MainWindow::eventFilter(QObject * obj, QEvent * event)
                            {
                            if(event->type() == QEvent::MouseButtonPress)
                            {
                            Dialog mdialog;

                                QSignalMapper mapper(&mdialog);
                                mapper.setMapping(qobject_cast<QWidget *>(obj));
                                QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map()));
                                QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *)));
                            
                                mdialog.exec();
                            }
                            return false;
                            

                            }

                            my compiler says

                            mapper.setMapping(qobject_cast<QWidget *>(obj));
                            

                            requires a second argument

                            mapper.setMapping(qobject_cast<QWidget *>(obj),0);
                            

                            works but i have no idea what thats doing

                            K 1 Reply Last reply 9 Feb 2016, 23:59
                            0
                            • M mrsurge
                              9 Feb 2016, 23:43

                              @kshegunov said:

                              bool MainWindow::eventFilter(QObject * obj, QEvent * event)
                              {
                              if(event->type() == QEvent::MouseButtonPress)
                              {
                              Dialog mdialog;

                                  QSignalMapper mapper(&mdialog);
                                  mapper.setMapping(qobject_cast<QWidget *>(obj));
                                  QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map()));
                                  QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *)));
                              
                                  mdialog.exec();
                              }
                              return false;
                              

                              }

                              my compiler says

                              mapper.setMapping(qobject_cast<QWidget *>(obj));
                              

                              requires a second argument

                              mapper.setMapping(qobject_cast<QWidget *>(obj),0);
                              

                              works but i have no idea what thats doing

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 9 Feb 2016, 23:59 last edited by
                              #14

                              @mrsurge
                              Yes, I forgot the sender. That should be:

                              mapper.setMapping(&mdialog, qobject_cast<QWidget *>(obj));
                              

                              QSignalMapper is a simple utility class to provide mapping of signals without parameters to signals/slots with a single parameter. This is done, because QDialog::accepted has no notion of the QLineEdit that triggers the event filter, so what the line does is simply to remap the signal to a slot that accepts the QLineEdit object as a parameter.

                              Kind regards.

                              Read and abide by the Qt Code of Conduct

                              M 1 Reply Last reply 13 Feb 2016, 04:03
                              0
                              • K kshegunov
                                9 Feb 2016, 23:59

                                @mrsurge
                                Yes, I forgot the sender. That should be:

                                mapper.setMapping(&mdialog, qobject_cast<QWidget *>(obj));
                                

                                QSignalMapper is a simple utility class to provide mapping of signals without parameters to signals/slots with a single parameter. This is done, because QDialog::accepted has no notion of the QLineEdit that triggers the event filter, so what the line does is simply to remap the signal to a slot that accepts the QLineEdit object as a parameter.

                                Kind regards.

                                M Offline
                                M Offline
                                mrsurge
                                wrote on 13 Feb 2016, 04:03 last edited by
                                #15

                                @kshegunov

                                Ok I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?

                                K 1 Reply Last reply 13 Feb 2016, 09:20
                                0
                                • M mrsurge
                                  13 Feb 2016, 04:03

                                  @kshegunov

                                  Ok I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?

                                  K Offline
                                  K Offline
                                  kshegunov
                                  Moderators
                                  wrote on 13 Feb 2016, 09:20 last edited by
                                  #16

                                  @mrsurge
                                  Hello,

                                  Ok I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?

                                  It shouldn't matter how you initialize the dialog, provided you call QDialog::accept() at the appropriate place, i.e. when a save/ok button is clicked.

                                  Kind regards.

                                  Read and abide by the Qt Code of Conduct

                                  1 Reply Last reply
                                  0

                                  1/16

                                  8 Feb 2016, 00:12

                                  • Login

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