cannot get fixed sized columns in QTableView to work.
-
I am having trouble initializing a QTableView with fixed column header column widths.
When I display the table for the first time, the columns seem to use the default
horizontalHeaderDefaultSectionSize
property from the Qt Designer's property editor.I also have the
horizontalHeaderStretchLastSection
property set totrue
.If I double-click on each of the columns, the layout snaps to the correct width, however I have to do this for each of the columns (except the last which is set to stretch as I just described). I am not sure why the initial layout does not respect the widths in my code.
Has this something to do with
sizeHint
s in a model for ahorizontalHeader
? I do not want to automatically size to the contents of the table (as the table can grow to a very large size, I just want the initial sizes to be correct).I set up my views using a table driven approach. The table contains a sample fixed size string or a length that I use to size the header (using font metrics):
using TableSpec = std::vector< std::tuple< QTableView*, QStandardItemModel*, std::vector<TableColumnSpec> > >; Define the layout for tables in the main window. // Views with proxy sort filters need special handling // as the view does not directly have access to the model. const TableSpec gTableSpecs = { { // Thread colored logger. { ui->logView, mpLogViewModel.get(), { TableColumnSpec("Time", "Timestamp", "06-09-2023 20:01:33.334"), TableColumnSpec("Thread", "Thread ID", "0x00000000"), TableColumnSpec("Level", "Severity level", "critical"), TableColumnSpec("Description", "Description", "description") } }, } };
The above code shows just one of my tables (the one that shows a log table). This table uses a custom delegate that is assigned as follows (I don't think the delegate is involved with laying out the initial view of the horizontal header though), I also assign the
mpLogViewModel
(std::unique_ptr<QStandardItemModel>
) to the view from here:// Assign item delegate to color the rows using the threadID (column1). ui->logView->setItemDelegate(mpLogItemDelegate.get()); // Associate each model with its respective view. ui->logView->setModel(mpLogViewModel.get());
Now that the item delegate and model have been associated with the
ui->logView
(QTableView), I initialize the table(s) as follows:// Layout the main application tables & headers. initTableHeaders(gTableSpecs); void initTableHeaders(const TableSpec& rTableSpec) { for (const auto& [pView, pModel, colSpecs] : rTableSpec) { const auto fm = pView->fontMetrics(); const auto rowHeight = fm.lineSpacing(); pView->verticalHeader()->setDefaultSectionSize(rowHeight); pView->verticalHeader()->setMaximumSectionSize(rowHeight); pView->verticalHeader()->setMinimumSectionSize(rowHeight); pView->verticalHeader()->setVisible(false); pView->horizontalHeader()->setMinimumSectionSize(25); pView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); pView->horizontalHeader()->setStretchLastSection(true); pView->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); pView->horizontalHeader()->setSortIndicatorShown(true); pView->setSelectionBehavior(QAbstractItemView::SelectRows); for (auto col = 0; col < static_cast<int>(colSpecs.size()); ++col) { const auto headerLabel = new QStandardItem(colSpecs[col].mColumnTitle); headerLabel->setTextAlignment(colSpecs[col].mAlignment); pModel->setHorizontalHeaderItem(col, headerLabel); const auto columnWidth = std::visit(Overload{ [&](const QString& rSampleStr)->int { if (!rSampleStr.isEmpty()) { return fm.horizontalAdvance(rSampleStr); } return fm.horizontalAdvance(colSpecs[col].mColumnTitle); }, [&](const auto stringLength)->int { if (stringLength > 0) { return stringLength * fm.averageCharWidth(); } return fm.horizontalAdvance(colSpecs[col].mColumnTitle); }, }, colSpecs[col].mSizeInfo); // Add 20 to make room for the sort arrow. pView->setColumnWidth(col, columnWidth + 20); } } }
The problem is that when the log is displayed, it looks like this:
-
// [snip ...] // Add 20 to make room for the sort arrow. // pView->setColumnWidth(col, columnWidth + 20); auto header = pView->horizontalHeader(); header->setSectionResizeMode(col, QHeaderView::Fixed); header->resizeSection(col, columnWidth + 20);
-
@kshegunov said in cannot get fixed sized columns in QTableView to work.:
header->resizeSection(col, columnWidth + 20);
I just tried this, unfortunately it does not work - but thank you, as after changing from 'Fixed' to 'ResizeToContents', the initial layout accept ed my column widths (strange that it would not accept Fixed - perhaps it has to do with settings fixed on the last column which really needs to be Stretch to use the remaining horizontal space? My issue was not resizing the section on the view's horizontalHeader. Thanks!!!
// Add 20 to make room for the sort arrow. const auto header = pView->horizontalHeader(); header->setSectionResizeMode(col, QHeaderView::ResizeToContents); header->resizeSection(col, columnWidth + 20);
-
@johnco3 said in cannot get fixed sized columns in QTableView to work.:
perhaps it has to do with settings fixed on the last column which really needs to be Stretch to use the remaining horizontal space?
Yes, it does. I think to make it really a fixed size you might need to set the minimum and maximum size to the same thing.