Search code examples
c++qtqt6

How can I save a Window form in QTableWidget as it was a matrix?


I'm trying to save a Window form inside a QTableWidget table.

int rows = 0;
int columns = 0;
QTableWidget cellTable;

What I'm doing is that I first set the rows and columns

cellTable.setRowCount(++rows);
cellTable.setRowCount(++columns);

For every time I increase the rows, I call this code

for(int i = 0; i < rows; i++)
    cellTable.setCellWidget(rows-1, i, new DatabaseMeasurementType());

For every time I increase the columns, I call this code

for(int i = 0; i < rows; i++)
    cellTable.setCellWidget(i, columns-1, new DatabaseMeasurementType());

It works if I replace the new DatabaseMeasurementType() with new QPushButton(). But then all the fields will be buttons. For the moment, I just want to store a window form inside the setCellWidget. Yes, new DatabaseMeasurementType() is a widget form.

Problem:

When I call this code (dynamic cast)

DatabaseMeasurementType *databaseMeasurementType = static_cast<DatabaseMeasurementType*>(cellTable.cellWidget(row, column));
databaseMeasurementType->show();

Or this code (static cast)

DatabaseMeasurementType *databaseMeasurementType = dynamic_cast<DatabaseMeasurementType*>(cellTable.cellWidget(row, column));
databaseMeasurementType->show();

Then it crash. Why? My idea is to have a large 2D matrix where I can store windows forms. Then I only need to call x and y arguments for the 2D matrix to recieve the windows form.


Solution

  • Casting should work if you've inherited from QWidget properly. Casts return nullptr if failed. So, it's safier to check if it's failed or not:

    if(databaseMeasurementType != nullptr){
        //some works with databaseMeasurementType
    }
    

    It's recommended to use qobject_cast if you've written Q_OBJECT macro inside your class.

    If you want to show your window outside of the table's cell

    • Getting widget and removing it from the table. When you use setCellWidget method, QTableWidget change widget's parent because of memory management. Widgets are shown inside their parents. So, you should change it's parent after getting it and remove it from the table. But QTableWidget::removeCellWidget(int row, int column) removes the widget and deletes it. setCellWidget(row, col, nullptr) also deletes it. So one way to remove the widget without deleting it is wrapping it to another widget.
    • Cloning a widget. You should do it manually. One traditional way is to implement custom QWidget* clone() method, and cloning member-by-member.