×
Namespaces

Variants
Actions
Revision as of 09:15, 17 October 2012 by hamishwillee (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Archived:Implementing a layout manager in Qt

From Nokia Developer Wiki
Jump to: navigation, search

Archived.pngArchived: This article is archived because it is not considered relevant for third-party developers creating commercial solutions today. If you think this article is still relevant, let us know by adding the template {{ReviewForRemovalFromArchive|user=~~~~|write your reason here}}.

Qt Quick should be used for all UI development on mobile devices. The approach described in this article (using C++ for the Qt app UI) is deprecated.

This code example shows how to create a custom layout manager Qt. A flow layout is used as an example layout.

Article Metadata
Code Example
Source file: Media:LMExample.zip
Tested with
Devices(s): 5800 XpressMusic
Compatibility
Platform(s): Qt
Symbian
S60 5th Edition
Article
Keywords: layout manager, QLayout
Created: taaidant (17 Feb 2009)
Last edited: hamishwillee (17 Oct 2012)

Contents

Usage

After you have subclassed the QLayout and implemented the needed methods, the layout works for any other QLayout.

Setup code in QMainWindow

QWidget* centralWidget = new QWidget;
setCentralWidget(centralWidget);
 
FlowLayout* mainLayout = new FlowLayout;
centralWidget->setLayout(mainLayout);

Adding widgets

QTextEdit* editor = new QTextEdit;
QPushButton* button = new QPushButton("Push me!");
QPushButton* button2 = new QPushButton("Push me too!");
QPushButton* button3 = new QPushButton("No! Not them... Push me!");
editor->setReadOnly(true);
 
centralWidget->layout()->addWidget(editor);
centralWidget->layout()->addWidget(button);
centralWidget->layout()->addWidget(button2);
centralWidget->layout()->addWidget(button3);

Header file

/*
* Copyright (c) 2009 Nokia Corporation
* Original example taken from:
* http://doc.trolltech.com/4.4/layouts-flowlayout.html
*/

 
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
 
#include <QLayout>
#include <QRect>
#include <QWidgetItem>
 
class FlowLayout : public QLayout
{
public:
FlowLayout(QWidget *parent, int margin = 0, int spacing = -1);
FlowLayout(int spacing = -1);
~FlowLayout();

Public members

Here are some basic methods you have to implement. Explanations to all of these methods can be found in the Qt documentation.

Item manipulation

     /* http://doc.trolltech.com/qlayout.html#addItem */
void addItem(QLayoutItem *item);
/* http://doc.trolltech.com/qlayout.html#count */
int count() const;
/* http://doc.trolltech.com/qlayout.html#itemAt */
QLayoutItem *itemAt(int index) const;
/* http://doc.trolltech.com/qlayout.html#takeAt */
QLayoutItem *takeAt(int index);

Layout and item geometry features

     /* http://doc.trolltech.com/qlayout.html#expandingDirections */
Qt::Orientations expandingDirections() const;
/* http://doc.trolltech.com/qlayoutitem.html#hasHeightForWidth */
bool hasHeightForWidth() const;
/* http://doc.trolltech.com/qlayoutitem.html#heightForWidth */
int heightForWidth(int) const;
/* http://doc.trolltech.com/qlayout.html#minimumSize */
QSize minimumSize() const;
/* http://doc.trolltech.com/qlayoutitem.html#setGeometry */
void setGeometry(const QRect &rect);
/* http://doc.trolltech.com/qlayoutitem.html#sizeHint */
QSize sizeHint() const;

Private members

 private:
/*
* Calculates the positions and sizes of the widgets in the layout,
* sets them and returns the height of the layout.
*/

int doLayout(const QRect &rect, bool testOnly) const;
 
/* Contains the items in this layout. */
QList<QLayoutItem *> itemList;
};
 
#endif

Source file

/*
* Copyright (c) 2009 Nokia Corporation
* Original example taken from:
* http://doc.trolltech.com/4.4/layouts-flowlayout.html
*/

 
#include <QtGui>
 
#include "flowlayout.h"
 
FlowLayout::FlowLayout(QWidget *parent, int margin, int spacing)
: QLayout(parent)
{
setMargin(margin);
setSpacing(spacing);
}
 
FlowLayout::FlowLayout(int spacing)
{
setSpacing(spacing);
}
 
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}

Public members

Item manipulation

/* Adds an item to end of the itemList */
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
 
/* Returns the amount of items layout contains. */
int FlowLayout::count() const
{
return itemList.size();
}
 
/* Returns item pointer for the given index. */
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
 
/* Takes and returns the item from the given index of the itemList */
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
else
return 0;
}

Layout and item geometry features

/* Would tell which way the layout expands if it were implemented. */
Qt::Orientations FlowLayout::expandingDirections() const
{
return 0;
}
 
/* Tells if the layout handles width to height calculations. */
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
 
/* Calculates height from width. */
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
 
/* Sets the layouts geometry. */
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
 
/* Returns the layouts preferred size. */
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
 
/*
* Returns the minimum size of the layout.
* First find the the biggest minimum size and add margin to that.
*/

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

Private members

Geometry calculations

Here the layout does all the "hard work". It calculates the layout and returns the height.

int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int x = rect.x();
int y = rect.y();
int lineHeight = 0;
 
QLayoutItem *item;
/* For every element in itemList */
foreach (item, itemList) {
/* Next x is the items sizeHint's width + spacing */
int nextX = x + item->sizeHint().width() + spacing();
/*
* If the next x - spacing is greater than rect's right coordinate and
* line height is greater than zero, start a new line.
*/

if (nextX - spacing() > rect.right() && lineHeight > 0) {
x = rect.x();
y = y + lineHeight + spacing();
nextX = x + item->sizeHint().width() + spacing();
lineHeight = 0;
}
 
/* Set the geometry for current widget. */
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
 
/* Prepare for the next item. */
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
/* Returns height for the layout. */
return y + lineHeight - rect.y();
}

Postconditions

You know the basics of implementing a layout manager.

Supplementary material

  • You can test the FlowLayout manager with a test application. The application is available for download at File:LMExample.zip.

See also

This page was last modified on 17 October 2012, at 09:15.
125 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×