Qtのコントロール - リスト
概要
Qtにおいて、QListWidget
クラスを使用してリストのコントロールの手順を記載する。
似た名前のウィジェットにリストビューがあるので間違えないように注意すること。
ここでは、リストのコントロールIDをlistWidgetとしている。
アイテムの追加
listWidget->clear();
// 文字列を追加する場合
listWidget->addItem( tr("何か文字列") );
現在のアイテムの文字列を取得
QListWidgetItem *pItem = listWidget->currentItem();
QString str = pItem->text();
選択されているアイテムを取得
複数選択が有効になっている場合、複数選択されているアイテムを取得するため、以下のように記述する。
// 選択されているアイテムのリストを取得
QList<QListWidgetItem *> listItems = listWidget->selectedItems();
// 個別のアイテムに対する処理
for(int i = 0; i < listItems.size(); i++)
{
QListWidgetItem *pItem = listItems[i];
}
選択されているアイテムの削除
Qtの公式ドキュメントには、takeItem
メソッドを使用してリストのアイテムを削除するとの記述があるが、
takeItem
メソッドは引数に行番号を1つ渡すだけであるため、複数選択の場合、それらをまとめて削除することができない。
複数選択の場合、まとめて削除する方法は、以下のように記述する。
qDeleteAll(listWidget->selectedItems());
また、以下の方法においても、まとめて削除することができる。
QList<QListWidgetItem *> itemList = listWidget->selectedItems();
for(int i=0; i < itemList.size(); i++)
{
widget->takeItem(listWidget->indexFromItem(itemList[i]));
}
リストにファイル名リストを追加する
ファイル名に数を含む場合、例えば、"file1 file2 ... file10 file11"のようなファイル名リストをコントロールに追加する場合、
リストの標準メソッドに存在するソートを使用すると、"file1 file10 file11 file2 ..."のように並び替えられてしまう。
数値の大きさ順にファイルを並べるソートをナチュラルソートと呼ぶが、現在、QtのAPIには該当機能は実装されていないため、
ナチュラルソート関数を作成する必要がある。
Windowsの場合、StrCmpLogicalW
関数を使用して、ナチュラルソートを実装することができる。
// MainWindow.cpp
#if defined(Q_OS_WIN)
// 比較関数
bool MainWindow::lessThan(QString &left, QString &right)
{
LPCWSTR pszwLeft, pszwRight;
pszwLeft = (LPCWSTR)left.unicode();
pszwRight = (LPCWSTR)right.unicode();
return StrCmpLogicalW(pszwLeft, pszwRight) < 0;
}
#endif
// 複数選択したファイルリストをリストウィジェットに追加する関数
void MainWindow::browseImage()
{
QStringList listFileName = QFileDialog::getOpenFileNames(this, "Select files", "<検索ディレクトリのパス>", "File(*.*)");
if(listFileName.size() == 0)
{ // ファイルが存在しない場合
return;
}
#if defined(Q_OS_WIN)
qSort(listFileName.begin(), listFileName.end(), lessThan);
#elif defined(Q_OS_LINUX)
QCollator collator;
collator.setNumericMode(true);
std::sort(listFileName.begin(), listFileName.end(), [&collator](const QString &file1, const QString &file2)
{
return collator.compare(file1, file2) < 0;
});
// または、以下の記述でも良い
std::sort(listFileName.begin(), listFileName.end(), collator);
#endif
for(int i = 0; i < listFileName.size(); i++)
{
listWidget->addItem(listFileName.at(i));
}
}
// MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
// ...略
void browseImage();
#if defined(Q_OS_WIN)
static bool lessThan(QString &left, QString &right);
#endif
// ...略
};
QTreeView
クラスやQTableView
クラスの場合は、QSortFilterProxyModel
クラスを継承した派生クラスを作成して、ナチュラルソート関数を作成する方法もある。
以下のGoogle codeのプロジェクトが採用している。
kamicmd - Modern file manager - Google Project Hosting