QListWidgetの現在行番号currentRowの取得・設定方法【Qt GUI】

2025-05-31

「QListWidget::currentRow」は、QtのクラスであるQListWidgetにおいて、現在選択されている項目の行番号を取得または設定するために使用されるプロパティ(正確には、それに関連するメソッド群)です。

より具体的に説明すると以下のようになります。

取得 (Get)

currentRow() メソッドを呼び出すと、QListWidget 内で現在ユーザーが選択している項目の0から始まる行番号が返されます。もし何も選択されていない場合や、リストが空の場合は -1 が返されます。

int currentRowIndex = listWidget->currentRow();
if (currentRowIndex != -1) {
    // 現在選択されている項目の行番号は currentRowIndex です
    // ...
} else {
    // 何も選択されていないか、リストが空です
}

設定 (Set)

setCurrentRow(int row) スロットを使用すると、指定された行番号の項目をプログラムから選択状態にすることができます。

// 3番目の項目(インデックスは 2)を選択します
listWidget->setCurrentRow(2);


よくあるエラーとトラブルシューティング

    • 原因
      currentRow() を呼び出すタイミングが、項目の選択が行われる前である可能性があります。または、他の何らかの処理によって意図せず選択状態が変更されているかもしれません。
    • トラブルシューティング
      • currentRow() を呼び出す前に、ユーザーが項目を選択する操作を行っているか確認してください。
      • 選択状態を変更する可能性のある他のコード(例えば、setCurrentRow() の呼び出しや、シグナル・スロット接続など)を確認し、意図しない動作がないか調べます。
      • 選択状態の変化を追跡するために、QListWidget::currentRowChanged(int) シグナルを利用して、選択が実際に変わったタイミングで処理を行うようにします。
  1. 意図した行番号と異なる値が currentRow() から返ってくる

    • 原因
      • 項目の追加や削除がリストに行われた後、行番号のインデックスが期待通りになっていない可能性があります。
      • 複数の選択モード (SelectionMode) が設定されている場合、単一の現在の行という概念が曖昧になることがあります(ただし、currentRow() は常に最後に選択された行を返します)。
    • トラブルシューティング
      • 項目の追加や削除を行う際には、関連する行番号の管理が正しく行われているか確認してください。必要に応じて、選択状態をリセットしたり、再設定したりすることを検討します。
      • QListWidget::selectionMode() で現在の選択モードを確認し、アプリケーションの意図と合致しているか確認します。単一選択のみを想定している場合は、QAbstractItemView::SingleSelection を設定します。
      • 複数の項目が選択されている場合に、どの行が「現在」の行として扱われるかを理解しておく必要があります。currentRow() は最後に選択またはフォーカスされた行を返します。複数の選択された項目すべてを取得したい場合は、selectedItems()selectedIndexes() を使用します。
  2. setCurrentRow() を呼び出しても項目が選択されない

    • 原因
      • 指定した行番号がリストの範囲外である可能性があります。
      • リストが空である可能性があります。
      • 項目の選択が何らかの理由で禁止されている可能性があります(例えば、特定のフラグが設定されているなど)。
    • トラブルシューティング
      • setCurrentRow() に渡す行番号が、0 から count() - 1 の範囲内であることを確認してください。
      • QListWidget::count() でリスト内の項目数を確認し、リストが空でないことを確認してください。
      • 項目のフラグ (QListWidgetItem::flags()) を確認し、選択が可能になっているか (Qt::ItemIsSelectable フラグが含まれているか) 確認してください。
  3. シグナル currentRowChanged(int) が期待通りに発行されない

    • 原因
      • シグナルとスロットの接続が正しく行われていない可能性があります。
      • プログラム内で setCurrentRow() を呼び出した場合、そのタイミングによってはシグナルが発行されないことがあります(特に、初期化時など)。
    • トラブルシューティング
      • connect() 関数が正しく呼び出され、シグナルの種類とスロットの引数が一致しているか確認してください。
      • プログラムによる選択変更でシグナルを明示的にトリガーする必要がある場合は、状況に応じて適切な処理を検討してください。一般的には、ユーザー操作による選択変更でのみシグナルが発行されることが多いです。

一般的なトラブルシューティングのヒント

  • 簡単なテストケースを作成する
    問題を再現する最小限のコードを作成し、問題を特定しやすくします。
  • Qt のドキュメントを参照する
    QListWidget や関連するクラスの公式ドキュメントには、詳細な説明や使用例が記載されています。
  • ステップ実行
    デバッガを使用してコードを一行ずつ実行し、変数の変化や関数の呼び出し順序を確認します。
  • デバッグ出力を活用する
    qDebug() などを使用して、currentRow() の値や関連する変数の値をログ出力し、プログラムの動作を追跡します。


例1: 現在選択されている項目のテキストを取得する

この例では、QListWidget で現在選択されている項目の行番号を取得し、その行の項目のテキストを表示します。

#include <QApplication>
#include <QListWidget>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QListWidget listWidget;
    listWidget.addItem("りんご");
    listWidget.addItem("みかん");
    listWidget.addItem("バナナ");
    listWidget.addItem("ぶどう");

    // 項目が選択されたときに実行されるスロット
    QObject::connect(&listWidget, &QListWidget::currentRowChanged,
                     [&](int currentRow) {
        if (currentRow != -1) {
            QListWidgetItem *currentItem = listWidget.item(currentRow);
            qDebug() << "選択された行番号:" << currentRow;
            qDebug() << "選択されたテキスト:" << currentItem->text();
        } else {
            qDebug() << "何も選択されていません";
        }
    });

    listWidget.show();

    return a.exec();
}

解説

  • currentRow-1 の場合は、何も選択されていないことを示すメッセージを出力します。
  • 取得した QListWidgetItemtext() メソッドを呼び出して、項目のテキストを取得し、qDebug() で出力しています。
  • currentRow-1 でない場合(つまり、何らかの項目が選択されている場合)、listWidget.item(currentRow) を使用してその行の QListWidgetItem ポインタを取得します。
  • ラムダ関数内では、引数 currentRow で新しい選択された行番号を受け取ります。
  • QObject::connect() を使用して、QListWidget::currentRowChanged(int) シグナルとラムダ関数(スロット)を接続しています。このシグナルは、選択されている行が変更されるたびに発行されます。
  • QListWidget のインスタンス listWidget を作成し、いくつかの項目を追加しています。

例2: 特定の行をプログラムから選択する

この例では、ボタンがクリックされたときに、QListWidget の特定の行をプログラムから選択状態にします。

#include <QApplication>
#include <QListWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget window;
    QVBoxLayout layout(&window);

    QListWidget listWidget;
    listWidget.addItem("東京");
    listWidget.addItem("大阪");
    listWidget.addItem("名古屋");
    listWidget.addItem("福岡");
    layout.addWidget(&listWidget);

    QPushButton selectButton("2番目の項目を選択");
    layout.addWidget(&selectButton);

    // ボタンがクリックされたときに実行されるスロット
    QObject::connect(&selectButton, &QPushButton::clicked,
                     [&]() {
        // インデックスは 0 から始まるため、2番目の項目はインデックス 1 です
        listWidget.setCurrentRow(1);
    });

    window.setLayout(layout);
    window.show();

    return a.exec();
}

解説

  • ラムダ関数内では、listWidget.setCurrentRow(1) を呼び出すことで、インデックスが 1 の項目(つまり、2番目の項目)をプログラムから選択状態にしています。これにより、currentRowChanged シグナルも発行されます。
  • ボタンの clicked シグナルとラムダ関数を接続しています。
  • QListWidgetQPushButton を持つウィンドウを作成しています。

例3: 現在選択されている行番号に基づいて処理を行う

この例では、選択された行番号に応じて異なる処理を行います。

#include <QApplication>
#include <QListWidget>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QListWidget listWidget;
    listWidget.addItem("赤");
    listWidget.addItem("青");
    listWidget.addItem("黄");

    QObject::connect(&listWidget, &QListWidget::currentRowChanged,
                     [&](int currentRow) {
        if (currentRow == 0) {
            qDebug() << "「赤」が選択されました。";
            // 赤に関連する処理
        } else if (currentRow == 1) {
            qDebug() << "「青」が選択されました。";
            // 青に関連する処理
        } else if (currentRow == 2) {
            qDebug() << "「黄」が選択されました。";
            // 黄に関連する処理
        } else {
            qDebug() << "何も選択されていないか、予期しない選択です。";
        }
    });

    listWidget.show();

    return a.exec();
}
  • currentRowChanged シグナルを受け取るラムダ関数内で、currentRow の値に応じて異なるメッセージを出力したり、それぞれの項目に関連する処理を分岐させたりしています。


QListWidget::selectedItems()

このメソッドは、現在選択されているすべての QListWidgetItem オブジェクトのリストを返します。複数の項目が選択されている場合や、項目のテキストやアイコンなどの情報に直接アクセスしたい場合に便利です。

QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
for (QListWidgetItem *item : selectedItems) {
    qDebug() << "選択されたテキスト:" << item->text();
    // 選択された項目に対する処理
}

利点

  • 各項目の QListWidgetItem オブジェクトに直接アクセスできるため、テキスト、アイコン、データなどの情報を取得しやすい。
  • 複数の選択された項目を簡単に取得できる。

欠点

  • 単一の現在の選択行のみに関心がある場合は、リストから最初の要素を取得する必要がある。
  • 選択された行番号を直接取得するには、indexOf() などを使ってリスト内で検索する必要がある場合がある。

QListWidget::selectedIndexes()

このメソッドは、現在選択されているすべての項目の QModelIndex オブジェクトのリストを返します。QModelIndex は、モデル/ビューアーキテクチャにおける項目の位置を表す抽象化されたインデックスです。

QModelIndexList selectedIndexes = listWidget->selectedIndexes();
for (const QModelIndex &index : selectedIndexes) {
    int row = index.row();
    qDebug() << "選択された行番号:" << row;
    QListWidgetItem *item = listWidget->item(row);
    qDebug() << "選択されたテキスト:" << item->text();
    // 選択された行番号や項目に対する処理
}

利点

  • QModelIndex を使用することで、より柔軟なデータ操作が可能になる場合がある。
  • モデル/ビューアーキテクチャに沿った方法で選択された項目を扱える。

欠点

  • currentRow() よりも少し複雑になる場合がある。
  • QModelIndex から直接 QListWidgetItem にアクセスするには、QListWidget::item(int row) を使用する必要がある。

QListWidget::itemAt(const QPoint &p)

このメソッドは、指定された座標 p に位置する QListWidgetItem を返します。マウスイベントなどが発生した位置にある項目を特定するのに役立ちます。

void mousePressEvent(QMouseEvent *event) override
{
    QListWidgetItem *item = listWidget->itemAt(event->pos());
    if (item) {
        qDebug() << "クリックされた項目:" << item->text();
        int row = listWidget->row(item);
        qDebug() << "クリックされた行番号:" << row;
        listWidget->setCurrentRow(row); // クリックされた行を選択状態にする例
    }
    QListWidget::mousePressEvent(event);
}

利点

  • マウス操作などのイベント処理と連携しやすい。
  • 特定の座標にある項目を直接取得できる。

欠点

  • 現在の選択状態全体を取得するのには適していない。

シグナル QListWidget::itemSelectionChanged()

このシグナルは、選択状態が変更されたときに発行されます。このシグナルに接続されたスロット内で、selectedItems()selectedIndexes() を使用して、現在選択されているすべての項目を取得できます。

QObject::connect(&listWidget, &QListWidget::itemSelectionChanged,
                 [&]() {
    QList<QListWidgetItem*> selected = listWidget->selectedItems();
    qDebug() << "選択された項目数:" << selected.count();
    for (QListWidgetItem *item : selected) {
        qDebug() << "選択されたテキスト:" << item->text();
    }
});

利点

  • 複数の選択された項目を扱うのに適している。