Qtテーブルウィジェットのカスタマイズ:ヘッダーソート機能を拡張して3回目のクリックでデフォルトソートを復元

クライアントアプリケーションの開発において、ユーザーインターフェースの品質向上が求められています。特にデータ表示に使用されるテーブルウィジェットは、ソートやフィルタリングなどの高度な機能が重要です。この記事では、QtのQHeaderViewクラスを拡張し、3回連続クリック時にデフォルトの非ソート状態に戻るカスタムソート機能を実装する方法について説明します。

1. カスタムソートの概要

Qtの標準的なテーブルウィジェットには、列ごとの昇順・降順ソートがサポートされていますが、特定のビジネス要件に対応するために、さらに柔軟性のあるソート動作が必要になることがあります。例えば、以下のような動作を実現したい場合があります:

  • 1回目のクリックで降順ソート
  • 2回目のクリックで昇順ソート
  • 3回目のクリックでソート解除(非ソート状態)

さらに、一部の列に対してソートを無効化することも可能です。

2. 実装ステップ

2.1 列単位でのソート制御

まず、特定の列に対するソートを無効にするために、QHeaderViewクラスをサブクラス化し、mouseReleaseEventメソッドをオーバーライドします。


class CustomHeaderView : public QHeaderView {
    Q_OBJECT
public:
    explicit CustomHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr)
        : QHeaderView(orientation, parent), m_sortEnabled(true) {}

    void setSortEnabled(int logicalIndex, bool enabled) {
        m_sortMap[logicalIndex] = enabled;
    }

protected:
    void mouseReleaseEvent(QMouseEvent *event) override {
        int column = logicalIndexAt(event->pos().x());
        if (m_sortMap.contains(column) && !m_sortMap[column]) {
            setSectionsClickable(false);
            QHeaderView::mouseReleaseEvent(event);
            setSectionsClickable(true);
            return;
        }
        QHeaderView::mouseReleaseEvent(event);
    }

private:
    QMap m_sortMap;
};

2.2 3回クリックによるソート状態の管理

次に、3回連続クリックでソート状態をリセットするロジックを追加します。クリック回数と対応するソート状態を管理するために、内部変数を使用します。


void CustomHeaderView::mouseReleaseEvent(QMouseEvent *event) {
    QHeaderView::mouseReleaseEvent(event);

    int column = logicalIndexAt(event->pos().x());
    static QMap clickCounts; // クリック回数を記録

    if (!m_sortMap.contains(column) || m_sortMap[column]) {
        clickCounts[column]++;
        switch (clickCounts[column] % 3) {
        case 1: // 降順
            emit sortRequested(column, Qt::DescendingOrder);
            break;
        case 2: // 昇順
            emit sortRequested(column, Qt::AscendingOrder);
            break;
        case 0: // リセット
            emit resetSort(column);
            break;
        }
    } else {
        clickCounts[column] = 0; // 無効な列の場合、カウントをリセット
    }
}

3. テーブルモデル側での処理

最後に、テーブルモデルまたはプロキシモデル内でソートリクエストを処理します。


class CustomTableModel : public QAbstractTableModel {
    Q_OBJECT
public:
    void restoreDefaultSort() {
        beginResetModel();
        std::sort(m_data.begin(), m_data.end(), [](const auto &a, const auto &b) {
            return a.id < b.id; // デフォルトのソート基準
        });
        endResetModel();
    }

signals:
    void defaultSortRestored();

private:
    QVector<MyData> m_data;
};

4. 注意点

カスタムソートを実装する際には、以下の点に注意してください:

  • ソート状態の可視化(ソートアイコンの描画)を適切に行う必要がある。
  • 外部からのソート要求を正しくハンドリングするため、シグナル/スロット機構を活用する。

タグ: Qt QHeaderView CustomSorting

5月15日 18:55 投稿