Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Updating QTablWidget correctly



  • Hi,

    I am using a QTableWidget with 2 columns and 3 rows in my GUI. This table is updated approximately 5 times per second. For updating the QTableWidget I have the following function, which takes a QMap as an argument which in turn contains the data to be printed in the QTableWidget. It is called in a slot:

    void Ui::updateTable(QMap<QString, float> data)
    {
        ui->table->setItem(0,0, new QTableWidgetItem(QString::number(data["a"])));
        ui->table->setItem(1,0, new QTableWidgetItem(QString::number(data["b"])));
        ui->table->setItem(2,0, new QTableWidgetItem(QString::number(data["c"])));
        ui->table->setItem(0,1, new QTableWidgetItem(QString::number(data["d"])));
        ui->table->setItem(1,1, new QTableWidgetItem(QString::number(data["e"])));
        ui->table->setItem(2,1, new QTableWidgetItem(QString::number(data["f"])));
    }
    

    Is that correct? I have a strange feeling, especially since this "new QTableWidgetItem" is called every time - so there are no memory problems (leak), right?

    Or would this be the correct way:

    void Ui::updateTable(QMap<QString, float> data)
    {
        ui->table->item(0,0)->setText(QString::number(data["a"]));
        ui->table->item(1,0)->setText(QString::number(data["b"]));
        ui->table->item(2,0)->setText(QString::number(data["c"]));
        ui->table->item(0,1)->setText(QString::number(data["d"]));
        ui->table->item(1,1)->setText(QString::number(data["e"]));
        ui->table->item(2,1)->setText(QString::number(data["f"]));
    }
    

    Thank you!


  • Lifetime Qt Champion

    Hi,

    The second solution is cleaner. You are needlessly creating and destroying objects with the first approach.

    The setItem documentation states that the widget takes ownership of the item so it should dispose of it properly.


  • Lifetime Qt Champion

    Hi,

    The second solution is cleaner. You are needlessly creating and destroying objects with the first approach.

    The setItem documentation states that the widget takes ownership of the item so it should dispose of it properly.



  • @TUStudi
    Separate from that question, if this is being called often

    void Ui::updateTable(QMap<QString, float> data)
    

    I would have thought

    void Ui::updateTable(const QMap<QString, float> &data)
    

    would be better?



  • @SGaist said in Updating QTablWidget correctly:

    Hi,

    The second solution is cleaner. You are needlessly creating and destroying objects with the first approach.

    The setItem documentation states that the widget takes ownership of the item so it should dispose of it properly.

    This makes sense, thank you!

    @JonB said in Updating QTablWidget correctly:

    I would have thought

    void Ui::updateTable(const QMap<QString, float> &data)
    

    would be better?

    Why? Would that make a big difference?


  • Lifetime Qt Champion

    @TUStudi
    Hi
    The & means by reference so

    void Ui::updateTable(QMap<QString, float> data)
    

    This will make a copy of the original container you use with it.
    If it has many items, that can be expensive.
    But QMap uses sharing
    https://doc.qt.io/qt-5/implicit-sharing.html
    So its cheap to copy.
    But for other containers, it can make a huge difference.
    Also if it contains complex objects.

    void Ui::updateTable(const QMap<QString, float> &data)
    

    This does not make a copy but is a reference (like pointer) to the original
    map. So very fast.



  • @mrjj Thank you very much, I completely ignored that.

    One more thing:
    In my previous version of updating the table
    ui->table->setItem(0,0, new QTableWidgetItem(QString::number(data["a"])));,
    I used a reset button, which calls ui->table->clearContent.
    With the new code
    ui->table->item(0,0)->setText(QString::number(data["a"]));
    , when I click the reset button and then start the updateData-Slot egain, there is a access-violation exception pointing to my first line

     ui->table->item(0,0)->setText(QString::number(data["a"]));
    

    When I comment out ui->table->clearContent, the exception does not occur. What's the issue here?



  • @TUStudi
    When you create a new QTableWidget, or call clearContents(), there are no items in the table! So ui->table->item(0,0) is nullptr.



  • @JonB said in Updating QTablWidget correctly:

    @TUStudi
    When you create a new QTableWidget, or call clearContents(), there are no items in the table! So ui->table->item(0,0) is nullptr.

    Ahhh, okay. So actually I do not have to call clearContents, so I will just remove this line of code!
    Thanks again =D



  • @TUStudi
    Well, it's not necessarily that: you can create an item via void QTableWidget::setItem(int row, int column, QTableWidgetItem *item) instead.


Log in to reply