Exemple de colonne gelée
Cet exemple montre comment geler une colonne dans une page QTableView.

Nous utilisons le cadre modèle/vue de Qt pour mettre en œuvre un tableau dont la première colonne est gelée. Cette technique peut être appliquée à plusieurs colonnes ou lignes, à condition qu'elles se trouvent sur le bord du tableau.
Le cadre modèle/vue permet d'afficher un modèle de différentes manières à l'aide de plusieurs vues. Dans cet exemple, nous utilisons deux vues sur le même modèle - deux sites table views partageant un même modèle. La colonne gelée est un enfant de la vue principale de la table, et nous obtenons l'effet visuel souhaité en utilisant une technique de superposition qui sera décrite étape par étape dans les sections suivantes.

Définition de la classe FreezeTableWidget
La classe FreezeTableWidget possède un constructeur et un destructeur. Elle possède également deux membres privés : la vue de la table que nous utiliserons en tant que superposition et le modèle partagé pour les deux vues de la table. Deux slots sont ajoutés pour aider à maintenir la synchronisation des tailles de section, ainsi qu'une fonction pour réajuster la géométrie de la colonne gelée. En outre, nous réimplémentons deux fonctions : resizeEvent() et moveCursor().
class FreezeTableWidget : public QTableView { Q_OBJECT public: FreezeTableWidget(QAbstractItemModel * model); ~FreezeTableWidget(); protected: void resizeEvent(QResizeEvent *event) override; QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible) override; private: QTableView *frozenTableView; void init(); void updateFrozenTableGeometry(); private slots: void updateSectionWidth(int logicalIndex, int oldSize, int newSize); void updateSectionHeight(int logicalIndex, int oldSize, int newSize); };
Remarque : QAbstractItemView est l'ancêtre de QTableView.
Mise en œuvre de la classe FreezeTableWidget
Le constructeur prend model comme argument et crée une vue de table que nous utiliserons pour afficher la colonne gelée. Ensuite, dans le constructeur, nous invoquons la fonction init() pour mettre en place la colonne gelée. Enfin, nous connectons les signaux QHeaderView::sectionResized() (pour les en-têtes horizontaux et verticaux) aux emplacements appropriés. Cela permet de s'assurer que les sections de notre colonne gelée sont synchronisées avec les en-têtes. Nous connectons également les barres de défilement verticales afin que la colonne gelée défile verticalement avec le reste de notre tableau.
FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model) { setModel(model); frozenTableView = new QTableView(this); init(); //connect the headers and scrollbars of both tableviews together connect(horizontalHeader(),&QHeaderView::sectionResized, this, &FreezeTableWidget::updateSectionWidth); connect(verticalHeader(),&QHeaderView::sectionResized, this, &FreezeTableWidget::updateSectionHeight); connect(frozenTableView->verticalScrollBar(), &QAbstractSlider::valueChanged, verticalScrollBar(), &QAbstractSlider::setValue); connect(verticalScrollBar(), &QAbstractSlider::valueChanged, frozenTableView->verticalScrollBar(), &QAbstractSlider::setValue); }
Dans la fonction init(), nous nous assurons que la vue de tableau superposée responsable de l'affichage de la colonne gelée est correctement configurée. Cela signifie que cette vue de table, frozenTableView, doit avoir le même modèle que la vue de table principale. Toutefois, la différence est la suivante : la seule colonne visible de frozenTableView est sa première colonne ; nous masquons les autres à l'aide de setColumnHidden().
void FreezeTableWidget::init() { frozenTableView->setModel(model()); frozenTableView->setFocusPolicy(Qt::NoFocus); frozenTableView->verticalHeader()->hide(); frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); viewport()->stackUnder(frozenTableView);
En ce qui concerne l'ordre z de la colonne gelée, nous l'empilons au-dessus de la fenêtre de visualisation. Pour ce faire, nous appelons stackUnder() sur la fenêtre de visualisation. Pour des raisons d'apparence, nous empêchons la colonne de voler le focus de la vue principale de la table. Nous nous assurons également que les deux vues partagent le même modèle de sélection, de sorte qu'une seule cellule puisse être sélectionnée à la fois. Quelques autres ajustements sont effectués pour que notre application ait une bonne apparence et se comporte de manière cohérente avec la vue principale du tableau. Notez que nous avons appelé updateFrozenTableGeometry() pour que la colonne occupe le bon emplacement.
frozenTableView->setStyleSheet("QTableView { border: none;" "background-color: #8EDE21;" "selection-background-color: #999}"); //for demo purposes frozenTableView->setSelectionModel(selectionModel()); for (int col = 1; col < model()->columnCount(); ++col) frozenTableView->setColumnHidden(col, true); frozenTableView->setColumnWidth(0, columnWidth(0) ); frozenTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); frozenTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); frozenTableView->show(); updateFrozenTableGeometry(); setHorizontalScrollMode(ScrollPerPixel); setVerticalScrollMode(ScrollPerPixel); frozenTableView->setVerticalScrollMode(ScrollPerPixel); }
Lorsque vous redimensionnez la colonne gelée, la même colonne de la vue principale du tableau doit être redimensionnée en conséquence, afin d'assurer une intégration transparente. Pour ce faire, la nouvelle taille de la colonne est obtenue à partir de la valeur newSize du signal sectionResized(), émis par l'en-tête horizontal et l'en-tête vertical.
void FreezeTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize) { if (logicalIndex == 0){ frozenTableView->setColumnWidth(0, newSize); updateFrozenTableGeometry(); } } void FreezeTableWidget::updateSectionHeight(int logicalIndex, int /* oldSize */, int newSize) { frozenTableView->setRowHeight(logicalIndex, newSize); }
Puisque la largeur de la colonne gelée est modifiée, nous ajustons la géométrie du widget en conséquence en invoquant updateFrozenTableGeometry(). Cette fonction est expliquée plus en détail ci-dessous.
Dans notre réimplémentation de QTableView::resizeEvent(), nous appelons updateFrozenTableGeometry() après avoir invoqué l'implémentation de la classe de base.
void FreezeTableWidget::resizeEvent(QResizeEvent * event) { QTableView::resizeEvent(event); updateFrozenTableGeometry(); }
Lorsque nous naviguons dans le tableau à l'aide du clavier, nous devons nous assurer que la sélection en cours ne disparaît pas derrière la colonne gelée. Pour synchroniser cela, nous réimplémentons QTableView::moveCursor() et ajustons les positions de la barre de défilement si nécessaire, après avoir appelé l'implémentation de la classe de base.
QModelIndex FreezeTableWidget::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) { QModelIndex current = QTableView::moveCursor(cursorAction, modifiers); if (cursorAction == MoveLeft && current.column() > 0 && visualRect(current).topLeft().x() < frozenTableView->columnWidth(0) ){ const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x() - frozenTableView->columnWidth(0); horizontalScrollBar()->setValue(newValue); } return current; }
Le calcul de la géométrie de la colonne gelée est basé sur la géométrie de la table située en dessous, de sorte qu'elle apparaît toujours au bon endroit. L'utilisation de la fonction QFrame::frameWidth() permet de calculer correctement cette géométrie, quel que soit le style utilisé. Nous nous appuyons sur la géométrie de la fenêtre et des en-têtes pour définir les limites de la colonne gelée.
void FreezeTableWidget::updateFrozenTableGeometry() { frozenTableView->setGeometry(verticalHeader()->width() + frameWidth(), frameWidth(), columnWidth(0), viewport()->height()+horizontalHeader()->height()); }
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.