QTableView 没有正确更新

QTableView not updating properly

我正在创建一个小程序,它将用户输入输入模型,然后在多个视图中显示该输入,这些视图通过过滤器。

当用户单击接受输入的按钮时,程序会更新视图中的单元格数量,然后根据需要调整这些单元格的大小,以便它们整齐地适合它们的区域。

我的问题是,出于某种原因,单元格大小调整似乎不适用于其中一个视图(我尝试寻找差异,但找不到我遇到的原因)。

我在两个地方调用单元格大小调整功能:

  1. dataChanged 插槽。
  2. resizeEvent 插槽。

如果单元格大小调整函数在 dataChanged 中被调用 两次,那么视图 更新,但是这涉及一些计算和 ui 访问,显然不应该发生。

如果我 resize 我的 window 则单元格会正确调整大小。

我怀疑我总是落后一个更新 - 在新更新开始计算之前视图不会绘制,然后新更新被搁置直到下一次计算(因为调整大小发生了很多次随后它可能与按钮的行为相同,但 harder/impossible 需要注意)。

我有一些肮脏的解决方法:

  1. 正如我提到的,如果我再次调用我的单元格调整大小函数,视图会正确更新。
  2. 如果我删除下一段代码中的第二个 "if",那么一切正常。

我想我可以通过仅在收到全部输入后才进行处理来节省我的计算机一些工作。我的想法是,虽然 dataChanged 是为我插入的每个项目发出的,但我只需要在它全部进入后才真正需要更新:

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
}

只处理最后一个信号不好吗?为什么?

我尝试在矩阵和主 window 上调用 update() and/or repaint()

我尝试在 QTableView 的视口上调用这两个,并尝试从矩阵本身连续调用它们到没有使我的程序崩溃的最高父级。 (ui->矩阵->parentWidget()->parentWidget()...)

我试过了qApp->processEvents()

我什至使用了 resizeEvent,但在我看来这太过分了,因为它会再次执行一些计算。

以防万一它有某种相关性:数据显示正确。唯一的错误是单元格没有调整大小。

只有您提供的代码示例中的这个逻辑是错误的。而这个 static 关键字使情况变得更糟。

实际答案:

Qt 提供现成的解决方案!请参阅 QHeaderView::ResizeMode and QHeaderView::setSectionResizeMode

的文档

旧答案:

IMO 这应该是这样的:

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();
}

这样一来,在事件循环的一次迭代中执行的所有数据更新将仅导致在事件循环的某个未来迭代中调用一次 MainWindow::ResizeTableCells

您需要从您的模型发出 layoutChanged 信号。但是要注意大量物品,因为处理这个信号可能会花费很多时间。

类似问题:one, two