Qt
Comprehensive cross-platform development framework for C++. Integrates rich UI components, networking, database, and graphics capabilities. Balances declarative UI development with QML and high C++ performance. Offers both commercial and open-source licenses.
GitHub Overview
Topics
Star History
Framework
Qt
Overview
Qt is a cross-platform application framework written in C++. Develop high-performance native applications for Windows, macOS, Linux, Android, iOS, and embedded systems from a unified codebase.
Details
Qt (pronounced "cute") is a mature cross-platform development framework that has been evolving since 1995. As of 2025, it is used by approximately 1 million developers across more than 70 industries worldwide, with adoption by major enterprises including AMD, European Space Agency, Walt Disney Animation Studios, Siemens, and Panasonic.
Qt 6.9, the latest version, was released on April 2, 2025, demonstrating ongoing development and feature enhancement. Qt's core philosophy is "Write Once, Deploy Everywhere," enabling efficient development of applications for multiple platforms from a single codebase.
Notable implementations include Mercedes Benz's MBUX user experience, Adobe Photoshop Elements, Google Earth, and TeamViewer. Qt has established a strong position particularly in desktop applications, embedded systems, and industrial applications.
Advantages & Disadvantages
Advantages
- Mature Ecosystem: Nearly 30 years of history with rich functionality
- True Cross-platform: Support for Windows, macOS, Linux, Android, iOS, and embedded systems
- Native Performance: Native UI and high performance
- Comprehensive Libraries: Includes GUI, networking, database, multimedia, and more
- Qt Designer: Visual UI design tool
- Wide Industry Adoption: Proven track record with major corporations
- Extensive Documentation: Detailed documentation and samples
- Enterprise Support: Commercial support from The Qt Company
Disadvantages
- High Learning Curve: Requires C++ knowledge and understanding of Qt-specific systems
- License Complexity: Choice between LGPL/GPL and commercial licenses
- Binary Size: Application size can become large with required libraries
- Mobile Limitations: Some restrictions on iOS/Android
- Release Cycle: Potential API changes with major updates
Key Links
- Qt Official Site
- Qt Official Documentation
- Qt Creator IDE
- Qt GitHub Repository
- Qt Community
- Qt Learning
Code Examples
Basic Qt Application
// main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr)
: QMainWindow(parent)
{
auto *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
auto *layout = new QVBoxLayout(centralWidget);
auto *label = new QLabel("Hello, Qt!", this);
auto *button = new QPushButton("Click me!", this);
layout->addWidget(label);
layout->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
setWindowTitle("Qt Application");
resize(300, 200);
}
private slots:
void onButtonClicked()
{
static int count = 0;
auto *label = findChild<QLabel*>();
if (label) {
label->setText(QString("Click count: %1").arg(++count));
}
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
#include "main.moc"
Signals and Slots
// counter.h
#include <QObject>
#include <QTimer>
class Counter : public QObject
{
Q_OBJECT
public:
explicit Counter(QObject *parent = nullptr);
public slots:
void start();
void stop();
void reset();
private slots:
void updateCount();
signals:
void countChanged(int count);
void finished();
private:
QTimer *m_timer;
int m_count;
int m_maxCount;
};
// counter.cpp
#include "counter.h"
Counter::Counter(QObject *parent)
: QObject(parent), m_count(0), m_maxCount(10)
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Counter::updateCount);
}
void Counter::start()
{
m_timer->start(1000); // 1 second interval
}
void Counter::stop()
{
m_timer->stop();
}
void Counter::reset()
{
m_count = 0;
emit countChanged(m_count);
}
void Counter::updateCount()
{
++m_count;
emit countChanged(m_count);
if (m_count >= m_maxCount) {
m_timer->stop();
emit finished();
}
}
QML and C++ Integration
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "datamodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// Expose C++ object to QML
DataModel dataModel;
engine.rootContext()->setContextProperty("dataModel", &dataModel);
// Load QML file
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
visible: true
width: 400
height: 300
title: "Qt QML Application"
ColumnLayout {
anchors.centerIn: parent
spacing: 20
Text {
text: "Data: " + dataModel.currentValue
font.pixelSize: 18
Layout.alignment: Qt.AlignHCenter
}
Button {
text: "Update Data"
Layout.alignment: Qt.AlignHCenter
onClicked: dataModel.updateValue()
}
Slider {
from: 0
to: 100
value: dataModel.sliderValue
Layout.fillWidth: true
onValueChanged: dataModel.sliderValue = value
}
Text {
text: "Slider value: " + Math.round(dataModel.sliderValue)
Layout.alignment: Qt.AlignHCenter
}
}
}
Database Operations
// database.cpp
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class DatabaseManager
{
public:
bool initializeDatabase()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("example.db");
if (!db.open()) {
qDebug() << "Database connection error:" << db.lastError().text();
return false;
}
// Create table
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS users ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name TEXT NOT NULL, "
"email TEXT UNIQUE NOT NULL)");
return true;
}
bool addUser(const QString &name, const QString &email)
{
QSqlQuery query;
query.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
query.addBindValue(name);
query.addBindValue(email);
if (!query.exec()) {
qDebug() << "User add error:" << query.lastError().text();
return false;
}
return true;
}
QStringList getAllUsers()
{
QStringList users;
QSqlQuery query("SELECT name, email FROM users");
while (query.next()) {
QString name = query.value(0).toString();
QString email = query.value(1).toString();
users << QString("%1 <%2>").arg(name, email);
}
return users;
}
};
Network Communication
// networkclient.h
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
class NetworkClient : public QObject
{
Q_OBJECT
public:
explicit NetworkClient(QObject *parent = nullptr);
void fetchData(const QString &url);
void postData(const QString &url, const QJsonObject &data);
signals:
void dataReceived(const QJsonObject &data);
void errorOccurred(const QString &error);
private slots:
void onReplyFinished();
private:
QNetworkAccessManager *m_manager;
};
// networkclient.cpp
#include "networkclient.h"
#include <QJsonDocument>
#include <QDebug>
NetworkClient::NetworkClient(QObject *parent)
: QObject(parent)
{
m_manager = new QNetworkAccessManager(this);
}
void NetworkClient::fetchData(const QString &url)
{
QNetworkRequest request(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = m_manager->get(request);
connect(reply, &QNetworkReply::finished, this, &NetworkClient::onReplyFinished);
}
void NetworkClient::postData(const QString &url, const QJsonObject &data)
{
QNetworkRequest request(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QJsonDocument doc(data);
QNetworkReply *reply = m_manager->post(request, doc.toJson());
connect(reply, &QNetworkReply::finished, this, &NetworkClient::onReplyFinished);
}
void NetworkClient::onReplyFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if (!reply) return;
if (reply->error() == QNetworkReply::NoError) {
QByteArray data = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(data);
emit dataReceived(doc.object());
} else {
emit errorOccurred(reply->errorString());
}
reply->deleteLater();
}
CMakeLists.txt Configuration
cmake_minimum_required(VERSION 3.16)
project(MyQtApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find Qt6
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui Sql Network Qml Quick)
# Create executable
qt_add_executable(MyQtApp
main.cpp
mainwindow.cpp
mainwindow.h
counter.cpp
counter.h
datamodel.cpp
datamodel.h
networkclient.cpp
networkclient.h
)
# Add QML module
qt_add_qml_module(MyQtApp
URI MyApp
VERSION 1.0
QML_FILES
main.qml
)
# Link Qt libraries
target_link_libraries(MyQtApp PRIVATE
Qt6::Core
Qt6::Widgets
Qt6::Gui
Qt6::Sql
Qt6::Network
Qt6::Qml
Qt6::Quick
)
# Platform-specific settings
set_target_properties(MyQtApp PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
Project Creation and Execution
# Create project with Qt Creator (recommended)
# Qt Creator -> File -> New Project -> Application
# Or create project with CMake
mkdir my-qt-app && cd my-qt-app
# Create CMakeLists.txt and source files, then:
mkdir build && cd build
cmake ..
cmake --build .
# Run the application
./MyQtApp # Linux/macOS
# or
MyQtApp.exe # Windows
# Using qmake
qmake -project
qmake
make # Linux/macOS
# or
nmake # Windows