受け入れられた答えは素晴らしいです-より高度なQtの概念のいくつかを紹介してくれました。
将来これを試す人のために、これをスムーズに機能させるためにいくつかの変更を加える必要がありました。
- スレッドを制限する:
QThreadPool
最大スレッド数を 1 または 2 に設定して、 aをに渡しQConcurrent::run
ます。デフォルトを使用すると、すべてのスレッドがビルド イメージのプレビューを焼き付けるため、アプリが強制終了されました。ボトルネックはディスクになるため、このタスクに 1 つまたは 2 つ以上のスレッドを使用しても意味がありません。
- 再入力の回避:アイコンの生成が完了する前に、同じパスのアイコンが複数回照会されるケースを処理する必要があります。現在のコードでは、同じアイコンを生成する複数のスレッドが生成されます。簡単な解決策は、QConcurrent::run 呼び出しの前に m_icons マップにプレースホルダー エントリを追加することです。default を呼び出した
QIdentityProxyModel::data(index, QFileSystemModel::FileIconRole)
ので、ロードが完了する前にアイコンはまともなデフォルトを取得します
- タスクのキャンセル:モデルを破棄する場合 (またはビュー フォルダーなどを切り替えたい場合)、アクティブなタスクをキャンセルする方法が必要になります。
QConcurrent::run
残念ながら、保留中のタスクをキャンセルする組み込みの方法はありません。std::atomic_bool
タスクが実行前にチェックするキャンセルを通知するために a を使用しました。そして、std::condition_variable
すべてのタスクがキャンセル/完了するまで待機します。
ヒント:これの私の使用例は、ディスク上の画像からサムネイル プレビューを読み込むことでした (一般的な使用例と思われます)。いくつか実験した結果、プレビューを生成する最速の方法は、 を使用しQImageReader
、サムネイル サイズを に渡すことであることがわかりましたsetScaledSize
。正方形でない画像がある場合は、次のように適切な縦横比のサイズを渡す必要があることに注意してください。
const QSize originalSize = reader.size(); // Note: Doesn't load the file contents
QSize scaledSize = originalSize;
scaledSize.scale(MaximumIconSize, Qt::KeepAspectRatio);
reader.setScaledSize(scaledSize);