「Qtのコントロール - リスト」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
60行目: 60行目:
リストの標準メソッドに存在するソートを使用すると、"file1 file10 file11 file2 ..."のように並び替えられてしまう。<br>
リストの標準メソッドに存在するソートを使用すると、"file1 file10 file11 file2 ..."のように並び替えられてしまう。<br>
<br>
<br>
そこで、リストの標準メソッドを使用せずに、独自にソート関数を作成してコントロールに追加する必要がある。<br>
数値の大きさ順にファイルを並べるソートをナチュラルソートと呼ぶが、現在、QtのAPIには該当機能は実装されていないため、<br>
Windowsの場合、<code>StrCmpLogicalW</code>関数がこのような文字列を数字順にソートすることができる。 <br>
ナチュラルソート関数を作成する必要がある。<br>
<br>
Windowsの場合、<code>StrCmpLogicalW</code>関数を使用して、ナチュラルソートを実装することができる。 <br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  // MainWindow.cpp
  // MainWindow.cpp
   
   
#if defined(Q_OS_WIN)
  // 比較関数
  // 比較関数
  bool MainWindow::lessThan(QString &left, QString &right)
  bool MainWindow::lessThan(QString &left, QString &right)
  {
  {
     LPCWSTR pszwLeft, pszwRight;
     LPCWSTR pszwLeft, pszwRight;
 
   
  #if defined(Q_OS_WIN)
     pszwLeft = (LPCWSTR)left.unicode();
     pszwLeft = (LPCWSTR)left.unicode();
     pszwRight = (LPCWSTR)right.unicode();
     pszwRight = (LPCWSTR)right.unicode();
#elif defined(Q_OS_LINUX)
   
#endif
   
   
     return StrCmpLogicalW(pszwLeft, pszwRight) < 0;
     return StrCmpLogicalW(pszwLeft, pszwRight) < 0;
  }
  }
#endif
   
   
  // 複数選択したファイルリストをリストウィジェットに追加する関数
  // 複数選択したファイルリストをリストウィジェットに追加する関数
  void MainWindow::browseImage()
  void MainWindow::browseImage()
  {
  {
     QStringList strlFName = QFileDialog::getOpenFileNames(this, "Select files",  "C:\\", "File(*.*)");
     QStringList listFileName = QFileDialog::getOpenFileNames(this, "Select files",  "<検索ディレクトリのパス>", "File(*.*)");
     if(strlFName.size() == 0)
     if(listFileName.size() == 0)
     {
     { // ファイルが存在しない場合
       return;
       return;
     }
     }
   
   
     qSort(strlFName.begin(), strlFName.end(), lessThan);
#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;
                                                        });
#endif
   
   
     for(int i = 0; i < strlFName.size(); i++)
     for(int i = 0; i < listFileName.size(); i++)
     {
     {
       listWidget->addItem(strlFName.at(i));
       listWidget->addItem(listFileName.at(i));
     }
     }
  }
  }
107行目: 117行目:
   
   
     void browseImage();
     void browseImage();
#if defined(Q_OS_WIN)
     static bool lessThan(QString &left, QString &right);
     static bool lessThan(QString &left, QString &right);
#endif
   
   
     // ...略
     // ...略
113行目: 126行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
QTreeViewクラスやQTableViewクラスの場合は、QSortFilterProxyModelクラスを継承した派生クラスを作成してセットする方法もある。<br>
<code>QTreeView</code>クラスや<code>QTableView</code>クラスの場合は、<code>QSortFilterProxyModel</code>クラスを継承した派生クラスを作成して、ナチュラルソート関数を作成する方法もある。<br>
以下のGoogle codeのプロジェクトが採用している。<br>
以下のGoogle codeのプロジェクトが採用している。<br>
[http://code.google.com/p/kamicmd/ kamicmd - Modern file manager - Google Project Hosting]<br>
[http://code.google.com/p/kamicmd/ kamicmd - Modern file manager - Google Project Hosting]<br>

2021年2月23日 (火) 20:20時点における版

概要

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