QTableView未正确更新

时间:2016-05-12 07:28:53

标签: qt qtableview

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

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

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

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

  1. dataChanged slot。
  2. resizeEvent slot。
  3. 如果细胞大小调整功能在dataChanged中被称为两次,那么视图更新,但是这涉及一些计算和ui访问,显然不应该发生。< / p>

    如果我调整大小我的窗口,那么单元格会正确调整大小。

    我怀疑我总是有一个更新 - 在新的更新开始计算之前视图不会绘制,然后新的更新一直处于保持状态直到下一次计算(因为调整大小连续发生很多次它可能与按钮的行为相同,但更难/不可能注意到。)

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

    1. 正如我所提到的,如果我再次调用我的单元格调整大小功能,则视图会正确更新。
    2. 如果我删除下一段代码中的第二个“if”,那么一切正常。
    3. 我以为只有在收到整个输入时才进行处理,我会保存计算机的一些工作。我的想法是,虽然我插入的每一个项目都会发出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
      }
      

      仅处理最后一个信号是不是很糟糕?为什么呢?

      我尝试在矩阵和主窗口上调用update()和/或repaint()

      我尝试在QTableView的视口上调用这两个,并尝试从矩阵本身连续调用它们到最高父节点,但不会导致程序崩溃。 (UI-&GT;基质 - &GT; parentWidget() - &GT; parentWidget()...)

      我尝试了qApp->processEvents()

      我甚至使用了resizeEvent,但这是过度的IMO,因为它会再次进行一些计算。

      以防万一它是相关的:数据显示正确。唯一错误的是细胞不会调整大小。

2 个答案:

答案 0 :(得分:2)

这个逻辑只在你给出的代码示例中是如此可怕而且错误。这个static关键字会让情况变得更糟。您知道static关键字的作用吗?

当我读到你到目前为止所尝试的内容时,我会感到很难过(你试着做一些随意的东西,希望有些东西可以做到&#34;魔法&#34;)。

实际答案:

Qt提供了现成的解决方案!请参阅maxDiffQHeaderView::ResizeMode

的文档

旧答案:

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的一次调用。

答案 1 :(得分:2)

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

类似问题:onetwo