【保存版】Qt Widgetsで選択行をハイライトする方法:QListView::visualRegionForSelection()徹底解説


構文

QRegion QListView::visualRegionForSelection(const QItemSelection &selection) const;

引数

  • selection: 選択されたアイテムを表す QItemSelection オブジェクト

戻り値

選択されたアイテムの視覚的な領域を表す QRegion オブジェクト

詳細

QListView::visualRegionForSelection() 関数は、選択されたアイテムのモデルインデックスに基づいて視覚的な領域を計算します。その後、その領域はビューポートと交差させ、表示されている矩形のみが含まれるようにフィルター処理されます。

この関数は、アイテムが部分的に表示されている場合でも、選択されたアイテムの完全な視覚的な領域を返します。たとえば、アイテムの一部がビューポートの境界からはみ出ている場合、その部分も領域に含まれます。

次の例では、QListView ウィジェットで選択されているアイテムの視覚的な領域を赤い矩形でハイライトする方法を示します。

void highlightSelectedItems()
{
    QItemSelection selection = selectionModel()->selection();
    QRegion region = visualRegionForSelection(selection);

    QPainter painter(viewport());
    painter.setPen(Qt::red);
    painter.setBrush(Qt::NoBrush);
    painter.drawRegion(region);
}

この例では、まず selectionModel()->selection() を使用して、選択されたアイテムの QItemSelection オブジェクトを取得します。次に、visualRegionForSelection() 関数を使用して、選択されたアイテムの視覚的な領域を取得します。最後に、QPainter オブジェクトを使用して、赤い矩形で領域を描画します。

QListView::visualRegionForSelection() 関数は、QAbstractItemView クラスの仮想関数 visualRegionForSelection() を再実装しています。この関数は、QListView 以外のアイテムビューウィジェットでも使用できます。



class MyListView : public QListView
{
public:
    MyListView(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;
};

MyListView::MyListView(QWidget *parent) : QListView(parent)
{
    connect(selectionModel(), &QAbstractSelectionModel::selectionChanged, this, &MyListView::highlightSelectedItems);
}

void MyListView::paintEvent(QPaintEvent *event)
{
    QListView::paintEvent(event);

    QItemSelection selection = selectionModel()->selection();
    QRegion region = visualRegionForSelection(selection);

    QPainter painter(viewport());
    painter.setPen(Qt::red);
    painter.setBrush(Qt::NoBrush);
    painter.drawRegion(region);
}

例2: 選択されたアイテムのテキストを太字にする

この例では、QListView ウィジェットで選択されているアイテムのテキストを太字にする方法を示します。

class MyListView : public QListView
{
public:
    MyListView(QWidget *parent = nullptr);

protected:
    void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
};

MyListView::MyListView(QWidget *parent) : QListView(parent)
{
    connect(selectionModel(), &QAbstractSelectionModel::selectionChanged, this, &MyListView::selectionChanged);
}

void MyListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
    QModelIndexList indexes = selected.indexes();
    for (const QModelIndex &index : indexes) {
        QModelEditor modelEditor(index.model());
        modelEditor.setData(index, QVariant("<b>" + index.data().toString() + "</b>"));
    }
}

例3: 選択されたアイテムを別の色で表示する

この例では、QListView ウィジェットで選択されているアイテムを別の色で表示する方法を示します。

class MyListView : public QListView
{
public:
    MyListView(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;
};

MyListView::MyListView(QWidget *parent) : QListView(parent)
{
    connect(selectionModel(), &QAbstractSelectionModel::selectionChanged, this, &MyListView::updateStyle);
}

void MyListView::paintEvent(QPaintEvent *event)
{
    QListView::paintEvent(event);

    QItemSelection selection = selectionModel()->selection();
    QRegion region = visualRegionForSelection(selection);

    QPainter painter(viewport());
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(255, 255, 200));
    painter.drawRegion(region);
}


選択されたアイテムのインデックスに基づいて矩形を計算する

QListView::selectedIndexes() 関数を使用して、選択されたアイテムのモデルインデックスのリストを取得できます。その後、これらのインデックスを使用して、各アイテムの矩形を個別に計算できます。

QRegion region;
QModelIndexList indexes = selectionModel()->selectedIndexes();
for (const QModelIndex &index : indexes) {
    QRect rect = index.data(Qt::DisplayRole).boundingRect();
    region += rect;
}

この方法は、QListView::visualRegionForSelection() 関数よりも柔軟性が高く、選択されたアイテムの一部のみをハイライトしたい場合などに役立ちます。

カスタムデリゲートを使用する

カスタムデリゲートを使用すると、選択されたアイテムの外観を完全に制御できます。デリゲートの paint() メソッド内で、選択されたアイテムの視覚的な領域を描画するカスタムコードを実装できます。

class MyDelegate : public QItemDelegate
{
public:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (option.state & QStyle::State_Selected) {
        // 選択されたアイテムの視覚的な領域を描画
        QRect rect = option.rect;
        painter.setPen(Qt::red);
        painter.setBrush(Qt::NoBrush);
        painter.drawRect(rect);
    } else {
        // デフォルトのデリゲートを使用
        QItemDelegate::paint(painter, option, index);
    }
}

この方法は、選択されたアイテムに対して高度な視覚効果を適用したい場合に役立ちます。

アイテムビューのスタイルシートを使用する

Qt スタイルシートを使用すると、アイテムビューの外観をカスタマイズできます。選択されたアイテムの状態に基づいてスタイルを定義することで、視覚的な領域をハイライトできます。

QListView::item:selected {
    background-color: #ff0000;
}

この方法は、シンプルで効果的な方法ですが、QListView::visualRegionForSelection() 関数ほど柔軟ではありません。

最適な方法の選択

使用する方法は、要件によって異なります。

  • 選択されたアイテムの一部のみをハイライトしたい場合や、カスタムの視覚効果を適用したい場合は、他の方法を使用する必要があります。
  • 単純に選択されたアイテムをハイライトしたい場合は、QListView::visualRegionForSelection() 関数が最適です。