Qtウィジェットでプログラミングを始めよう

Qtウィジェットベースのメモ帳アプリケーションのチュートリアルです。

このトピックでは、C++とQt Widgetsモジュールを使って簡単なメモ帳アプリケーションを実装することで、Qtの基本的な知識を学びます。このアプリケーションは小さなテキストエディタで、テキストファイルを作成したり、保存したり、印刷したり、再度開いて編集したりすることができます。また、使用するフォントを設定することもできます。

"Notepad application"

サンプルを実行する

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

メモ帳プロジェクトの作成

Qt Creator で新しいプロジェクトをセットアップするには、プロジェクト作成プロセスをステップバイステップでガイドするウィザードを使用します。ウィザードは、特定のタイプのプロジェクトに必要な設定の入力を促し、プロジェクトを作成します。

注意: Qt Creator の UI テキストと生成されるファイルの内容は、使用する Qt Creator のバージョンによって異なります。

"Qt Creator New Project dialog"

メモ帳プロジェクトを作成するには、File >New Project >Application (Qt) >Qt Widgets Application >Choose を選択し、ウィザードの指示に従います。Class Information ダイアログで、クラス名としてNotepadと入力し、ベース・クラスとしてQMainWindow を選択します。

"Class Information Dialog"

Qt Widgets Application ウィザードは、メイン・ソース・ファイルとユーザー・インターフェイス(メモ帳ウィジェット)を指定するファイル・セットを含むプロジェクトを作成します:

  • CMakeLists.txt - プロジェクト・ファイル。
  • main.cpp - アプリケーションのメイン・ソース・ファイル。
  • notepad.cpp - メモ帳ウィジェットのnotepadクラスのソース・ファイル。
  • notepad.h - メモ帳ウィジェットのメモ帳クラスのヘッダ・ファイルです。
  • notepad.ui - メモ帳ウィジェットのUIフォーム。

これらのファイルには、プロジェクトをビルドして実行するために必要なボイラープレート・コードが含まれています。次のセクションで、ファイルの内容を詳しく見ていきましょう。

詳細はこちら

についてここでは
Qt Creator の使い方Qt Creator
Qt Creator でその他のアプリケーションを作成するQt Creator チュートリアル

メインソースファイル

ウィザードは main.cpp ファイルに以下のコードを生成します:

#include "notepad.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Notepad w;
    w.show();
    return a.exec();
}

コードを一行ずつ見ていきましょう。以下の行には、メモ帳ウィジェットのヘッダーファイルとQApplication が含まれています。すべての Qt クラスには、その名前にちなんだヘッダーファイルがあります。

#include "notepad.h"

#include <QApplication>

次の行は、すべてのCおよびC++ベースのアプリケーションのエントリポイントであるmain関数を定義しています:

int main(int argc, char *argv[])

次の行では、QApplication オブジェクトを作成しています。このオブジェクトはアプリケーション全体のリソースを管理し、Qtウィジェットを使用するQtプログラムを実行するために必要です。これは、argv で実行されるargc コマンドライン引数を持つアプリケーション・オブジェクトを構築します(Qtウィジェットを使用しないGUIアプリケーションでは、代わりにQGuiApplication を使用できます)。

    QApplication a(argc, argv);

次の行ではメモ帳オブジェクトを作成しています。これはウィザードがクラスとUIファイルを作成したオブジェクトです。ユーザー・インターフェースには、Qt ではwidgets と呼ばれる視覚的な要素が含まれています。ウィジェットの例としては、テキスト編集、スクロール・バー、ラベル、ラジオ・ボタンなどがあります。ウィジェットは他のウィジェットのコンテナにもなります。例えば、ダイアログやメイン・アプリケーション・ウィンドウなどです。

    Notepad w;

次の行では、メモ帳ウィジェットが独自のウィンドウで表示されています。ウィジェットはコンテナとしても機能します。この例として、QMainWindow があります。 には、複数のタイプのウィジェットが含まれていることがよくあります。ウィジェットは、デフォルトでは表示されません。関数show() は、ウィジェットを表示します。

    w.show();

次の行は、QApplication をイベントループに入れます。Qt アプリケーションが実行されているとき、イベントが生成され、アプリケーションのウィジェットに送られます。イベントの例としては、マウスの押下やキーのストロークなどがあります。

    return a.exec();

詳細はこちら

Qtについて以下
ウィジェットとウィンドウのジオメトリウィンドウとダイアログウィジェット
イベントとイベント処理イベントシステム

UIのデザイン

ウィザードは XML 形式のユーザーインターフェース定義を生成します: notepad.ui。notepad.ui ファイルを Qt Creator で開くと、自動的に統合された Qt Widgets Designer で開きます。

アプリケーションをビルドするとき、Qt Creator は QtUser Interface Compiler (uic)を起動し、.ui ファイルを読み込んで対応する C++ ヘッダファイル ui_notepad.h を作成します。

Qt ウィジェットデザイナーの使用

ウィザードは、QMainWindow を使用するアプリケーションを作成します。 このアプリケーションには独自のレイアウトがあり、メニューバー、ドックウィジェット、ツールバー、ステータスバーを追加することができます。中央の領域には、どのような種類のウィジェットでも配置できます。ウィザードはメモ帳ウィジェットをここに配置します。

Qt Widgets Designer でウィジェットを追加するには:

  1. Qt CreatorEdit モードで、Projects ビューの notepad.ui ファイルをダブルクリックして、統合された Qt Widgets Designer でファイルを起動します。
  2. ウィジェット Text Edit (QTextEdit) をフォームにドラッグ&ドロップします。
  3. Ctrl+A(またはCmd+A) を押してウィジェットを選択し、Lay out Vertically (またはCtrl+L) をクリックして縦書きレイアウト (QVBoxLayout) を適用します。
  4. Ctrl+S(またはCmd+S)を押して変更を保存します。

これで、Qt Widgets Designer で UI が以下のように表示されます:

生成された XML ファイルはコードエディターで見ることができます:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Notepad</class>
 <widget class="QMainWindow" name="Notepad">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>400</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Notepad</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTextEdit" name="textEdit"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menuBar">
    ...

次の行は XML 宣言で、ドキュメントで使用する XML バージョンと文字エンコーディングを指定します:

<?xml version="1.0" encoding="UTF-8"?>

ファイルの残りの部分では、メモ帳ウィジェットを定義するui 要素を指定します:

<ui version="4.0">

UIファイルは、メモ帳クラスのヘッダーとソース・ファイルとともに使用されます。残りのUIファイルについては、後のセクションで説明します。

メモ帳ヘッダーファイル

ウィザードは、必要な#include、コンストラクタ、デストラクタ、Uiオブジェクトを含むメモ帳クラスのヘッダーファイルを生成しました。ファイルは以下のようになっています:

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class Notepad;
}
QT_END_NAMESPACE

class Notepad : public QMainWindow
{
    Q_OBJECT

public:
    explicit Notepad(QWidget *parent = nullptr);
    ~Notepad();

private:
    Ui::Notepad *ui;
    QString currentFile;
};

次の行は、メイン・アプリケーション・ウィンドウを提供するQMainWindow

#include <QMainWindow>

これは、uic ツールによって .ui ファイルから生成される UI クラスの標準名前空間です:

namespace Ui {
class Notepad;
}

クラス宣言にはQ_OBJECT マクロが含まれています。クラス宣言にはQObject マクロが含まれています。このマクロはクラス定義で最初に来る必要があり、このクラスを として宣言します。当然、QObject も継承する必要があります。QObject は、通常のC++クラスにいくつかの機能を追加します。特に、クラス名とスロット名を実行時に問い合わせることができます。また、スロットのパラメータ型を照会して呼び出すこともできます。

class Notepad : public QMainWindow
{
    Q_OBJECT

次の行は、parent というデフォルト引数を持つコンストラクタを宣言しています。値0は、ウィジェットに親がない(トップレベル・ウィジェットである)ことを示します。

public:
    explicit Notepad(QWidget *parent = nullptr);

次の行は、オブジェクトがライフサイクル中に獲得したリソースを解放するための仮想デストラクタを宣言しています。C++ の命名規則では、デストラクタは、関連するクラスと同じ名前にチルダ(~)を付加します。QObject では、ベースクラスへのポインタを通してオブジェクトが削除されたときに、派生クラスのデストラクタが適切に呼び出されるように、デストラクタは仮想です。

    ~Notepad();

次の行は、メモ帳UIクラスへのポインタであるメンバ変数を宣言しています。メンバ変数は特定のクラスに関連付けられ、そのクラスのすべてのメソッドにアクセスできます。

private:
    Ui::Notepad *ui;
    QString currentFile;
};
メモ帳ソース・ファイル

ウィザードが生成したメモ帳クラスのソース・ファイルは以下のようになります:

#include "notepad.h"
#include "ui_notepad.h"

Notepad::Notepad(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Notepad)
{
    ui->setupUi(this);

}

以下の行には、ウィザードによって生成されたメモ帳クラス・ヘッダー・ファイルと、uic ツールによって生成された UI ヘッダー・ファイルが含まれています:

#include "notepad.h"
#include "ui_notepad.h"

次の行は、Notepad コンストラクタを定義しています:

Notepad::Notepad(QWidget *parent) :

次の行では、メモ帳クラスのベース・クラスであるQMainWindow コンストラクタを呼び出しています:

    QMainWindow(parent),

次の行では、UIクラスのインスタンスを作成し、ui メンバに割り当てています:

    ui(new Ui::Notepad)

次の行でUIをセットアップします:

{
    ui->setupUi(this);

デストラクタでは、ui を削除します:

Notepad::~Notepad()
{
    delete ui;
}
プロジェクト・ファイル

ウィザードは、次のプロジェクト・ファイルCMakeLists.txt を生成します:

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

cmake_minimum_required(VERSION 3.16)
project(notepad LANGUAGES CXX)

find_package(Qt6
    REQUIRED COMPONENTS Core Gui Widgets
    OPTIONAL_COMPONENTS PrintSupport
)

qt_standard_project_setup()

qt_add_executable(notepad
    main.cpp
    notepad.cpp notepad.h notepad.ui
)

set_target_properties(notepad PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)

target_link_libraries(notepad PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Widgets
)

if(TARGET Qt6::PrintSupport)
    target_link_libraries(notepad PRIVATE Qt6::PrintSupport)
endif()

# Resources:
set(notepad_resource_files
    "images/bold.png"
    "images/copy.png"
    "images/create.png"
    "images/cut.png"
    "images/edit_redo.png"
    "images/edit_undo.png"
    "images/exit.png"
    "images/font.png"
    "images/info.png"
    "images/italic.png"
    "images/new.png"
    "images/open.png"
    "images/paste.png"
    "images/pencil.png"
    "images/print.png"
    "images/save.png"
    "images/save_as.png"
    "images/underline.png"
)

qt_add_resources(notepad "notepad"
    PREFIX
        "/"
    FILES
        ${notepad_resource_files}
)

install(TARGETS notepad
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET notepad
    OUTPUT_SCRIPT deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

プロジェクト・ファイルは、プロジェクトに含まれるソース・ファイル、ヘッダー・ファイル、UIファイルを指定します。

詳細はこちら

プロジェクトについてここで
Qt ウィジェット・デザイナーを使用するQt Widgets Designerマニュアル
レイアウトレイアウト管理ウィジェットとレイアウトレイアウトの例
Qt 付属のウィジェットQt ウィジェットギャラリー
メインウィンドウとメインウィンドウクラスアプリケーションのメインウィンドウメインウィンドウの例
QObjects と Qt オブジェクトモデル(これは Qt を理解するために不可欠です)オブジェクトモデル
qmake と Qt ビルドシステムqmakeマニュアル

ユーザーインタラクションの追加

エディタに機能を追加するために、ツールバーにメニュー項目とボタンを追加することから始めます。

Type Here」をクリックし、「New」、「Open」、「Save」、「Save as」、「Print」、「Exit」のオプションを追加します。これで下のアクションエディターに5つの行ができます。アクションをスロットに接続するには、アクションを右クリックして、Go to slot >triggered() を選択し、指定されたスロットのコードを完成させます。

アクションをツールバーにも追加したい場合は、それぞれのQAction にアイコンを割り当て、QAction をツールバーにドラッグします。アイコンを割り当てるには、アクションのIconプロパティにアイコン名を入力します。QAction がツールバーにドラッグされると、アイコンをクリックすることで関連するスロットが起動します。

newDocument() メソッドを完成させる:

void Notepad::newDocument()
{
    currentFile.clear();
    ui->textEdit->setText(QString());
}

currentFile 変数は現在編集中のファイルを含むグローバル変数で、clear() はテキストバッファをクリアします。currentFile 変数はnotepad.hのprivateパートで定義されている:

private:
    Ui::Notepad *ui;
    QString currentFile;
ファイルを開く

notepad.ui で、actionOpen を右クリックし、Go to Slot を選択する。

完全メソッドopen().

void Notepad::open()
{
    QString fileName = QFileDialog::getOpenFileName(this, "Open the file");
    if (fileName.isEmpty())
        return;
    QFile file(fileName);
    currentFile = fileName;
    if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot open file: " + file.errorString());
        return;
    }
    setWindowTitle(fileName);
    QTextStream in(&file);
    QString text = in.readAll();
    ui->textEdit->setText(text);
    file.close();
}

QFileDialog::getOpenFileName ファイルを選択するダイアログが開きます。 オブジェクト は、選択された をパラメーターとして持っています。選択されたファイルは、後の目的のためにグローバル変数 にも格納されます。 でファイルを読み取り専用のテキスト・ファイルとして開く。オープンできない場合は警告が出され、プログラムは停止する。QFile myfile file_name currentFile file.open

パラメータmyfile に対してQTextStream instream を定義する。ファイルmyfile の内容はQString text にコピーされる。setText(text) はエディターのバッファをtext で満たす。

ファイルの保存

actionSave を右クリックし、Go to Slot を選択します。

void Notepad::save()
{
    QString fileName;
    // If we don't have a filename from before, get one.
    if (currentFile.isEmpty()) {
        fileName = QFileDialog::getSaveFileName(this, "Save");
        if (fileName.isEmpty())
            return;
        currentFile = fileName;
    } else {
        fileName = currentFile;
    }
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
        return;
    }
    setWindowTitle(fileName);
    QTextStream out(&file);
    QString text = ui->textEdit->toPlainText();
    out << text;
    file.close();
}

QFile オブジェクト はグローバル変数 にリンクされています。 を開けない場合、エラーメッセージが表示され、メソッドは停止する。 を作成します。エディタ・バッファの内容はプレーン・テキストに変換され、 に書き込まれます。myfile current_file myfile QTextStream outstream outstream

別の名前でファイルを保存する
void Notepad::saveAs()
{
    QString fileName = QFileDialog::getSaveFileName(this, "Save as");
    if (fileName.isEmpty())
        return;
    QFile file(fileName);

    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
        return;
    }
    currentFile = fileName;
    setWindowTitle(fileName);
    QTextStream out(&file);
    QString text = ui->textEdit->toPlainText();
    out << text;
    file.close();
}

これはファイルの保存と同じ手順であるが、唯一の違いは、作成するファイルの新しいファイル名を入力する必要があることである。

ファイルの印刷

印刷機能を使いたい場合は、PrintSupport をプロジェクト・ファイルに追加する必要があります:

find_package(Qt6
    REQUIRED COMPONENTS Core Gui Widgets
    OPTIONAL_COMPONENTS PrintSupport
)

notepad.cpp で、printDev という QPrinter オブジェクトを宣言します:

void Notepad::print()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
    QPrinter printDev;
#if QT_CONFIG(printdialog)
    QPrintDialog dialog(&printDev, this);
    if (dialog.exec() == QDialog::Rejected)
        return;
#endif // QT_CONFIG(printdialog)
    ui->textEdit->print(&printDev);
#endif // QT_CONFIG(printer)
}

プリンタ・ダイアログ・ボックスを起動し、選択したプリンタをオブジェクトprintDev に格納します。Cancel をクリックしてプリンタを選択しなかった場合は、メソッドが返されます。実際のプリンタコマンドは、QPrinterオブジェクトをパラメータとしてui->textEdit->print

フォントの選択
void Notepad::selectFont()
{
    bool fontSelected;
    QFont font = QFontDialog::getFont(&fontSelected, this);
    if (fontSelected)
        ui->textEdit->setFont(font);
}

フォントを選択したかどうかを示すブール値をQFontDialog で宣言します。選択した場合は、ui->textEdit->setFont(myfont) でフォントを設定します。

コピー、切り取り、貼り付け、元に戻す、やり直し

テキストを選択してクリップボードにコピーしたい場合は、ui->textEdit の適切なメソッドを呼び出します。カット、ペースト、元に戻す、やり直しも同様です。

この表は、使用するメソッド名を示しています。

タスク呼び出されるメソッド
コピーui->textEdit->copy()
カットui->textEdit->cut()
貼り付けui->textEdit->paste()
元に戻すui->textEdit->undo()
やり直しui->textEdit->redo()

さらに詳しく

についてここで
ファイルとI/OデバイスQFile,QIODevice
tr() と国際化Qt言語学者マニュアル翻訳のためのソースコードの記述Qtによる国際化

コマンドラインからのビルドと実行

コマンドラインからサンプルアプリケーションをビルドするには、ビルドディレクトリを作成します。ビルドディレクトリに移動し、qt-cmake を実行して、ビルド用にプロジェクトを設定します。プロジェクトが正常に設定されると、生成されたファイルによってプロジェクトをビルドできるようになります。

md <build_directory>
cd <build_directory>
<qt_installation_directory>\bin\qt-cmake -GNinja <source_directory>
<generator>

コマンドはビルド・ディレクトリに実行ファイルを作成します。CMake ツールはプロジェクト・ファイルを読み込み、アプリケーションのビルド方法の指示を生成します。そして、ジェネレーターはその命令を使用して実行バイナリを生成します。

例えば、Ninjaをジェネレーターとして使用する場合、Windowsでメモ帳のサンプルをビルドするには、以下のコマンドを入力します:

md notepad-build
cd notepad-build
C:\Qt\6.8.0\msvc2019_64\bin\qt-cmake -GNinja C:\Examples\notepad
ninja

Ninjaをジェネレーターとして使用しない場合は、ninja の代わりに、ジェネレーターに依存しないCMakeコマンドを使用してアプリケーションをビルドします:

cmake --build

プロジェクト例 @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。