Search code examples
qtqtableviewqitemdelegateqstandarditemmodel

Qt: Create a QItemDelegate to have a custom editor (Combo Boxes) in a QTableView with QStandardItemModel


I need to implement a table in Qt that shows a Combo Box on each row on a particular column.

So far based on this example: http://doc.qt.nokia.com/4.7-snapshot/itemviews-spinboxdelegate.html and on this question: QStandardItem + QComboBox I succesfully managed to create a QItemDelegate.

My problem is that everything works fine if I implement it from my main() function in main.cpp, but it does not work well if I insert the table in Qt Designer to use it then within a function of MainWindow class in mainwindow.cpp.

Could you please give me a clue? Thanks in advance!

Delegation on main.cpp (it works well, when I double click on the second column it shows a Combo Box):

QStandardItemModel model(4, 2);
QTableView tableView;
tableView.setModel(&model);
ComboBoxDelegate delegate;
tableView.setItemDelegateForColumn(1,&delegate);
tableView.horizontalHeader()->setStretchLastSection(true);

for (int row = 0 ; row < 4; ++row) {
    for (int col = 0; col < 2; ++col) {
        QModelIndex index = model.index(row, col, QModelIndex());
        model.setData(index, QVariant((row+1) * (col+1)));
    }
}
tableView.show();

Delegation on mainwindow.cpp alternative 1 (it shows an empty table)

QStandardItemModel model(4,2);
ui->tablePoint->setModel(&model);
ComboBoxDelegate delegate;
ui->tablePoint->setItemDelegateForColumn(1,&delegate);
ui->tablePoint->horizontalHeader()->setStretchLastSection(true);

for (int row = 0 ; row < 4; ++row) {
    for (int col = 0; col < 2; ++col) {
        QModelIndex index = model.index(row, col, QModelIndex());
        model.setData(index, QVariant((row+1) * (col+1)));
    }
}

Delegation on mainwindow.cpp alternative 2 (it shows the table but when I double click on the second column it does not show the Combo Box. Instead it shows the regular Spin Box):

QStandardItemModel* model = new QStandardItemModel(4,2);
ui->tablePoint->setModel(model);
ComboBoxDelegate delegate;
ui->tablePoint->setItemDelegateForColumn(1,&delegate);
ui->tablePoint->horizontalHeader()->setStretchLastSection(true);

for (int row = 0 ; row < 4; ++row) {
    for (int col = 0; col < 2; ++col) {
        QModelIndex index = model->index(row, col, QModelIndex());
        model->setData(index, QVariant((row+1) * (col+1)));
    }
}

Solution

  • Assuming that in both mainwindow.cpp cases, the code you show is in the constructor, you do the classic "coming from java, python, perl or any language where you don't give a damn about memory management" error to allocate your model and/or delegate on the stack rather than on the heap.

    In c++, stuff allocated on the stack (e.g. QStandardItemModel model(4,2);) is destroyed when returning from the function, while stuff allocated on the heap (e.g. QStandardItemModel* model = new QStandardItemModel(4,2); lives until you delete it). Case 1 works because stuff allocated on the stack in main() lives for the duration of the app.

    Bottom line: for case 3, do a ComboBoxDelegate* delegate = new ComboBoxDelegate(); and ui->tablePoint->setItemDelegateForColumn(1,delegate);