Varying time problems dynamically filling a QTableWidget



  • Ok Guys I am really puzzled by this. I wrote a small tool for managing components (stuff like resistors, leds etc.). I use the sql stuff from Qt to query a sqlite database. Components are displayed in a QTableWidget according to a selection from "Location" or "Category". The whole selection stuff works, according to the selection a SQL "WHERE" is created (or not if all is to be displayed).

    Everything works fine except that in a very specific case the filling of the QTableWidget takes a considerable amount of time. Please not: It is NOT the sqlquery which is delaying.

    Please excuse my code mess. Here's the function "updateComponentsTable" I use to refresh my QTableWidget. Line 53-68 show the for loop where the time is lost. I added some debug messages to quickly tell the time.

    First the Debug output: First time updateComponentsTable is called is right after startup. The exact same query is triggered manually a few seconds later. You see the difference of filling the table (the for loop). Initially it takes milliseconds. The second time it takes 24 Seconds. However thats the exact same query, the query itself took like no time. And this only happens when the "WHERE" string is empty, even so thats (imho) totally unrelated to the problem.

    This is confusing me, is there some sort of GUI Race condition, is it a system problem regarding the frequent allocating of new QTableItemWidgets? (We're talking of less than 150 Elements) I put breakpoints at almost every location in my code, at least according to the debugger the prgramm is not doing anything besides filling the table. I don't know how to debug this further.

    Regards
    Christoph

    @Start QTime("10:58:47.610")
    whereString done QTime("10:58:47.610")
    where -> ""
    getTableData done QTime("10:58:47.614") # Elements 129
    setup Table done QTime("10:58:47.632")
    fill Table done QTime("10:58:47.638") count 129

    Start QTime("10:58:49.848")
    whereString done QTime("10:58:49.848")
    where -> ""
    getTableData done QTime("10:58:49.851") # Elements 129
    setup Table done QTime("10:58:49.853")
    fill Table done QTime("10:59:14.427") count 129@

    @// updates main components table regarding WHERE string
    void MainWindow::updateComponentsTable(){

    qDebug() << "\n\n\nStart " << QTime::currentTime();
    
    // which columns are to be used?
    QVector<int> use;
    use << 0 << 1 << 2 << 3 << 8 << 10 << 12;
    
    // where string for categories and locations
    QString where;
    whereStringTree("category_id",ui->tw_categories,where);
    whereStringTree("location_id",ui->tw_locations,where);
    
    qDebug() << "whereString done " << QTime::currentTime() ;
    qDebug() << "  where -> " << where ;
    
    ui->te_where->setText(where);
    
    QVector<QVector<QString>* > * data = new QVector<QVector<QString>* >();
    m_db->getTableData("components",where,data);
    
    qDebug() << "getTableData done " << QTime::currentTime() << " # Elements " << data->count() ;
    
    QMap<int, QString> id_name_locations;
    m_db->getKeyValueMap("locations",id_name_locations);
    
    QMap<int, QString> id_name_categories;
    m_db->getKeyValueMap("categories",id_name_categories);
    
    //--
    ui->l_count->setText(QString("# of Components found: %1").arg(data->count()));
    
    ui->tw_components->clearContents();
    ui->tw_components->setRowCount(data->count());
    ui->tw_components->setColumnCount(use.count());
    
    QStringList h = m_db->getColumnNamesComponents("components");
    QStringList h_;
    for(int i = 0; i < use.count(); i++){
        h_.append(h.at(use.at(i)));
    }
    ui->tw_components->setHorizontalHeaderLabels(h_);
    ui->tw_components->verticalHeader()->setVisible(false);
    ui->tw_components->setSelectionBehavior(QAbstractItemView::SelectRows);
    //--
    
    qDebug() << "setup Table done " << QTime::currentTime() ;
    
    int count = 0;
    int rowmax = data->count();
    
    for(int row = 0; row < rowmax; row++){
        ++count;
        QVector<QString> * rowdata = data->at(row);
        for(int col = 0; col < use.count(); col++){
            if(use.at(col) == 10)
                ui->tw_components->setItem(row, col,
                                           new QTableWidgetItem(id_name_locations[rowdata->at(use.at(col)).toInt()]));
            else if(use.at(col) == 12)
                ui->tw_components->setItem(row, col,
                                           new QTableWidgetItem(id_name_categories[rowdata->at(use.at(col)).toInt()]));
            else
                ui->tw_components->setItem(row, col,
                                           new QTableWidgetItem(rowdata->at(use.at(col))));
    
            //qDebug() << "fill Table done " << QTime::currentTime() << " count " <<  count ;
        }
    }
    
    ui->tw_components->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    
    qDebug() << "fill Table done " << QTime::currentTime() << " count " <<  count ;
    

    }@


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    How often does the time increase happen ?

    Out of curiosity, since you have a database, why not make use of QTableView ?

    From a programming point of view:
    @QVector<QVector<QString>* > * data@
    Why these pointers to QString and QVector ?

    You also have multiple memory leaks here since you never delete anything



  • Hi sorry for the delay

    I am "resUtQ". For some reason i cannot use my account...

    [quote author="SGaist" date="1417822711"]Out of curiosity, since you have a database, why not make use of QTableView ?

    From a programming point of view:
    @QVector<QVector<QString>* > * data@
    Why these pointers to QString and QVector ?

    You also have multiple memory leaks here since you never delete anything[/quote]Totally insensible use of C++. I tend to write C with Classes, not C++ which sometimes leads to nonsense like Vectors of pointers. Anyway it does work, still you are correct pointing out the memory leak. I will fix that ... maybe ;-)

    I found the solution.
    It's totally unrelated to the query, apparantly it comes from whatever happens to the GUI side of QTableWidget when inserting a new element. Looks like inserting to many new Items leads to that kind of problem, I did not investigate further, here is the workaround by (which sounds like a joke) "turning it off an on again" ;-)

    Solution as Pseudocode:
    @QTableWidget::setVisible(false);
    for(...){
    QTableWidget::setItem()
    }
    QTableWidget::setVisible(true);@

    Thanks anyway.
    Christoph


  • Lifetime Qt Champion

    If you insert that much items you should rather consider setUpdatesEnable that will avoid the flicker of setVisible



  • It does not flicker for me. But thanks for the Info.

    Anyway I would not recommend my code. Better check out QSqlTableModel and Model/View pattern and the use of delegates. I was not really aware of all that.


  • Lifetime Qt Champion

    Indeed, if you have a database behind that, the QSql* classes are a good choice.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.