×
Namespaces

Variants
Actions

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.
139 page views in the last 30 days.
×