Qtプログラミング: QListWidgetのアイテム操作を徹底解説

2025-05-31

QListWidget とは

QListWidget は、アイテムのリストを表示・操作するためのウィジェットです。各アイテムは QListWidgetItem オブジェクトとして表され、それぞれテキスト、アイコン、チェックボックスなどの情報を持つことができます。

QModelIndex とは

QModelIndex は、Qt のモデル/ビューアーキテクチャにおいて、モデル内のデータアイテムの位置(行、列、親インデックスなど)を示すための抽象的な概念です。QListWidget の場合、これはリスト内の特定のアイテムを一意に特定するための「住所」のようなものと考えることができます。

QListWidget::itemFromIndex() の役割

QListWidget::itemFromIndex(const QModelIndex &index) 関数は、次のような目的で使用されます。

  1. QModelIndex から QListWidgetItem への変換: QListWidget が内部的に使用する QModelIndex オブジェクトから、開発者が直接操作したい QListWidgetItem オブジェクトを取得するために使用します。

  2. 他のモデル/ビュークラスとの連携: 例えば、QSortFilterProxyModel のように、モデルのデータをソートしたりフィルタリングしたりするクラスを使用している場合、表示されているアイテムの QModelIndex は元のモデルのインデックスとは異なることがあります。このような場合でも、QListWidget::itemFromIndex() を使用することで、現在の QListWidget 上で表示されているアイテムに対応する QListWidgetItem を正確に取得できます。

  3. 特定のアイテムのプロパティへのアクセス: 一度 QListWidgetItem オブジェクトを取得すれば、そのアイテムのテキスト、アイコン、状態(チェックされているかなど)といったプロパティにアクセスしたり、変更したりすることができます。

例えば、QListWidget で選択されたアイテムのテキストを取得したい場合、通常は selectedItems() を使用しますが、もし何らかの理由で QModelIndex から開始する必要がある場合、以下のように使用できます。

// 選択されているアイテムのモデルインデックスを取得 (例として、QItemSelectionModelから取得する場合)
QModelIndex selectedModelIndex = ui->listWidget->selectionModel()->currentIndex();

// QModelIndex から QListWidgetItem を取得
QListWidgetItem *item = ui->listWidget->itemFromIndex(selectedModelIndex);

if (item) {
    // 取得した QListWidgetItem のテキストを表示
    qDebug() << "Selected item text:" << item->text();
}


itemFromIndex が protected メンバーであるというコンパイルエラー

エラーメッセージ例
'itemFromIndex' is a protected member of 'QListWidget'

原因
QListWidget::itemFromIndex()protected メンバー関数であるため、QListWidget のサブクラス内から、または QListWidget のフレンドクラスからしか直接呼び出すことができません。通常のアプリケーションコードで ui->listWidget->itemFromIndex(index) のように直接呼び出そうとすると、このエラーが発生します。

トラブルシューティング

  • 行番号からアイテムを取得する (item(int row))
    QModelIndex から行番号を取得できる場合(例: index.row())、QListWidget::item(int row) 関数を使って直接 QListWidgetItem を取得できます。これは、最も一般的な回避策であり、推奨される方法です。

    void MyWidget::on_listWidget_clicked(const QModelIndex &index)
    {
        // QModelIndex から行番号を取得し、item() 関数を使用
        QListWidgetItem *item = ui->listWidget->item(index.row());
        if (item) {
            qDebug() << "クリックされたアイテムのテキスト:" << item->text();
        }
    }
    
  • QModelIndex を使わずに QListWidgetItem を取得する
    多くの場合、QModelIndex を直接扱う必要がないことがあります。例えば、QListWidget のシグナル (例: itemClicked(QListWidgetItem*)currentItemChanged(QListWidgetItem*, QListWidgetItem*)) を使用する場合、コールバック関数に直接 QListWidgetItem が渡されるため、itemFromIndex() を使う必要はありません。

  • QListWidget のサブクラスを作成する
    もし QListWidget の特定の動作をカスタマイズする必要がある場合、QListWidget を継承した独自のクラスを作成し、その中で itemFromIndex() を呼び出すのが最も適切な方法です。

戻り値が nullptr になる

原因
itemFromIndex() は、有効な QModelIndex が与えられた場合にのみ QListWidgetItem へのポインタを返します。以下のいずれかの状況で nullptr を返す可能性があります。

  • モデルが異なる
    QListWidget は内部的に独自のモデルを使用しています。もし別のモデル(例えば、QStandardItemModelQListView で使用している場合)から取得した QModelIndexQListWidget::itemFromIndex() に渡すと、期待通りに動作しない可能性があります。
  • 無効な QModelIndex を渡した
    QModelIndex が、存在しない行や列を指している場合(例: アイテムが削除された後も古いインデックスを使用している、または範囲外のインデックスを使用している)。

トラブルシューティング

  • モデルとビューの整合性を確認する
    QListWidget を使用している場合、基本的に QListWidgetItem を直接追加・削除するため、モデルとビューの不整合は起こりにくいですが、カスタムモデルを使用している場合は、モデルとビューの状態が同期しているかを確認してください。

  • イベントハンドラやシグナル/スロットの使用を見直す
    QListWidget から直接取得した QModelIndex (例: clicked(const QModelIndex &index) シグナルから渡されるもの) であれば通常は有効ですが、他のソースから QModelIndex を取得している場合は、その有効性を慎重に確認する必要があります。

  • QModelIndex::isValid() で有効性を確認する
    itemFromIndex() を呼び出す前に、渡す QModelIndex が有効であるかを確認します。

    void MyWidget::someFunction(const QModelIndex &index)
    {
        if (index.isValid()) {
            QListWidgetItem *item = ui->listWidget->itemFromIndex(index);
            if (item) {
                // アイテムが正常に取得された場合の処理
            } else {
                qWarning() << "QListWidgetItem が nullptr を返しました。インデックスが有効なアイテムを指していません。";
            }
        } else {
            qWarning() << "無効な QModelIndex が渡されました。";
        }
    }
    

取得した QListWidgetItem のプロパティが期待通りでない

原因
itemFromIndex() は正しく QListWidgetItem を返しているが、そのアイテムのテキストやデータが期待通りではない場合があります。これは itemFromIndex() 自体の問題ではなく、通常は以下のいずれかが原因です。

  • カスタムデータロールの扱いの誤り
    QListWidgetItem::setData() を使ってカスタムデータを保存している場合、取得する際に正しいデータロール(Qt::UserRole など)を指定しているか確認してください。
  • アイテムのデータが変更された後、UIが更新されていない
    モデル内のデータが変更されたにもかかわらず、QListWidget がその変更を反映していない可能性があります。明示的な更新が必要な場合(まれですが)、QListWidget::update()QListWidget::viewport()->update() を試すことができます。ただし、通常はモデル/ビューの仕組みによって自動的に更新されます。
  • 間違った QModelIndex を渡している
    意図しないアイテムの QModelIndex を渡してしまっている可能性があります。デバッガを使って index.row()index.column() を確認し、正しいアイテムを指しているかを確認してください。

トラブルシューティング

  • シグナルとスロットの接続を確認する
    イベントが発生した際に正しい QModelIndex または QListWidgetItem がシグナルによって渡されているかを確認します。
  • アイテムのデータ設定箇所を確認する
    QListWidgetItem が追加される際に、どのようなデータが設定されているか(テキスト、アイコン、カスタムデータなど)を確認します。
  • デバッガで QModelIndex の内容を確認する
    index.row()index.data() の値をデバッガで確認し、意図したアイテムのインデックスやデータが渡されているかを確認します。


Qt の QListWidget::itemFromIndex()protected メンバー関数であるため、通常のアプリケーションコードから直接呼び出すことはできません。そのため、itemFromIndex() を直接呼び出す例は、通常は QListWidget のサブクラス内でしか機能しません。

しかし、現実的なアプリケーションでこの関数に相当する機能(QModelIndex から QListWidgetItem を取得する)が必要になるケースは存在します。ここでは、以下の2つのパターンでコード例を説明します。

  1. QListWidget のサブクラス内で itemFromIndex() を使用する例 (この関数が protected であることを示す)
  2. itemFromIndex() の代替として item(int row) を使用する一般的な例 (より実用的で推奨される方法)

QListWidget のサブクラス内で itemFromIndex() を使用する例

この例では、MyListWidget という QListWidget のサブクラスを作成し、その中で itemFromIndex() を使用する方法を示します。

mylistwidget.h

#ifndef MYLISTWIDGET_H
#define MYLISTWIDGET_H

#include <QListWidget>
#include <QDebug> // デバッグ出力用

class MyListWidget : public QListWidget
{
    Q_OBJECT
public:
    explicit MyListWidget(QWidget *parent = nullptr);

protected:
    // QListWidget の clicked シグナルに対応するスロット
    // このスロットは QModelIndex を受け取ります
    void mousePressEvent(QMouseEvent *event) override; // 例としてクリックイベントをオーバーライド

signals:
    // 新しいシグナルを定義して、MyListWidget の外に QListWidgetItem を渡す
    void myItemClicked(QListWidgetItem *item);

private:
    // ここで itemFromIndex() を呼び出すプライベート関数
    // 実際に protected 関数を呼び出すのは、このクラスのメンバ関数からのみ
    void processIndex(const QModelIndex &index);
};

#endif // MYLISTWIDGET_H

mylistwidget.cpp

#include "mylistwidget.h"
#include <QModelIndex> // QModelIndex を使用するために必要
#include <QMouseEvent> // QMouseEvent を使用するために必要

MyListWidget::MyListWidget(QWidget *parent)
    : QListWidget(parent)
{
    // 通常、QListWidget::clicked(const QModelIndex &index) シグナルを
    // スロットに接続して使用しますが、ここでは例として mousePressEvent をオーバーライド
    // connect(this, &QListWidget::clicked, this, &MyListWidget::processIndex);
}

void MyListWidget::mousePressEvent(QMouseEvent *event)
{
    // クリックされた位置のモデルインデックスを取得
    QModelIndex index = indexAt(event->pos());

    if (index.isValid()) {
        processIndex(index);
    }

    // 基底クラスのイベントハンドラを呼び出すことを忘れない
    QListWidget::mousePressEvent(event);
}

void MyListWidget::processIndex(const QModelIndex &index)
{
    // ここが重要: protected メンバーである itemFromIndex() を
    // MyListWidget クラスのメンバ関数から呼び出す
    QListWidgetItem *item = itemFromIndex(index);

    if (item) {
        qDebug() << "MyListWidget::processIndex() - アイテムのテキスト:" << item->text();
        // 外部にアイテムを通知するためのシグナルを発行
        emit myItemClicked(item);
    } else {
        qWarning() << "MyListWidget::processIndex() - QListWidgetItem が取得できませんでした。";
    }
}

main.cpp (使用例)

#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QWidget>
#include "mylistwidget.h" // 作成したカスタムウィジェット

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

    QMainWindow window;
    QWidget *centralWidget = new QWidget(&window);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);

    MyListWidget *myListWidget = new MyListWidget(centralWidget);
    myListWidget->addItem("アイテム A");
    myListWidget->addItem("アイテム B");
    myListWidget->addItem("アイテム C");

    layout->addWidget(myListWidget);
    window.setCentralWidget(centralWidget);

    // MyListWidget から発行されるカスタムシグナルに接続
    QObject::connect(myListWidget, &MyListWidget::myItemClicked,
                     [](QListWidgetItem *clickedItem) {
        qDebug() << "メインウィンドウで受信: クリックされたアイテムのテキスト:" << clickedItem->text();
    });

    window.show();

    return a.exec();
}

説明
この例では、MyListWidget クラス内で mousePressEvent をオーバーライドし、クリックされた位置から QModelIndex を取得しています。その QModelIndexprocessIndex 関数に渡し、processIndex 関数内で itemFromIndex() を呼び出して対応する QListWidgetItem を取得しています。MyListWidgetQListWidget のサブクラスなので、protected メンバーである itemFromIndex() を呼び出すことができます。

これが、QListWidget::itemFromIndex() を直接呼び出すことなく、QModelIndex から QListWidgetItem を取得する最も一般的で推奨される方法です。QListWidgetclicked(const QModelIndex &index) シグナルなどを利用します。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QListWidget> // QListWidget を使用
#include <QModelIndex> // QModelIndex を使用
#include <QDebug> // デバッグ出力用

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    // QListWidget の clicked シグナルに対応するスロット
    void on_listWidget_clicked(const QModelIndex &index);

private:
    Ui::MainWindow *ui;
    QListWidget *listWidget; // UIファイルを使わない場合
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QVBoxLayout>

// UI ファイルを使用しない場合のコンストラクタの例
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // UIをセットアップ
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    setCentralWidget(centralWidget);

    listWidget = new QListWidget(this);
    layout->addWidget(listWidget);

    // アイテムの追加
    listWidget->addItem("リンゴ");
    listWidget->addItem("バナナ");
    listWidget->addItem("オレンジ");

    // QListWidget の clicked シグナルをスロットに接続
    // このシグナルはクリックされたアイテムの QModelIndex を渡します
    connect(listWidget, &QListWidget::clicked, this, &MainWindow::on_listWidget_clicked);
}

// UI ファイルを使用する場合のコンストラクタの例(ui->listWidget_clicked を想定)
/*
#include "ui_mainwindow.h" // UIファイルが生成するヘッダ

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // アイテムの追加
    ui->listWidget->addItem("リンゴ");
    ui->listWidget->addItem("バナナ");
    ui->listWidget->addItem("オレンジ");

    // UIデザイナーで自動接続 (on_listWidget_clicked) されるか、手動で接続
    // connect(ui->listWidget, &QListWidget::clicked, this, &MainWindow::on_listWidget_clicked);
}
*/

MainWindow::~MainWindow()
{
    // delete ui; // UIファイルを使用する場合
}

// QListWidget の clicked シグナルに対応するスロット
void MainWindow::on_listWidget_clicked(const QModelIndex &index)
{
    // QModelIndex から行番号 (row) を取得
    int row = index.row();

    // QListWidget::item(int row) を使って QListWidgetItem を取得
    // item() は protected ではなく public なので、どこからでも呼び出せる
    QListWidgetItem *clickedItem = listWidget->item(row); // UIファイルを使う場合は ui->listWidget->item(row);

    if (clickedItem) {
        qDebug() << "クリックされたアイテムのテキスト:" << clickedItem->text();
        qDebug() << "データ (Qt::UserRole):" << clickedItem->data(Qt::UserRole).toString();

        // 例えば、アイテムの背景色を変更する
        clickedItem->setBackground(Qt::yellow);
    } else {
        // これは通常、index.isValid() が false の場合に発生
        qWarning() << "アイテムが取得できませんでした。インデックスが無効な可能性があります。";
    }
}

説明
この例では、QListWidgetclicked(const QModelIndex &index) シグナルを使用しています。このシグナルはクリックされたアイテムの QModelIndex を提供します。 この QModelIndex から index.row() を呼び出すことで、アイテムの行番号を取得できます。 そして、QListWidget::item(int row) 関数(これは public メンバー関数です)に行番号を渡すことで、対応する QListWidgetItem を取得しています。この方法は itemFromIndex() を直接使うよりもはるかに一般的で、推奨される方法です。

  • QModelIndex から QListWidgetItem を取得する一般的な方法
    QModelIndex::row() で行番号を取得し、QListWidget::item(int row) を呼び出すのが最も一般的で実用的な方法です。これは public メンバー関数なので、どこからでも呼び出すことができます。
  • QListWidget::itemFromIndex() を直接使う場合
    QListWidget のサブクラス内からのみ可能です。これは、QListWidget の内部的な振る舞いをカスタマイズする際に役立ちます。


QListWidget::item(int row) を使用する(最も一般的で推奨される方法)

説明
QModelIndex オブジェクトから行番号 (row) を取得し、その行番号を使って QListWidget::item(int row) 関数を呼び出す方法です。QListWidget::item()public メンバー関数なので、どこからでも安全に呼び出すことができます。

使用場面

  • QItemSelectionModel などから取得した QModelIndex に基づいてアイテムを取得する際。
  • QListWidget::clicked(const QModelIndex &index) シグナルや QListWidget::doubleClicked(const QModelIndex &index) シグナルから渡される QModelIndex を処理する際。

コード例

#include <QApplication>
#include <QMainWindow>
#include <QListWidget>
#include <QVBoxLayout>
#include <QDebug>
#include <QModelIndex> // QModelIndex を使用するために必要

class MyWindow : public QMainWindow
{
    Q_OBJECT
public:
    MyWindow(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        QListWidget *listWidget = new QListWidget(this);
        setCentralWidget(listWidget);

        listWidget->addItem("最初のアイテム");
        listWidget->addItem("二番目のアイテム");
        listWidget->addItem("三番目のアイテム");
        listWidget->addItem("四番目のアイテム");

        // QListWidget の clicked シグナルに接続
        // このシグナルはクリックされたアイテムの QModelIndex を渡します
        connect(listWidget, &QListWidget::clicked,
                this, &MyWindow::onListItemClicked);
    }

private slots:
    void onListItemClicked(const QModelIndex &index)
    {
        if (index.isValid()) {
            // QModelIndex から行番号を取得
            int row = index.row();

            // QListWidget::item(int row) を使って QListWidgetItem を取得
            QListWidgetItem *item = qobject_cast<QListWidget*>(sender())->item(row);
            // あるいは、メンバ変数として QListWidget を持っている場合は直接アクセス
            // QListWidgetItem *item = this->myListWidget->item(row);

            if (item) {
                qDebug() << "クリックされたアイテムのテキスト (item(row) 経由):" << item->text();
                item->setBackground(Qt::yellow); // 例として背景色を変更
            } else {
                qWarning() << "アイテムが取得できませんでした。";
            }
        } else {
            qWarning() << "無効な QModelIndex が渡されました。";
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWindow w;
    w.show();
    return a.exec();
}

#include "main.moc" // moc ファイルのインクルード(Qt Creator以外で手動コンパイルする場合)

利点

  • ほとんどの一般的なユースケースに対応できる。
  • public な関数なので、どこからでも呼び出せる。
  • 最も直接的で理解しやすい。

QListWidget::currentItem() または QListWidget::selectedItems() を使用する

説明
特定のアイテムが選択されている場合や、現在フォーカスを持っているアイテムを取得したい場合に非常に便利です。QModelIndex を介さずに直接 QListWidgetItem を取得できます。

使用場面

  • コンテキストメニューの表示など、選択状態に依存する操作。
  • 現在ハイライトされているアイテムの情報を取得したい場合。
  • ユーザーが単一または複数のアイテムを選択した後に、そのアイテムを操作したい場合。

コード例

#include <QApplication>
#include <QMainWindow>
#include <QListWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QMenu>
#include <QMessageBox>

class MyWindow : public QMainWindow
{
    Q_OBJECT
public:
    MyWindow(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        QWidget *centralWidget = new QWidget(this);
        QVBoxLayout *layout = new QVBoxLayout(centralWidget);
        setCentralWidget(centralWidget);

        listWidget = new QListWidget(this);
        listWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); // 複数選択を可能にする
        layout->addWidget(listWidget);

        listWidget->addItem("アイテム 1");
        listWidget->addItem("アイテム 2");
        listWidget->addItem("アイテム 3");
        listWidget->addItem("アイテム 4");

        QPushButton *buttonCurrent = new QPushButton("現在のアイテムを表示", this);
        layout->addWidget(buttonCurrent);
        connect(buttonCurrent, &QPushButton::clicked,
                this, &MyWindow::showCurrentItem);

        QPushButton *buttonSelected = new QPushButton("選択されたアイテムを表示", this);
        layout->addWidget(buttonSelected);
        connect(buttonSelected, &QPushButton::clicked,
                this, &MyWindow::showSelectedItems);

        // コンテキストメニューの例
        listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(listWidget, &QListWidget::customContextMenuRequested,
                this, &MyWindow::showContextMenu);
    }

private slots:
    void showCurrentItem()
    {
        QListWidgetItem *currentItem = listWidget->currentItem();
        if (currentItem) {
            qDebug() << "現在のアイテム (currentItem()):" << currentItem->text();
        } else {
            qDebug() << "現在のアイテムはありません。";
        }
    }

    void showSelectedItems()
    {
        QList<QListWidgetItem *> selectedItems = listWidget->selectedItems();
        if (!selectedItems.isEmpty()) {
            qDebug() << "選択されたアイテム (selectedItems()):";
            for (QListWidgetItem *item : selectedItems) {
                qDebug() << "  -" << item->text();
            }
        } else {
            qDebug() << "選択されたアイテムはありません。";
        }
    }

    void showContextMenu(const QPoint &pos)
    {
        QListWidgetItem *clickedItem = listWidget->itemAt(pos); // ここも代替方法!
        if (clickedItem) {
            QMenu contextMenu(this);
            QAction *deleteAction = contextMenu.addAction("削除");
            QAction *renameAction = contextMenu.addAction("名前変更");

            QAction *selectedAction = contextMenu.exec(listWidget->mapToGlobal(pos));

            if (selectedAction == deleteAction) {
                QMessageBox::information(this, "アクション", clickedItem->text() + " を削除します。");
                delete listWidget->takeItem(listWidget->row(clickedItem)); // アイテムを削除
            } else if (selectedAction == renameAction) {
                QMessageBox::information(this, "アクション", clickedItem->text() + " の名前を変更します。");
                // 実際にはQInputDialogなどを使って名前変更処理を実装
            }
        }
    }

private:
    QListWidget *listWidget;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWindow w;
    w.show();
    return a.exec();
}

#include "main.moc"

利点

  • ユーザーのインタラクション(選択)に直接関連する処理に適している。
  • 非常に直感的で、コードが簡潔になる。

QListWidget::itemAt(const QPoint &p) を使用する

説明
ビューポート内の特定の座標 (QPoint) にある QListWidgetItem を取得します。主に、マウスイベント(例: mousePressEventcustomContextMenuRequested)やドラッグ&ドロップ操作で、ユーザーがクリックまたはドラッグしている位置のアイテムを特定したい場合に使用します。

使用場面

  • マウスホバーイベントで、マウスカーソル下のアイテム情報を表示する。
  • カスタムのドラッグ&ドロップ処理で、ドロップ先のアイテムを特定する。
  • 右クリックメニュー(コンテキストメニュー)を表示する際に、クリックされたアイテムを特定する。

コード例
上記の「選択されたアイテムを表示」の例の showContextMenu 関数内で listWidget->itemAt(pos) を使用しています。

// ... (上記コードの続き)
    void showContextMenu(const QPoint &pos)
    {
        // ビューポート座標 pos にあるアイテムを取得
        QListWidgetItem *clickedItem = listWidget->itemAt(pos);
        if (clickedItem) {
            QMenu contextMenu(this);
            QAction *deleteAction = contextMenu.addAction("削除");
            QAction *renameAction = contextMenu.addAction("名前変更");

            // グローバル座標に変換してメニューを表示
            QAction *selectedAction = contextMenu.exec(listWidget->mapToGlobal(pos));

            if (selectedAction == deleteAction) {
                qDebug() << clickedItem->text() << "を削除";
                // 削除処理...
            } else if (selectedAction == renameAction) {
                qDebug() << clickedItem->text() << "の名前を変更";
                // 名前変更処理...
            }
        }
    }
// ...

利点

  • マウスイベントと組み合わせて非常に強力なインタラクションを提供できる。
  • 物理的なスクリーン上の位置からアイテムを特定できる。

アイテムのデータロールを利用する (QListWidgetItem::data(), Qt::UserRole)

説明
直接 QListWidgetItem を取得する方法ではありませんが、アイテムに関連付けられたカスタムデータを取得・操作したい場合に非常に重要です。QListWidgetItem には、表示されるテキストやアイコン以外にも、任意のデータを保存できます。

使用場面

  • アイテム選択後、そのカスタムデータを元に次の処理を行いたい場合。

コード例

#include <QApplication>
#include <QMainWindow>
#include <QListWidget>
#include <QVBoxLayout>
#include <QDebug>
#include <QVariant> // QVariant を使用するために必要

class MyWindowWithData : public QMainWindow
{
    Q_OBJECT
public:
    MyWindowWithData(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        QListWidget *listWidget = new QListWidget(this);
        setCentralWidget(listWidget);

        // アイテムにカスタムデータを追加
        QListWidgetItem *item1 = new QListWidgetItem("商品 A");
        item1->setData(Qt::UserRole, QVariant(101)); // 商品ID
        listWidget->addItem(item1);

        QListWidgetItem *item2 = new QListWidgetItem("商品 B");
        item2->setData(Qt::UserRole, QVariant(102)); // 商品ID
        listWidget->addItem(item2);

        QListWidgetItem *item3 = new QListWidgetItem("商品 C");
        item3->setData(Qt::UserRole, QVariant(103)); // 商品ID
        listWidget->addItem(item3);

        connect(listWidget, &QListWidget::itemClicked,
                this, &MyWindowWithData::onListItemClicked);
    }

private slots:
    void onListItemClicked(QListWidgetItem *item)
    {
        if (item) {
            qDebug() << "クリックされたアイテムのテキスト:" << item->text();
            // カスタムデータ (Qt::UserRole) を取得
            int productId = item->data(Qt::UserRole).toInt();
            qDebug() << "関連する商品ID:" << productId;
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWindowWithData w;
    w.show();
    return a.exec();
}

#include "main.moc"
  • モデル/ビューの概念に沿ったデータの管理ができる。
  • 複雑な情報を各アイテムに効率的に格納できる。
  • 表示データと内部データを分離できる。