By now, you might have already gone through some of the examples provided by Qt and have a rough idea on how to create a Qt application. However, most Qt examples are designed around a particular usage or to demonstrate a specific class. And often, it's unclear how to expand and scale them. The purpose of this post is to demonstrate how to structure and architect a typical reasonably large Qt application. We'll start from scratch by setting up the file structure and later on show how a MVC-variant can be used to separate the core components. By the time you've read through this post, you should have a pretty good understanding on how to organise your files and components and how to scale the project into a larger application.
We have now come to a point in the learning journey when we have to make an important decision. We've approached a junction that can lead us to two different paths. Which path we decide to follow will depend on our requirements and desired look and feel of the application. It will most likely be very costly and time consuming to turn back and change path half way through. We have to choose between the Qt Quick/QML-path and the Qt Widgets-path. This post will cover the differences between the two and guide you through when one might be preferred over the other in different scenarios.
Have you ever heard of Model-View-Controller, or MVC for short? If not - not to worry - as you might have never worked with a GUI toolkit before. But perhaps you've heard of the SoC principle, i.e. Separation of Concerns? Essentially MVC is a design pattern used in GUI applications which follows the SoC principle by isolating and decoupling different components. In other words, each component: the Model, the View and the Controller are addressing different concerns, which give developers a greater flexibility and reusage. MVC originates from smalltalks, and was formulated by Trygve Reenskaug. Although the design pattern is rather old, I dare say that most GUI toolkits rely on a variant of it, such as MVP and MVVM. Qt's MVC variant is called the Model/View which plays a central role in any data-driven Qt application. This post will discuss the importance of this pattern and how it's implemented in the Qt framework.
As a modern C++ developer, I'm sure you're striving to use raw pointers as much as you can. Handling raw allocations and deallocations are for the professionals, smart pointers are for the nit-witted programmers. As they say - the more Well... no. Please forgive me. However, in my defence, this is partially true for Qt. If you scan through the Qt examples you will see a lot of new
and delete
scattered all over the codebase the merrier. Right⸮new
and a few delete
. In this post we'll explore why this is the case and how memory is managed the Qt-way.
Envision you've decided to go solo and start an indie game studio to fulfil your lifelong dream - to design and create a turn-based strategy game. You begin your endeavour by outlining the different components and sketch on the overall architecture of the game. The game will have some units which can be moved and controlled by using the mouse. There will be an AI component which will perhaps kick in after the units have completed their movements. The AI will then decide how the enemies should respond. In other words, a sequence of actions need to happen: the mouse click, then the movement of units and then the response of the enemies. However, you probably don't want the mouse logic to directly depend on the unit-classes; it will be used for much more. For the same reason the unit-classes shouldn't need to rely on the AI nor the enemy logic; possibly the same AI will be used for many different enemies. I'm sure you're a great developer so you're aiming to decouple these different components. Nonetheless, the components need to communicate with each other and you need some kind of callback-mechanism. And this, ladies and gentlemen, this is where Qt's signals and slots comes to the rescue.
In the last post we learnt about the event loop and how and why you should avoid blocking it. Another concept that you might have already stumbled upon is the meta-object system. If you have gone through the compile output of a Qt project you should have seen some traces of it; the output looks a bit different compared to compiling standard C++ code. If you haven't done it already, try to compile one of the Qt examples. See if you can spot something unusual about the output. This is the second post in the series "Crash course in Qt for C++ developers" covering the Meta-object system (including QObject and MOC).
In a way to encourage more people to start using Qt I've decided to kick off yet another series: a crash course in Qt for C++ developers. The Qt documentation and the wiki is extremely well composed and contain a lot of information on how to get started and is an excellent resource when used as a reference manual. However, what I found lacking are the answers to the following questions "what is the gist of Qt?"; "what is the 20% that you need to know to develop 80% of the application?"; "what are the perhaps unknown unknowns?". The series aims to answer these.
Does your CMake projects look similar to the example below? If yes - I'm positive you'll find this post helpful as it's is especially composed for you. This post will cover the core of what's considered modern CMake and will be part of a blog post series.add_definitions("-Wall")
include_directories(${PROJECT_SOURCE_DIR}/src/)
set(CMAKE_CXX_FLAGS -std=c++11)
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)
If you try to copy a class that derives from a with Qt5 and using C++11 (supporting error: use of deleted function ‘MyClass::MyClass(const MyClass&)’ or with earlier versions: error: ‘QObject::QObject(const QObject&)’ is private within this context` This behaviour is by design. But why is the copy constructor (as well as the assignment operator) deleted? What if you still want to copy it? If it's not copyable is it then movable? The following post will examine these questions as well as explore whether it's a good practice to repeat the deletion in the custom subclass. Let's dive in!QObject
it will result in a compiler error, e.g.class MyClass : public QObject {
Q_OBJECT
} my_class;
auto my_class_copy = my_class;
=delete
):
The following post will dive into the world of containers and explore the ones Qt provides and how they compare to the standard library's (STL). The post will explore the different types and which ones are unique to each library. API, performance and some internal implementation details will also be covered. The goal of the post is to identify which library might be preferred over the other.