Reputation: 396
I am creating a small program that takes user input into a model and then shows that input in several views that take it through filters.
When the user clicks the button that accepts the input, the program updates the amount of cells in the views and then resizes those cells as necessary so that they fit neatly in their area.
My problem is that the cell resizing doesn't seem to work for one of the views for some reason (I tried looking for differences but couldn't find a reason for what I'm experiencing).
I'm calling the cell resizing function in two places:
If the cell resize function gets called twice inside dataChanged, then the view does update, however this involves some calculations and ui access and obviously not supposed to happen.
If I resize my window then the cells are resized properly.
I suspect that I'm always one update behind - that the view doesn't paint until the new update starts getting calculated and then that new update is on hold until the next calculation (since resize happens a lot of times in succession it might just act the same as the button but is harder/impossible to notice).
I have some dirty workarounds:
I thought I'd save my computer some work by only processing when the entire input had been received. My thinking was that, although dataChanged is emitted for every single item I'm inserting, I only really need to update once it is all in:
void MainWindow::on_dataChanged()
{
static int left_to_insert = -1;
if ( 0 > left_to_insert )
{
left_to_insert = m_model.rowCount() - 1;
}
if ( 0 == left_to_insert )
{
...
m_matrix_proxy.resize_to_fit();
adjust_matrix_cells_sizes();
}
--left_to_insert
}
Is it bad to only process the last signal? Why?
I tried calling update()
and/or repaint()
on both the matrix and the main window.
I tried calling both of these on the viewport of the QTableView
and tried calling them in succession from the matrix itself to the highest parent that didn't make my program crash. (ui->matrix->parentWidget()->parentWidget()...)
I tried qApp->processEvents()
.
I even resorted to emitting a resizeEvent
, but this is overkill IMO as it makes some calculations be performed again.
Just in case it is somehow relevant: The data appears correctly. The only thing that's wrong is that the cells don't resize.
Upvotes: 1
Views: 2666
Reputation: 37597
This logic in only code sample you have given is wrong. And this static
keyword makes it even worse.
There is ready solution delivered by Qt! See documentation of QHeaderView::ResizeMode and QHeaderView::setSectionResizeMode
IMO this should look like this:
void MainWindow::MainWindow()
…
{
…
mNeetToResizeCells = false;
connect(this, &MainWindow::NeedUpdateCellsSizes,
this, &MainWindow::ResizeTableCells,
Qt::QueuedConnection); // this is imporatant
}
void MainWindow::on_dataChanged()
{
if (!mNeetToResizeCells) {
mNeetToResizeCells = true;
emit NeedUpdateCellsSizes();
}
}
void MainWindow::ResizeTableCells()
{
mNeetToResizeCells = false;
// update cells sizes here
ui->tableView->resizeColumnsToContents();
ui->tableView->resizeRowsToContents();
}
This way all data updates performed in one iteration of event loop will cause only one invocation of MainWindow::ResizeTableCells
in some future iteration of event loop.
Upvotes: 2
Reputation: 8994
You need to emit layoutChanged
signal from your model. But be care with large amounts of items, because handling of this signal may take a lot of time.
Upvotes: 3