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. Qt Sqlite loading data to QComboBox slow and freeze for seconds

Qt Sqlite loading data to QComboBox slow and freeze for seconds

Scheduled Pinned Locked Moved Solved General and Desktop
qt 6.0.2sqlite datebaseqcombobox
11 Posts 3 Posters 1.1k 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.
  • P Proton Phoenix

    i have a problem with loading specified data from sqlite table to QComboBox , it's really very slow and freeze the software screen for 3 to 5 second until it gets the specified data

    alt text

    the first right button this is the code of it's button

    void facture::on_loadbuyer_clicked()
    {
         facture conn3; // an object ...
               // creating a a Query object (pointer)
               QSqlQueryModel * model = new QSqlQueryModel();
               // opening the connection again
               conn3.DOpen(); // this is a function inside header file used for opening SQLITE Connection
               QSqlQuery* qry=new QSqlQuery(conn3.db);
                qry->prepare("SELECT Name FROM customers");
               qry->exec();
               model->setQuery(*qry);
               ui->nameofbuyercombobox_1->setModel(model);
    }
    

    and the second button this is it's code :

    void facture::on_loaddatabasebutton_5_clicked()
    {
        facture conn4;
           // creating a a Query object (pointer)
           QSqlQueryModel * model = new QSqlQueryModel();
           // opening the connection again
           conn4.conOpen();
           QSqlQuery* qry=new QSqlQuery(conn4.db);
            qry->prepare("SELECT Name_Products FROM product");
           qry->exec();
           qry->lastError();
           model->setQuery(*qry);
           ui->comboBox_1->setModel(model);
    }
    

    then using slots of Combobox to show barcode and Name_Products Price (related to button which is in the center) this is the code :

    void facture::on_comboBox_1_currentIndexChanged(int index)
    {
        QSqlQuery qry(db);
        QString search = ui->comboBox_1->currentText();
            qry.prepare("SELECT * FROM product WHERE (Name_Products = '"+search+"') ");
            if(qry.exec()){
                while (qry.next()){
             qDebug() << qry.lastError();
             ui->barcode_1->setValue(qry.value(0).toInt());
             ui->comboBox_1->setCurrentText(qry.value(1).toString());
             ui->priceofbuy_1->setValue(qry.value(3).toFloat());
    
    }
            }
    }
    

    my problem the data load correctly but very slow really very slow from 3 to 6 seconds to load 10 of data to QComboBox My pc : i3 4160 with 12 gb ram ddr3

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #2

    @Proton-Phoenix

    • Remove the combo box from your timings, and verify what is going on just executing the queries without that complication.
    • Why are you creating new models/connections each time? Try with an existing model & connection and see if that explains the overhead.
    P 1 Reply Last reply
    1
    • JonBJ JonB

      @Proton-Phoenix

      • Remove the combo box from your timings, and verify what is going on just executing the queries without that complication.
      • Why are you creating new models/connections each time? Try with an existing model & connection and see if that explains the overhead.
      P Offline
      P Offline
      Proton Phoenix
      wrote on last edited by Proton Phoenix
      #3

      @JonB said in Qt Sqlite loading data to QComboBox slow and freeze for seconds:

      your

      //
      alt text
      after removing comboBox from my timings code just clicking to the right button (loadbuyer) will freeze the software for 3 to 6 until it back!
      about Why are you creating new models/connections each time? Try with an existing model & connection and see if that explains the overhead.
      i have just 6 month QT experience i still a beginner in connections that's why i am using new models connections each time
      but in this situation i removed all slots ... only the button right and the center one works (two buttons with two combobox
      -- remark if i remove the stylesheet .. it became faster about 3 seconds .....
      is there any solution?

      artwawA 1 Reply Last reply
      0
      • P Proton Phoenix

        @JonB said in Qt Sqlite loading data to QComboBox slow and freeze for seconds:

        your

        //
        alt text
        after removing comboBox from my timings code just clicking to the right button (loadbuyer) will freeze the software for 3 to 6 until it back!
        about Why are you creating new models/connections each time? Try with an existing model & connection and see if that explains the overhead.
        i have just 6 month QT experience i still a beginner in connections that's why i am using new models connections each time
        but in this situation i removed all slots ... only the button right and the center one works (two buttons with two combobox
        -- remark if i remove the stylesheet .. it became faster about 3 seconds .....
        is there any solution?

        artwawA Offline
        artwawA Offline
        artwaw
        wrote on last edited by
        #4

        @Proton-Phoenix Hi. In my opinion there are multiple not very efficient approaches. Let's try to sort this out:

        1. if I understood parts of your code correctly you introduce new connection (with opening and such) after each push of the button. That is not necessary! One connection is sufficient. Try to init your db default connection in the constructor of the main class, for the ease of example:
        auto db = QSqlDatabase::addDatabase('QSQLite');
        db.setDatabaseName('path_to_your_db_file');
        if (!db.open()) {
            //here what you want to do if file cannot be open
        }
        

        After successfully opening the database you have permanent (let's say) default connection that can be reused.
        If I understand your code correctly you are not using threads for interactions with your UI so that should really suffice.
        Please also note that db above should not be stored as a member of any class, it can safely go out of the scope.

        1. Models. For some reason you are using QSqlQuery, which is very primitive for your purpose. I'd suggest using QSqlTableModel - a class that will automate quite a bit for you. As the name suggests you can go with one model per table. So let's assume that in your header file you've got:
        QSqlTableModel *customersModel;
        QSqlTableModel *productModel;
        

        Now somewhere in your code you need to initialise those models. Again, this needs to be done only once so if you place the code just after opening db connection you can reuse db. Otherwise you'll need to recall the default connection which can be easily done with auto db = QSqlDatabase::database(true);

        customersModel = new QSqlTableModel(this,db);
        customersModel->setTable('customers');
        customerModel->select(); //here the model is populated with data;
        productModel = new QSqlTableModel(this,db);
        productModel->setTable('product');
        productModel->select();
        

        Now - how to apply that to your UI? Let's take your first method:

        ui->nameofbuyercombobox_1->setModel(customersModel);
        ui->nameofbuyercombobox_1->setModelColumn(number_of_column_with_customer_name); //please note that columns numbering starts with zero
        

        And that is mostly it. For starters.

        1. The slot for combo box index changed signal:
          it is usually faster (although requires a bit more work on your side) to utilise QSortFilterProxyModel - you connect it between your model (in our test case here it would be productModel) and the view. The documentation describes exactly the kind of filtering you need to I am leaving it for you to have some fun.
          Why this way? Well, for starters you don't call the query every single time someone types the character in the filter. It all happens in the memory, time saving can be enormous.
          Secondly, select '*' returns unsorted results, with this model you can have nice user experience.
          And, lastly, the whole codebase is easier to read I think.
          Anyway, that is how I would approach your problems.

        For more information please re-read.

        Kind Regards,
        Artur

        P 2 Replies Last reply
        4
        • artwawA artwaw

          @Proton-Phoenix Hi. In my opinion there are multiple not very efficient approaches. Let's try to sort this out:

          1. if I understood parts of your code correctly you introduce new connection (with opening and such) after each push of the button. That is not necessary! One connection is sufficient. Try to init your db default connection in the constructor of the main class, for the ease of example:
          auto db = QSqlDatabase::addDatabase('QSQLite');
          db.setDatabaseName('path_to_your_db_file');
          if (!db.open()) {
              //here what you want to do if file cannot be open
          }
          

          After successfully opening the database you have permanent (let's say) default connection that can be reused.
          If I understand your code correctly you are not using threads for interactions with your UI so that should really suffice.
          Please also note that db above should not be stored as a member of any class, it can safely go out of the scope.

          1. Models. For some reason you are using QSqlQuery, which is very primitive for your purpose. I'd suggest using QSqlTableModel - a class that will automate quite a bit for you. As the name suggests you can go with one model per table. So let's assume that in your header file you've got:
          QSqlTableModel *customersModel;
          QSqlTableModel *productModel;
          

          Now somewhere in your code you need to initialise those models. Again, this needs to be done only once so if you place the code just after opening db connection you can reuse db. Otherwise you'll need to recall the default connection which can be easily done with auto db = QSqlDatabase::database(true);

          customersModel = new QSqlTableModel(this,db);
          customersModel->setTable('customers');
          customerModel->select(); //here the model is populated with data;
          productModel = new QSqlTableModel(this,db);
          productModel->setTable('product');
          productModel->select();
          

          Now - how to apply that to your UI? Let's take your first method:

          ui->nameofbuyercombobox_1->setModel(customersModel);
          ui->nameofbuyercombobox_1->setModelColumn(number_of_column_with_customer_name); //please note that columns numbering starts with zero
          

          And that is mostly it. For starters.

          1. The slot for combo box index changed signal:
            it is usually faster (although requires a bit more work on your side) to utilise QSortFilterProxyModel - you connect it between your model (in our test case here it would be productModel) and the view. The documentation describes exactly the kind of filtering you need to I am leaving it for you to have some fun.
            Why this way? Well, for starters you don't call the query every single time someone types the character in the filter. It all happens in the memory, time saving can be enormous.
            Secondly, select '*' returns unsorted results, with this model you can have nice user experience.
            And, lastly, the whole codebase is easier to read I think.
            Anyway, that is how I would approach your problems.
          P Offline
          P Offline
          Proton Phoenix
          wrote on last edited by
          #5

          @artwaw Really Thank you bro <3 i will try that i am sure it will work ^^
          you understand my code very well i didn't use threads ... etc
          <3

          artwawA 1 Reply Last reply
          0
          • P Proton Phoenix

            @artwaw Really Thank you bro <3 i will try that i am sure it will work ^^
            you understand my code very well i didn't use threads ... etc
            <3

            artwawA Offline
            artwawA Offline
            artwaw
            wrote on last edited by
            #6

            @Proton-Phoenix Always happy to help. Also, your code might benefit from using this class https://doc.qt.io/qt-5/qdatawidgetmapper.html#details - but can easily go without it too. Sometimes it is just easier to manage connections between models and multiple widgets that way.

            For more information please re-read.

            Kind Regards,
            Artur

            P 1 Reply Last reply
            3
            • artwawA artwaw

              @Proton-Phoenix Always happy to help. Also, your code might benefit from using this class https://doc.qt.io/qt-5/qdatawidgetmapper.html#details - but can easily go without it too. Sometimes it is just easier to manage connections between models and multiple widgets that way.

              P Offline
              P Offline
              Proton Phoenix
              wrote on last edited by
              #7

              @artwaw said in Qt Sqlite loading data to QComboBox slow and freeze for seconds:

              @Proton-Phoenix Always happy to help. Also, your code might benefit from using this class https://doc.qt.io/qt-5/qdatawidgetmapper.html#details - but can easily go without it too. Sometimes it is just easier to manage connections between models and multiple widgets that way.

              really thank you for your great help bro <3 , notice i have ask this question in many famous sites .... stack.... no one found the solution exception you ... really many thanks <3

              1 Reply Last reply
              0
              • artwawA artwaw

                @Proton-Phoenix Hi. In my opinion there are multiple not very efficient approaches. Let's try to sort this out:

                1. if I understood parts of your code correctly you introduce new connection (with opening and such) after each push of the button. That is not necessary! One connection is sufficient. Try to init your db default connection in the constructor of the main class, for the ease of example:
                auto db = QSqlDatabase::addDatabase('QSQLite');
                db.setDatabaseName('path_to_your_db_file');
                if (!db.open()) {
                    //here what you want to do if file cannot be open
                }
                

                After successfully opening the database you have permanent (let's say) default connection that can be reused.
                If I understand your code correctly you are not using threads for interactions with your UI so that should really suffice.
                Please also note that db above should not be stored as a member of any class, it can safely go out of the scope.

                1. Models. For some reason you are using QSqlQuery, which is very primitive for your purpose. I'd suggest using QSqlTableModel - a class that will automate quite a bit for you. As the name suggests you can go with one model per table. So let's assume that in your header file you've got:
                QSqlTableModel *customersModel;
                QSqlTableModel *productModel;
                

                Now somewhere in your code you need to initialise those models. Again, this needs to be done only once so if you place the code just after opening db connection you can reuse db. Otherwise you'll need to recall the default connection which can be easily done with auto db = QSqlDatabase::database(true);

                customersModel = new QSqlTableModel(this,db);
                customersModel->setTable('customers');
                customerModel->select(); //here the model is populated with data;
                productModel = new QSqlTableModel(this,db);
                productModel->setTable('product');
                productModel->select();
                

                Now - how to apply that to your UI? Let's take your first method:

                ui->nameofbuyercombobox_1->setModel(customersModel);
                ui->nameofbuyercombobox_1->setModelColumn(number_of_column_with_customer_name); //please note that columns numbering starts with zero
                

                And that is mostly it. For starters.

                1. The slot for combo box index changed signal:
                  it is usually faster (although requires a bit more work on your side) to utilise QSortFilterProxyModel - you connect it between your model (in our test case here it would be productModel) and the view. The documentation describes exactly the kind of filtering you need to I am leaving it for you to have some fun.
                  Why this way? Well, for starters you don't call the query every single time someone types the character in the filter. It all happens in the memory, time saving can be enormous.
                  Secondly, select '*' returns unsorted results, with this model you can have nice user experience.
                  And, lastly, the whole codebase is easier to read I think.
                  Anyway, that is how I would approach your problems.
                P Offline
                P Offline
                Proton Phoenix
                wrote on last edited by
                #8

                @artwaw said in Qt Sqlite loading data to QComboBox slow and freeze for seconds:

                @Proton-Phoenix Hi. In my opinion there are multiple not very efficient approaches. Let's try to sort this out:

                1. if I understood parts of your code correctly you introduce new connection (with opening and such) after each push of the button. That is not necessary! One connection is sufficient. Try to init your db default connection in the constructor of the main class, for the ease of example:
                auto db = QSqlDatabase::addDatabase('QSQLite');
                db.setDatabaseName('path_to_your_db_file');
                if (!db.open()) {
                    //here what you want to do if file cannot be open
                }
                

                After successfully opening the database you have permanent (let's say) default connection that can be reused.
                If I understand your code correctly you are not using threads for interactions with your UI so that should really suffice.
                Please also note that db above should not be stored as a member of any class, it can safely go out of the scope.

                1. Models. For some reason you are using QSqlQuery, which is very primitive for your purpose. I'd suggest using QSqlTableModel - a class that will automate quite a bit for you. As the name suggests you can go with one model per table. So let's assume that in your header file you've got:
                QSqlTableModel *customersModel;
                QSqlTableModel *productModel;
                

                Now somewhere in your code you need to initialise those models. Again, this needs to be done only once so if you place the code just after opening db connection you can reuse db. Otherwise you'll need to recall the default connection which can be easily done with auto db = QSqlDatabase::database(true);

                customersModel = new QSqlTableModel(this,db);
                customersModel->setTable('customers');
                customerModel->select(); //here the model is populated with data;
                productModel = new QSqlTableModel(this,db);
                productModel->setTable('product');
                productModel->select();
                

                Now - how to apply that to your UI? Let's take your first method:

                ui->nameofbuyercombobox_1->setModel(customersModel);
                ui->nameofbuyercombobox_1->setModelColumn(number_of_column_with_customer_name); //please note that columns numbering starts with zero
                

                And that is mostly it. For starters.

                1. The slot for combo box index changed signal:
                  it is usually faster (although requires a bit more work on your side) to utilise QSortFilterProxyModel - you connect it between your model (in our test case here it would be productModel) and the view. The documentation describes exactly the kind of filtering you need to I am leaving it for you to have some fun.
                  Why this way? Well, for starters you don't call the query every single time someone types the character in the filter. It all happens in the memory, time saving can be enormous.
                  Secondly, select '*' returns unsorted results, with this model you can have nice user experience.
                  And, lastly, the whole codebase is easier to read I think.
                  Anyway, that is how I would approach your problems.

                after trying this , it works really very fast now , many thanks bro <3

                artwawA 1 Reply Last reply
                1
                • P Proton Phoenix

                  @artwaw said in Qt Sqlite loading data to QComboBox slow and freeze for seconds:

                  @Proton-Phoenix Hi. In my opinion there are multiple not very efficient approaches. Let's try to sort this out:

                  1. if I understood parts of your code correctly you introduce new connection (with opening and such) after each push of the button. That is not necessary! One connection is sufficient. Try to init your db default connection in the constructor of the main class, for the ease of example:
                  auto db = QSqlDatabase::addDatabase('QSQLite');
                  db.setDatabaseName('path_to_your_db_file');
                  if (!db.open()) {
                      //here what you want to do if file cannot be open
                  }
                  

                  After successfully opening the database you have permanent (let's say) default connection that can be reused.
                  If I understand your code correctly you are not using threads for interactions with your UI so that should really suffice.
                  Please also note that db above should not be stored as a member of any class, it can safely go out of the scope.

                  1. Models. For some reason you are using QSqlQuery, which is very primitive for your purpose. I'd suggest using QSqlTableModel - a class that will automate quite a bit for you. As the name suggests you can go with one model per table. So let's assume that in your header file you've got:
                  QSqlTableModel *customersModel;
                  QSqlTableModel *productModel;
                  

                  Now somewhere in your code you need to initialise those models. Again, this needs to be done only once so if you place the code just after opening db connection you can reuse db. Otherwise you'll need to recall the default connection which can be easily done with auto db = QSqlDatabase::database(true);

                  customersModel = new QSqlTableModel(this,db);
                  customersModel->setTable('customers');
                  customerModel->select(); //here the model is populated with data;
                  productModel = new QSqlTableModel(this,db);
                  productModel->setTable('product');
                  productModel->select();
                  

                  Now - how to apply that to your UI? Let's take your first method:

                  ui->nameofbuyercombobox_1->setModel(customersModel);
                  ui->nameofbuyercombobox_1->setModelColumn(number_of_column_with_customer_name); //please note that columns numbering starts with zero
                  

                  And that is mostly it. For starters.

                  1. The slot for combo box index changed signal:
                    it is usually faster (although requires a bit more work on your side) to utilise QSortFilterProxyModel - you connect it between your model (in our test case here it would be productModel) and the view. The documentation describes exactly the kind of filtering you need to I am leaving it for you to have some fun.
                    Why this way? Well, for starters you don't call the query every single time someone types the character in the filter. It all happens in the memory, time saving can be enormous.
                    Secondly, select '*' returns unsorted results, with this model you can have nice user experience.
                    And, lastly, the whole codebase is easier to read I think.
                    Anyway, that is how I would approach your problems.

                  after trying this , it works really very fast now , many thanks bro <3

                  artwawA Offline
                  artwawA Offline
                  artwaw
                  wrote on last edited by
                  #9

                  @Proton-Phoenix I am happy for you. Please mark the topic as "solved" if you are happy with the outcome.

                  For more information please re-read.

                  Kind Regards,
                  Artur

                  1 Reply Last reply
                  1
                  • P Offline
                    P Offline
                    Proton Phoenix
                    wrote on last edited by Proton Phoenix
                    #10

                    bro <3 <<"artwaw"> after trying this

                    QSqlTableModel *productModel;
                    productModel = new QSqlTableModel(this,db);
                    productModel->setTable("products");
                    productModel->select();
                    QDataWidgetMapper *mapper = new QDataWidgetMapper;
                    mapper->setModel(productModel);
                    mapper->addMapping(ui->barcode_1, 0);
                    mapper->addMapping(ui->comboBox_1, 1);
                    mapper->addMapping(ui->priceofbuy_1, 3);
                    mapper->toFirst();

                    i don't know what i may do without this help from you . you gave me everything i need in small topic <3 i wish happy great life for you bro really thanks

                    artwawA 1 Reply Last reply
                    0
                    • P Proton Phoenix

                      bro <3 <<"artwaw"> after trying this

                      QSqlTableModel *productModel;
                      productModel = new QSqlTableModel(this,db);
                      productModel->setTable("products");
                      productModel->select();
                      QDataWidgetMapper *mapper = new QDataWidgetMapper;
                      mapper->setModel(productModel);
                      mapper->addMapping(ui->barcode_1, 0);
                      mapper->addMapping(ui->comboBox_1, 1);
                      mapper->addMapping(ui->priceofbuy_1, 3);
                      mapper->toFirst();

                      i don't know what i may do without this help from you . you gave me everything i need in small topic <3 i wish happy great life for you bro really thanks

                      artwawA Offline
                      artwawA Offline
                      artwaw
                      wrote on last edited by
                      #11

                      @Proton-Phoenix Thank you!

                      For more information please re-read.

                      Kind Regards,
                      Artur

                      1 Reply Last reply
                      1

                      • Login

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