Qt

C++用の包括的なクロスプラットフォーム開発フレームワーク。豊富なUIコンポーネント、ネットワーク、データベース、グラフィックス機能を統合。QMLによる宣言的UI開発とC++の高性能を両立。商用・オープンソース両ライセンス提供。

デスクトップクロスプラットフォームC++GUI組み込み

GitHub概要

qt/qtbase

Qt Base (Core, Gui, Widgets, Network, ...)

スター2,747
ウォッチ118
フォーク1,088
作成日:2013年5月6日
言語:C++
ライセンス:-

トピックス

c-plus-plusqtqt5

スター履歴

qt/qtbase Star History
データ取得日時: 2025/7/15 22:54

フレームワーク

Qt

概要

Qtは、C++で書かれたクロスプラットフォーム・アプリケーション・フレームワークです。高性能なネイティブアプリケーションを、Windows、macOS、Linux、Android、iOS、組み込みシステムで統一されたコードベースから開発できます。

詳細

Qt(キュート)は、1995年から続く成熟したクロスプラットフォーム開発フレームワークです。2025年現在、世界70以上の業界で約100万人の開発者に使用され、AMD、欧州宇宙機関、ウォルト・ディズニー・アニメーション・スタジオ、シーメンス、パナソニックなどの大手企業で採用されています。

最新版のQt 6.9が2025年4月2日にリリースされ、継続的な開発と機能強化が行われています。Qtの最大の特徴は「Write Once, Deploy Everywhere」のコンセプトで、単一のコードベースから複数のプラットフォーム向けアプリケーションを効率的に開発できることです。

Mercedes BenzのMBUXユーザー体験、Adobe Photoshop Elements、Google Earth、TeamViewerなど、様々な著名アプリケーションでQtが使用されており、特にデスクトップアプリケーション、組み込みシステム、産業用アプリケーション分野で強固な地位を確立しています。

メリット・デメリット

メリット

  • 成熟したエコシステム: 30年近い歴史と豊富な機能
  • 真のクロスプラットフォーム: Windows、macOS、Linux、Android、iOS、組み込み対応
  • ネイティブ性能: ネイティブUIとハイパフォーマンス
  • 豊富なライブラリ: GUI、ネットワーク、データベース、マルチメディアなど包括的
  • Qt Designer: ビジュアルUIデザインツール
  • 幅広い業界採用: 大手企業での実績豊富
  • 強力なドキュメント: 詳細なドキュメントとサンプル
  • 企業サポート: The Qt Companyによる商用サポート

デメリット

  • 学習コストの高さ: C++の知識とQt特有のシステム理解が必要
  • ライセンス複雑性: LGPL/GPLとコマーシャルライセンスの選択
  • バイナリサイズ: 必要ライブラリによりアプリサイズが大きくなる場合
  • モバイル制約: iOS/Androidでの一部制限
  • リリースサイクル: メジャーアップデートでAPI変更の可能性

主要リンク

書き方の例

基本的なQtアプリケーション

// 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("クリックしてください", this);
        
        layout->addWidget(label);
        layout->addWidget(button);
        
        connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
        
        setWindowTitle("Qt アプリケーション");
        resize(300, 200);
    }

private slots:
    void onButtonClicked()
    {
        static int count = 0;
        auto *label = findChild<QLabel*>();
        if (label) {
            label->setText(QString("クリック回数: %1").arg(++count));
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    MainWindow window;
    window.show();
    
    return app.exec();
}

#include "main.moc"

シグナルとスロット

// 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秒間隔
}

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とC++の統合

// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "datamodel.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    
    QQmlApplicationEngine engine;
    
    // C++オブジェクトをQMLに公開
    DataModel dataModel;
    engine.rootContext()->setContextProperty("dataModel", &dataModel);
    
    // QMLファイルを読み込み
    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 アプリケーション"
    
    ColumnLayout {
        anchors.centerIn: parent
        spacing: 20
        
        Text {
            text: "データ: " + dataModel.currentValue
            font.pixelSize: 18
            Layout.alignment: Qt.AlignHCenter
        }
        
        Button {
            text: "データを更新"
            Layout.alignment: Qt.AlignHCenter
            onClicked: dataModel.updateValue()
        }
        
        Slider {
            from: 0
            to: 100
            value: dataModel.sliderValue
            Layout.fillWidth: true
            onValueChanged: dataModel.sliderValue = value
        }
        
        Text {
            text: "スライダー値: " + Math.round(dataModel.sliderValue)
            Layout.alignment: Qt.AlignHCenter
        }
    }
}

データベース操作

// 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() << "データベース接続エラー:" << db.lastError().text();
            return false;
        }
        
        // テーブル作成
        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() << "ユーザー追加エラー:" << 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;
    }
};

ネットワーク通信

// 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設定

cmake_minimum_required(VERSION 3.16)
project(MyQtApp LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Qt6を検索
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui Sql Network Qml Quick)

# 実行ファイルを作成
qt_add_executable(MyQtApp
    main.cpp
    mainwindow.cpp
    mainwindow.h
    counter.cpp
    counter.h
    datamodel.cpp
    datamodel.h
    networkclient.cpp
    networkclient.h
)

# QMLモジュールを追加
qt_add_qml_module(MyQtApp
    URI MyApp
    VERSION 1.0
    QML_FILES
        main.qml
)

# Qtライブラリをリンク
target_link_libraries(MyQtApp PRIVATE
    Qt6::Core
    Qt6::Widgets
    Qt6::Gui
    Qt6::Sql
    Qt6::Network
    Qt6::Qml
    Qt6::Quick
)

# プラットフォーム固有の設定
set_target_properties(MyQtApp PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)

プロジェクト作成と実行

# Qt Creatorでプロジェクト作成(推奨)
# Qt Creator -> File -> New Project -> Application

# または、CMakeでプロジェクト作成
mkdir my-qt-app && cd my-qt-app

# CMakeLists.txtとソースファイルを作成後
mkdir build && cd build
cmake ..
cmake --build .

# 実行
./MyQtApp  # Linux/macOS
# または
MyQtApp.exe  # Windows

# qmakeを使用する場合
qmake -project
qmake
make  # Linux/macOS
# または
nmake  # Windows