4

コード:

populateTable()
{
  tableWidget->clearContents();
  tableWidget->setRowCount(stringList.size());

  for(int i = 0; i < stringList.size(); ++i)
  {
    tableWidget->setItem(i, 0, new QTableWidgetItem(stringList.at(i)));
  }
}

問題:

初めてpopulateTable()を実行するときは、すべて問題ありません。しかし、次の結果として、以前よりも実行速度が大幅に低下します。

討論:

注意深くテストした結果、clearContents()が問題であると思われます。単にコードをから変更するため

tableWidget->clearContents();

に:

tableWidget->setRowCount(0);

問題は修正されますが、今では別の問題が発生します。行数を「0」に設定しても、ヒープに割り当てられたQTableWidgetItemsは削除されないようです。アイテムの所有権が残っているように見えるため、メモリリークが残ります。(または少なくとも私はそう思う...)

QTableWidgetのQtのドキュメントはかなりあいまいなので、clearContents()が実際に何をするのか正確にはわかりません。ドキュメントでは、「ヘッダーにないすべてのアイテムをビューから削除する」と書かれているので、テーブルの内容は非表示になりますか?削除されますか?よくわかりません。私の理論では、clearContents()はアイテムのみを非表示にし、テーブルにデータを入力しようとすると、実際には各アイテムが削除および削除され、新しいアイテムがテーブルに割り当てられます。これはコストのかかる操作です。

もう1つの興味深い点は、QTableWidgetに関するQtのドキュメントでは、QTableWidgetにデータを設定する適切な方法は、QTableWidgetItemをヒープに割り当ててから、上記のコードで示したように、setItem()を使用してテーブルセルに設定することです。奇妙な...

要約すれば:

これらの問題をすべて発生させることなく、Qtテーブルにデータを入力して再入力する別の方法はありますか?そうでない場合、これらの問題を修正する方法はありますか?

4

2 に答える 2

5

「QTableWidgetに関するQtのドキュメントによると、QTableWidgetを設定する適切な方法は、QTableWidgetItemをヒープに割り当ててから、上記のコードで示したように、setItem()を使用してテーブルセルに設定することです。 「」

QTableWidget :: setItemのドキュメントに、ウィジェットがアイテムの所有権を取得すると明示的に記載されていることを考えると、奇妙なことではありません。

「行数を「0」に設定しても、ヒープに割り当てられたQTableWidgetItemsが削除されないようです。アイテムの所有権が残っているように見えるため、メモリリークが残ります(または少なくとも私はそう思います...)」

リークしているかどうかを推測するのではなく、QTableWidgetItemの独自のサブクラスを作成し、そのデストラクタにコードを配置して、ブレークポイントを設定して確実に知ることができます。あるいは、Qtソースは非常に読みやすくなっています。 setRowCountを呼び出しますremoveRows。これは実際にQTableWidgetItemsを削除します。

http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/itemviews/qtablewidget.cpp#line370

http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/itemviews/qtablewidget.cpp#line100

ただし、これもQTableWidget::setRowCountのドキュメントと一致しています。

このモデルの行数を行に設定します。これがrowCount()より小さい場合、不要な行のデータは破棄されます。

clearContents()とsetRowCount(0)の違いはあまり見られないはずです。この現象を示す、より大きなプログラムに絡まない、再現可能な小さな例を生成しましたか?

于 2012-04-17T18:20:54.903 に答える
3

QTableWidgetの再設定だけでなく、変更を加えると、全体的に遅くなることに気づきました。

たとえば、setCheckState()を介してチェックボックスを表示するセルが約1000個あるセルがあります。それらをチェック/チェック解除することで初めて、それらは高速です。2回目は、15秒ほどかかりますが、これはまったく受け入れられません。テーブルでblockSignals(true / false)を試しましたが、何も機能しませんでした。

秘訣は、テーブルではなくモデルのシグナルをブロックすることです。モデルはCPUを消費しているものです。

auto table = ui.tableWidget;
auto rows = table->rowCount();
auto cols = table->columnCount();

table->model()->blockSignals(true);

for (auto row = 0; row < rows; row++)
    for (auto col = 0; col < cols; col++)
        if (auto cb = table->item(row, col))
            cb->setCheckState(Qt::CheckState::Checked);

table->model()->blockSignals(false);
table->model()->layoutChanged();//Required, or else you won't see your changes immediately.
于 2015-07-22T00:11:46.773 に答える