Containers in Qt5
last modified October 18, 2023
In this part of the Qt5 tutorial, we talk about containers in Qt5.
The following containers are mentioned: QVector
,
QList
, QStringList
, QSet
, and QMap
.
Containers are general-purpose classes that store items of a given type in memory. C++ has the Standard Template Library (STL), which has its own containers. It Qt, we can use Qt containers or STL containers.
There are two kinds of containers: sequential and associative. Sequential
containers store items one after another, whereas associative containers store
key-value pairs. QList
, QVector
,
QLinkedList
belong to sequential containers; QMap
and
QHash
are examples of associative containers.
Since in this chapter we create command line programs, we do not need the Qt GUI
module. We can add the QT -= gui
declaration to the project file.
Qt5 QVector
QVector
is a template class that provides a dynamic array. It
stores its items in adjacent memory locations and provides fast index-based
access. For large vectors, inserting operations are slower and
QList
container is recommended instead.
#include <QVector> #include <QTextStream> int main(void) { QTextStream out(stdout); QVector<int> vals = {1, 2, 3, 4, 5}; out << "The size of the vector is: " << vals.size() << endl; out << "The first item is: " << vals.first() << endl; out << "The last item is: " << vals.last() << endl; vals.append(6); vals.prepend(0); out << "Elements: "; for (int val : vals) { out << val << " "; } out << endl; return 0; }
The example works with a vector of integers.
QVector<int> vals = {1, 2, 3, 4, 5};
A vector of integers is created.
out << "The size of the vector is: " << vals.size() << endl;
The size
method gives the size of the vector—the number of items
in the vector.
out << "The first item is: " << vals.first() << endl;
The first item is retrieved with the first
method.
out << "The last item is: " << vals.last() << endl;
The last item of the vector is found with the last
method.
vals.append(6);
The append
method inserts the value at the end of the vector.
vals.prepend(0);
The prepend
method inserts the value at the beginning of the
vector.
for (int val : vals) { out << val << " "; }
We go through the vector in the for loop and print its contents.
$ ./myvector The size of the vector is: 5 The first item is: 1 The last item is: 5 Elements: 0 1 2 3 4 5 6
Qt5 QList
QList
is a container for creating a list of elements. It is similar
to QVector
. It stores a list of values and provides fast
index-based access as well as fast insertions and removals. It is one of the
most commonly used containers in Qt.
#include <QTextStream> #include <QList> #include <algorithm> int main(void) { QTextStream out(stdout); QList<QString> authors = {"Balzac", "Tolstoy", "Gulbranssen", "London"}; for (int i=0; i < authors.size(); ++i) { out << authors.at(i) << endl; } authors << "Galsworthy" << "Sienkiewicz"; out << "***********************" << endl; std::sort(authors.begin(), authors.end()); out << "Sorted:" << endl; for (QString author : authors) { out << author << endl; } return 0; }
The example presents the QList
container.
QList<QString> authors = {"Balzac", "Tolstoy", "Gulbranssen", "London"};
A QList
container is created. It stores the names of writers.
for (int i=0; i < authors.size(); ++i) { out << authors.at(i) << endl; }
In a for loop, we go through the container and print its elements. The
at
method returns the item at the given index.
authors << "Galsworthy" << "Sienkiewicz";
The << operator is used to insert two new items into the list.
std::sort(authors.begin(), authors.end());
The std::sort
method sorts the list in ascending order.
out << "Sorted:" << endl; for (QString author : authors) { out << author << endl; }
Now we print the sorted list.
$ ./mylist Balzac Tolstoy Gulbranssen London *********************** Sorted: Balzac Galsworthy Gulbranssen London Sienkiewicz Tolstoy
QStringList
QStringList
is a convenience container that provides a list of
strings. It has fast index-based access as well as fast insertions and removals.
#include <QTextStream> #include <QList> int main(void) { QTextStream out(stdout); QString string = "coin, book, cup, pencil, clock, bookmark"; QStringList items = string.split(","); QStringListIterator it(items); while (it.hasNext()) { out << it.next().trimmed() << endl; } return 0; }
In the example, we create a list of strings from a string and print the elements into the console.
QString string = "coin, book, cup, pencil, clock, bookmark"; QStringList items = string.split(",");
The QString's
split
method cuts the string into
substrings according to the provided separator. The substrings are returned in a
list.
QStringListIterator it(items);
QStringListIterator
provides a Java-style const iterator for
QStringList
.
while (it.hasNext()) { out << it.next().trimmed() << endl; }
With the created iterator, we print the elements of the list to the terminal.
The trimmed
method trims the white space in the string element.
$ ./mystringlist coin book cup pencil clock bookmark
Qt5 QSet
QSet
provides a single-valued mathematical set with fast lookups.
The values are stored in an unspecified order.
#include <QSet> #include <QList> #include <QTextStream> #include <algorithm> int main(void) { QTextStream out(stdout); QSet<QString> cols1 = {"yellow", "red", "blue"}; QSet<QString> cols2 = {"blue", "pink", "orange"}; out << "There are " << cols1.size() << " values in the set" << endl; cols1.insert("brown"); out << "There are " << cols1.size() << " values in the set" << endl; cols1.unite(cols2); out << "There are " << cols1.size() << " values in the set" << endl; for (QString val : cols1) { out << val << endl; } QList<QString> lcols = cols1.values(); std::sort(lcols.begin(), lcols.end()); out << "*********************" << endl; out << "Sorted:" << endl; for (QString val : lcols) { out << val << endl; } return 0; }
The QSet
is used to store colours in the example. It makes no sense
to have one colour value specified more times.
QSet<QString> cols1 = {"yellow", "red", "blue"}; QSet<QString> cols2 = {"blue", "pink", "orange"};
We have two sets of colour values. Blue colour is located in both sets.
out << "There are " << cols1.size() << " values in the set" << endl;
The size
method returns the size of the set.
cols1.insert("brown");
We add a new value to a set with the insert
method.
cols1.unite(cols2);
The unite
method performs a union of two sets. The
cols1
set will have all items inserted from cols2
set
that are not already present; in our case, all except for the colour blue.
for (QString val : cols1) { out << val << endl; }
With the for loop, we print all the items in the cols1
set.
QList<QString> lcols = cols1.values(); std::sort(lcols.begin(), lcols.end());
Sorting of a set is not supported. We can create a list out of a set and
sort it. The values
method returns a new QList
containing the elements in the set. The order of the elements in the
QList
is undefined.
$ ./myset There are 3 values in the set There are 4 values in the set There are 6 values in the set pink orange brown blue yellow red ********************* Sorted: blue brown orange pink red yellow
Qt5 QMap
QMap
is an associative array (dictionary) that stores key-value pairs.
It provides fast lookup of the value associated with a key.
#include <QTextStream> #include <QMap> int main(void) { QTextStream out(stdout); QMap<QString, int> items = { {"coins", 5}, {"books", 3} }; items.insert("bottles", 7); QList<int> values = items.values(); out << "Values:" << endl; for (int val : values) { out << val << endl; } QList<QString> keys = items.keys(); out << "Keys:" << endl; for (QString key : keys) { out << key << endl; } QMapIterator<QString, int> it(items); out << "Pairs:" << endl; while (it.hasNext()) { it.next(); out << it.key() << ": " << it.value() << endl; } return 0; }
In the example, we have a dictionary where we map string keys to integer values.
QMap<QString, int> items = { {"coins", 5}, {"books", 3} };
A QMap
is created. It has two pairs.
items.insert("bottles", 7);
A new pair is inserted with the insert
method.
QList<int> values = items.values(); out << "Values:" << endl; for (int val : values) { out << val << endl; }
We get all the values of the dictionary and print them to the console. The
values
method returns a list of map values.
QList<QString> keys = items.keys(); out << "Keys:" << endl; for (QString key : keys) { out << key << endl; }
Likewise, we print all the keys of the dictionary. The keys
method returns a list containing all the keys in the dictionary.
QMapIterator<QString, int> it(items);
QMapIterator
is a Java-style iterator for a QMap
.
It can be used to iterate over elements of a map.
while (it.hasNext()) { it.next(); out << it.key() << ": " << it.value() << endl; }
With the help of the iterator, we walk over all elements of the map. The
key
method returns the current key and the value
method returns the current value.
$ ./myqmap Values: 3 7 5 Keys: books bottles coins Pairs: books: 3 bottles: 7 coins: 5
Custom class sorting
In the following example, we are going to sort objects of a custom class
in a QList
.
class Book { public: Book(QString, QString); QString getAuthor() const; QString getTitle() const; private: QString author; QString title; };
This is the header file for our custom Book
class.
#include <QString> #include "book.h" Book::Book(QString auth, QString tit) { author = auth; title = tit; } QString Book::getAuthor() const { return author; } QString Book::getTitle() const { return title; }
This is the implementation of the Book
class; we have two
accessor methods.
#include <QTextStream> #include <QList> #include <algorithm> #include "book.h" bool compareByTitle(const Book &b1, const Book &b2) { return b1.getTitle() < b2.getTitle(); } int main(void) { QTextStream out(stdout); QList<Book> books = { Book("Jack London", "The Call of the Wild"), Book("Honoré de Balzac", "Father Goriot"), Book("Leo Tolstoy", "War and Peace"), Book("Gustave Flaubert", "Sentimental education"), Book("Guy de Maupassant", "Une vie"), Book("William Shakespeare", "Hamlet") }; std::sort(books.begin(), books.end(), compareByTitle); for (Book book : books) { out << book.getAuthor() << ": " << book.getTitle() << endl; } return 0; }
In the example, we create a few book objects and sort them with the
std::sort
algorithm.
bool compareByTitle(const Book &b1, const Book &b2) { return b1.getTitle() < b2.getTitle(); }
The compareByTitle
is a comparison function used by the sort
algorithm.
std::sort(books.begin(), books.end(), compareByTitle);
The std::sort
algorithm sorts the books in the list by the book's
title.
$ ./sortcustomclass Honoré de Balzac: Father Goriot William Shakespeare: Hamlet Gustave Flaubert: Sentimental education Jack London: The Call of the Wild Guy de Maupassant: Une vie Leo Tolstoy: War and Peace
In this chapter, we have worked with Qt's containers.