Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

Frozen Column Example

This example demonstrates how to freeze a column within a QTableView.

"Screenshot of the example"

We use Qt's model/view framework to implement a table with its first column frozen. This technique can be aplied to several columns or rows, as long as they are on the edge of the table.

The model/view framework allows for one model to be displayed in different ways using multiple views. For this example, we use two views on the same model - two table views sharing one model. The frozen column is a child of the main tableview, and we provide the desired visual effect using an overlay technique which will be described step by step in the coming sections.

FreezeTableWidget Class Definition

The FreezeTableWidget class has a constructor and a destructor. Also, it has two private members: the table view that we will use as an overlay, and the shared model for both table views. Two slots are added to help keep the section sizes in sync, as well as a function to readjust the frozen column's geometry. In addition, we reimplement two functions: resizeEvent() and moveCursor().

 class FreezeTableWidget : public QTableView {
      Q_OBJECT

 public:
       FreezeTableWidget(QAbstractItemModel * model);
       ~FreezeTableWidget();

 protected:
       virtual void resizeEvent(QResizeEvent *event);
       virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
       void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible);

 private:
       QTableView *frozenTableView;
       void init();
       void updateFrozenTableGeometry();

 private slots:
       void updateSectionWidth(int logicalIndex,int, int newSize);
       void updateSectionHeight(int logicalIndex, int, int newSize);

 };

Note: QAbstractItemView is QTableView's ancestor.

FreezeTableWidget Class Implementation

The constructor takes model as an argument and creates a table view that we will use to display the frozen column. Then, within the constructor, we invoke the init() function to set up the frozen column. Finally, we connect the QHeaderView::sectionResized() signals (for horizontal and vertical headers) to the appropriate slots. This ensures that our frozen column's sections are in sync with the headers. We also connect the vertical scrollbars together so that the frozen column scrolls vertically with the rest of our table.

 FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model)
 {
       setModel(model);
       frozenTableView = new QTableView(this);

       init();

       //connect the headers and scrollbars of both tableviews together
       connect(horizontalHeader(),SIGNAL(sectionResized(int,int,int)), this,
               SLOT(updateSectionWidth(int,int,int)));
       connect(verticalHeader(),SIGNAL(sectionResized(int,int,int)), this,
               SLOT(updateSectionHeight(int,int,int)));

       connect(frozenTableView->verticalScrollBar(), SIGNAL(valueChanged(int)),
               verticalScrollBar(), SLOT(setValue(int)));
       connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
               frozenTableView->verticalScrollBar(), SLOT(setValue(int)));

 }

In the init() function, we ensure that the overlay table view responsible for displaying the frozen column, is set up properly. This means that this table view, frozenTableView, has to have the same model as the main table view. However, the difference here is: frozenTableView's only visible column is its first column; we hide the others using setColumnHidden()

 void FreezeTableWidget::init()
 {
       frozenTableView->setModel(model());
       frozenTableView->setFocusPolicy(Qt::NoFocus);
       frozenTableView->verticalHeader()->hide();
       frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);

       viewport()->stackUnder(frozenTableView);

In terms of the frozen column's z-order, we stack it on top of the viewport. This is achieved by calling stackUnder() on the viewport. For appearance's sake, we prevent the column from stealing focus from the main tableview. Also, we make sure that both views share the same selection model, so only one cell can be selected at a time. A few other tweaks are done to make our application look good and behave consistently with the main tableview. Note that we called updateFrozenTableGeometry() to make the column occupy the correct spot.

       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);
 }

When you resize the frozen column, the same column on the main table view must resize accordingly, to provide seamless integration. This is accomplished by getting the new size of the column from the newSize value from the sectionResized() signal, emitted by both the horizontal and vertical header.

 void FreezeTableWidget::updateSectionWidth(int logicalIndex, int, int newSize)
 {
       if(logicalIndex==0){
             frozenTableView->setColumnWidth(0,newSize);
             updateFrozenTableGeometry();
       }
 }

 void FreezeTableWidget::updateSectionHeight(int logicalIndex, int, int newSize)
 {
       frozenTableView->setRowHeight(logicalIndex, newSize);
 }

Since the width of the frozen column is modified, we adjust the geometry of the widget accordingly by invoking updateFrozenTableGeometry(). This function is further explained below.

In our reimplementation of QTableView::resizeEvent(), we call updateFrozenTableGeometry() after invoking the base class implementation.

 void FreezeTableWidget::resizeEvent(QResizeEvent * event)
 {
       QTableView::resizeEvent(event);
       updateFrozenTableGeometry();
  }

When navigating around the table with the keyboard, we need to ensure that the current selection does not disappear behind the frozen column. To synchronize this, we reimplement QTableView::moveCursor() and adjust the scrollbar positions if needed, after calling the base class implementation.

 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;
 }

The frozen column's geometry calculation is based on the geometry of the table underneath, so it always appears in the right place. Using the QFrame::frameWidth() function helps to calculate this geometry correctly, no matter which style is used. We rely on the geometry of the viewport and headers to set the boundaries for the frozen column.

 void FreezeTableWidget::updateFrozenTableGeometry()
 {
       frozenTableView->setGeometry( verticalHeader()->width()+frameWidth(),
                                     frameWidth(), columnWidth(0),
                                     viewport()->height()+horizontalHeader()->height());
 }

Files:

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 5.0-snapshot
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web