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  ·  Toutes les fonctions  ·  Vues d'ensemble  · 

Flow Layout Example

Files:

The Flow Layout example demonstrates a custom layout that arranges child widgets from left to right and top to bottom in a top-level widget.

Screenshot of the Flow Layout example

The items are first laid out horizontally and then vertically when each line in the layout runs out of space.

The Flowlayout class mainly uses QLayout and QWidgetItem, while the Window uses QWidget and QLabel. We will only document the definition and implementation of FlowLayout below.

FlowLayout Class Definition

The FlowLayout class inherits QLayout. It is a custom layout class that arranges its child widgets horizontally and vertically.

 class FlowLayout : public QLayout
 {
 public:
     FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
     FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
     ~FlowLayout();

     void addItem(QLayoutItem *item);
     int horizontalSpacing() const;
     int verticalSpacing() const;
     Qt::Orientations expandingDirections() const;
     bool hasHeightForWidth() const;
     int heightForWidth(int) const;
     int count() const;
     QLayoutItem *itemAt(int index) const;
     QSize minimumSize() const;
     void setGeometry(const QRect &rect);
     QSize sizeHint() const;
     QLayoutItem *takeAt(int index);

 private:
     int doLayout(const QRect &rect, bool testOnly) const;
     int smartSpacing(QStyle::PixelMetric pm) const;

     QList<QLayoutItem *> itemList;
     int m_hSpace;
     int m_vSpace;
 };

We reimplement functions inherited from QLayout. These functions add items to the layout and handle their orientation and geometry.

We also declare two private methods, doLayout() and smartSpacing(). doLayout() lays out the layout items, while the smartSpacing() function calculates the spacing between them.

FlowLayout Class Implementation

We start off by looking at the constructor:

 FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
     : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
 {
     setContentsMargins(margin, margin, margin, margin);
 }

 FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
     : m_hSpace(hSpacing), m_vSpace(vSpacing)
 {
     setContentsMargins(margin, margin, margin, margin);
 }

In the constructor we call setContentsMargins() to set the left, top, right and bottom margin. By default, QLayout uses values provided by the current style (see QStyle::PixelMetric).

 FlowLayout::~FlowLayout()
 {
     QLayoutItem *item;
     while ((item = takeAt(0)))
         delete item;
 }

In this example we reimplement addItem(), which is a pure virtual function. When using addItem() the ownership of the layout items is transferred to the layout, and it is therefore the layout's responsibility to delete them.

 void FlowLayout::addItem(QLayoutItem *item)
 {
     itemList.append(item);
 }

addItem() is implemented to add items to the layout.

 int FlowLayout::horizontalSpacing() const
 {
     if (m_hSpace >= 0) {
         return m_hSpace;
     } else {
         return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
     }
 }

 int FlowLayout::verticalSpacing() const
 {
     if (m_vSpace >= 0) {
         return m_vSpace;
     } else {
         return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
     }
 }

We implement horizontalSpacing() and verticalSpacing() to get hold of the spacing between the widgets inside the layout. If the value is less than or equal to 0, this value will be used. If not, smartSpacing() will be called to calculate the spacing.

 int FlowLayout::count() const
 {
     return itemList.size();
 }

 QLayoutItem *FlowLayout::itemAt(int index) const
 {
     return itemList.value(index);
 }

 QLayoutItem *FlowLayout::takeAt(int index)
 {
     if (index >= 0 && index < itemList.size())
         return itemList.takeAt(index);
     else
         return 0;
 }

We then implement count() to return the number of items in the layout. To navigate the list of items we use itemAt() and takeAt() to remove and return items from the list. If an item is removed, the remaining items will be renumbered. All three functions are pure virtual functions from QLayout.

 Qt::Orientations FlowLayout::expandingDirections() const
 {
     return 0;
 }

expandingDirections() returns the Qt::Orientations in which the layout can make use of more space than its sizeHint().

 bool FlowLayout::hasHeightForWidth() const
 {
     return true;
 }

 int FlowLayout::heightForWidth(int width) const
 {
     int height = doLayout(QRect(0, 0, width, 0), true);
     return height;
 }

To adjust to widgets of which height is dependent on width, we implement heightForWidth(). The function hasHeightForWidth() is used to test for this dependency, and heightForWidth() passes the width on to doLayout() which in turn uses the width as an argument for the layout rect, i.e., the bounds in which the items are laid out. This rect does not include the layout margin().

 void FlowLayout::setGeometry(const QRect &rect)
 {
     QLayout::setGeometry(rect);
     doLayout(rect, false);
 }

 QSize FlowLayout::sizeHint() const
 {
     return minimumSize();
 }

 QSize FlowLayout::minimumSize() const
 {
     QSize size;
     QLayoutItem *item;
     foreach (item, itemList)
         size = size.expandedTo(item->minimumSize());

     size += QSize(2*margin(), 2*margin());
     return size;
 }

setGeometry() is normally used to do the actual layout, i.e., calculate the geometry of the layout's items. In this example, it calls doLayout() and passes the layout rect.

sizeHint() returns the preferred size of the layout and minimumSize() returns the minimum size of the layout.

 int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
 {
     int left, top, right, bottom;
     getContentsMargins(&left, &top, &right, &bottom);
     QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
     int x = effectiveRect.x();
     int y = effectiveRect.y();
     int lineHeight = 0;

doLayout() handles the layout if horizontalSpacing() or verticalSpacing() don't return the default value. It uses getContentsMargins() to calculate the area available to the layout items.

     QLayoutItem *item;
     foreach (item, itemList) {
         QWidget *wid = item->widget();
         int spaceX = horizontalSpacing();
         if (spaceX == -1)
             spaceX = wid->style()->layoutSpacing(
                 QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
         int spaceY = verticalSpacing();
         if (spaceY == -1)
             spaceY = wid->style()->layoutSpacing(
                 QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);

It then sets the proper amount of spacing for each widget in the layout, based on the current style.

         int nextX = x + item->sizeHint().width() + spaceX;
         if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
             x = effectiveRect.x();
             y = y + lineHeight + spaceY;
             nextX = x + item->sizeHint().width() + spaceX;
             lineHeight = 0;
         }

         if (!testOnly)
             item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));

         x = nextX;
         lineHeight = qMax(lineHeight, item->sizeHint().height());
     }
     return y + lineHeight - rect.y() + bottom;
 }

The position of each item in the layout is then calculated by adding the items width and the line height to the initial x and y coordinates. This in turn lets us find out whether the next item will fit on the current line or if it must be moved down to the next. We also find the height of the current line based on the widgets height.

 int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
 {
     QObject *parent = this->parent();
     if (!parent) {
         return -1;
     } else if (parent->isWidgetType()) {
         QWidget *pw = static_cast<QWidget *>(parent);
         return pw->style()->pixelMetric(pm, 0, pw);
     } else {
         return static_cast<QLayout *>(parent)->spacing();
     }
 }

smartSpacing() is designed to get the default spacing for either the top-level layouts or the sublayouts. The default spacing for top-level layouts, when the parent is a QWidget, will be determined by querying the style. The default spacing for sublayouts, when the parent is a QLayout, will be determined by querying the spacing of the parent layout.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 82
  2. Apercevoir la troisième dimension ou l'utilisation multithreadée d'OpenGL dans Qt, un article des Qt Quarterly traduit par Guillaume Belz 0
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  5. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  6. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
  7. 2017 : un quinquennat pour une nouvelle version du C++ ? Possible, selon Herb Sutter 6
Page suivante

Le Qt Labs au hasard

Logo

Quand il est juste de se tromper

Les Qt Labs sont les laboratoires des développeurs de Qt, où ils peuvent partager des impressions sur le framework, son utilisation, ce que pourrait être son futur. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

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 4.6
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