MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの基礎 - 終了処理のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの基礎 - 終了処理
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Qtアプリケーションの終了は、いくつかの段階を経て行われる。<br> <br> まず、アプリケーションの終了が開始される時、<code>QCoreApplication::aboutToQuit()</code>シグナルが発行される。<br> このシグナルは、アプリケーションが終了する直前に発生するため、重要なクリーンアップ作業を行うのに適している。<br> <br> 次に、<code>QApplication::exec()</code>メソッドから制御が戻る。<br> これにより、メインイベントループが終了して、アプリケーションの実行が停止する。<br> <br> GUIでは、この時点で、Qtは自動的に全ての子ウィジェットを削除する。<br> これには、トップレベルウィンドウやダイアログも含まれる。<br> <br> その後、グローバルなstaticオブジェクトのデストラクタが呼び出される。<br> これらのオブジェクトは、逆構築順序で破棄される。つまり、最後に作成されたオブジェクトが最初に破棄される。<br> <br> 最後に、メイン関数からreturn文が実行されて、プログラムが完全に終了する。<br> <br> Qtアプリケーションの終了をカスタマイズする方法もある。<br> 例えば、<code>QApplication::setQuitOnLastWindowClosed(false)</code>を呼び出すことにより、<br> 最後のウインドウが閉じられてもアプリケーションが終了しないようにすることができる。<br> <br> また、<code>QObject::deleteLater()</code>メソッドを使用して、イベントループの次の反復時にオブジェクトを安全に削除することもできる。<br> <br> メモリリークを防ぐために、動的に割り当てられたリソースを適切に解放することが重要である。<br> Qtのオブジェクト所有システムを活用すると、多くの場合、明示的なメモリ管理が不要になる。<br> <br> エラーハンドリングも終了処理の重要である。<br> 例外が捕捉されずにメイン関数を抜ける場合、プログラムがクラッシュする可能性がある。<br> そのため、適切な例外処理を実装することが推奨される。<br> <br><br> == コンソールアプリケーション == <code>QCoreApplication::quit()</code>メソッドおよび<code>QCoreApplication::exit()</code>において、<br> 両方ともアプリケーションを終了するために使用するが、動作と使用場面が異なる。<br> <br> 使用の指針を以下に示す。<br> * 一般的な状況では、<code>QCoreApplication::quit()</code>メソッドの使用を推奨する。<br>これは、イベントループを適切に終了して、保留中のイベントを処理する機会を与える。 *: <br> * <code>QCoreApplication::exit()</code>メソッドは、<br>即座にアプリケーションを終了する必要がある場合 (例: クリティカルなエラーが発生した場合) や特定の終了コードを返す必要がある場合に使用する。 *: <br> * GUIアプリケーションでは、<code>QCoreApplication::quit()</code>メソッドの使用を推奨する。<br>これにより、ウインドウを適切に閉じて、リソースをクリーンアップする機会が与えられる。 *: <br> * コンソールアプリケーションでは、<code>QCoreApplication::quit()</code>メソッドでもよいが、<br>特定の終了コードが必要な場合は、<code>QCoreApplication::exit()</code>メソッドを使用することがある。 <br> ==== QCoreApplication::quit() ==== <code>QCoreApplication::quit()</code>メソッドは、シグナルとして実装されている。<br> 非同期で動作して、イベントループを安全に終了させることができる。<br> (イベントループの次の反復時に処理される)<br> <br> 戻り値はない。<br> <br> 一般的に、スロットとして接続、または、<code>QTimer::singleShot()</code>と組み合わせて使用する。<br> <br> 以下の例では、QCoreApplication::quit()メソッドはシグナルとして動作するため、関数呼び出しは即座に戻り、次の行が実行される。<br> アプリケーションは次のイベントループの反復時に終了する。<br> <syntaxhighlight lang="c++"> // 使用例 #include <QCoreApplication> #include <QTimer> #include <iostream> void useQuit() { std::cout << "Calling quit()..." << std::endl; QCoreApplication::quit(); std::cout << "This line will be executed." << std::endl; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // QCoreApplication::quit()の例 QTimer::singleShot(1000, useQuit); return a.exec(); } </syntaxhighlight> <br> ==== QCoreApplication::exit() ==== <code>QCoreApplication::exit(int returnCode = 0)</code>は、通常のメソッドとして実装されている。<br> 同期的に動作して、イベントループを即座に終了させることができる。<br> (呼び出された時点で即座に処理される)<br> <br> 整数の戻り値を受け取り、それをアプリケーションの終了コードとして使用する。<br> <br> 特定の終了コードでアプリケーションを終了させる場合に使用する。<br> <br> 以下の例では、QCoreApplication::exit(0)メソッドが呼び出された直後にアプリケーションが終了するため、2番目のcout文は実行されない。<br> <syntaxhighlight lang="c++"> #include <QCoreApplication> #include <iostream> void useExit() { std::cout << "Calling exit()..." << std::endl; QCoreApplication::exit(0); std::cout << "This line will NOT be executed." << std::endl; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // QCoreApplication::exit()の例 QTimer::singleShot(1000, useExit); return a.exec(); } </syntaxhighlight> <br><br> == QWidgetsアプリケーション == GUIアプリケーションの終了処理は、ユーザがアプリケーションのメインウィンドウを閉じる、または、[終了]ボタンを押下することにより開始される。<br> この時点で、アプリケーションの終了プロセスが実行される。<br> <br> 終了プロセスの最初のステップとして、<code>QApplication::aboutToQuit()</code>シグナルが発行される。<br> このシグナルは、GUIアプリケーションが終了する直前に発生するため、重要なクリーンアップを行うのに適したタイミングである。<br> <br> 重要なクリーンアップの例として、以下に示すようなものがある。<br> * ユーザデータの保存 *: 未保存の作業内容やアプリケーションの状態を保存する。 *: これには、ドキュメントの内容、ウインドウの位置やサイズ、ユーザ設定等が含まれている。 * 開いているファイルやデータベース接続の終了 *: ファイルハンドルやデータベース接続を適切に閉じることにより、データの整合性を保ち、リソースリークを防ぐ。 * ネットワーク接続の終了 *: アクティブなネットワーク接続を適切に終了して、リモートサーバにグレースフルな切断を通知する。 * テンポラリファイルの削除 *: GUIアプリケーションが作成した一時ファイルを削除して、不要なディスク使用を避ける。 * バックグラウンドタスクの終了 *: 実行中のバックグラウンドスレッドやタイマを適切に停止する。 <br> これらのクリーンアップを実行するために、<code>QObject::connect()</code>メソッドを使用して<code>aboutToQuit()</code>シグナルにスロットを接続する。<br> クリーンアップの完了後は、<code>QApplication::exec()</code>メソッドから制御が戻り、メインイベントループが終了する。<br> この時に、Qtは自動的に全ての子ウィジェットを削除する。<br> <br> 最後に、グローバルなstaticオブジェクトのデストラクタが呼び出されて、メイン関数からreturn文が実行されてプログラムが完全に終了する。<br> <br> 以下の例では、QWidgetsアプリケーションの終了処理を示している。<br> 基本的な終了処理とエラーハンドリングを実装しているが、実務ではより具体的なクリーンアップ処理を追加する必要がある。<br> <br> <syntaxhighlight lang="c++"> // MainWindow.hファイル #include <QApplication> #include <QMainWindow> #include <QMenu> #include <QMenuBar> #include <QAction> #include <QCloseEvent> #include <QMessageBox> #include <QDebug> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { setWindowTitle("Qt Application"); QMenu *fileMenu = menuBar()->addMenu("&File"); QAction *exitAction = fileMenu->addAction("E&xit"); connect(exitAction, &QAction::triggered, this, &MainWindow::onExit); // アプリケーション終了時のクリーンアップ処理を接続 connect(qApp, &QApplication::aboutToQuit, this, &MainWindow::performCleanup); } protected: // closeEventメソッドをオーバーライドして、アプリケーション終了時の動作をカスタマイズする void closeEvent(QCloseEvent *event) override { if (saveChanges()) { event->accept(); } else { event->ignore(); } } private slots: void onExit() { close(); } // アプリケーション終了時のクリーンアップ処理を行う void performCleanup() { qDebug() << "Performing cleanup..."; // リソースの解放やその他のクリーンアップ処理を実装 } private: // 未保存の変更がある場合にユーザに確認を求める bool saveChanges() { // ここで未保存の変更をチェックし、必要に応じて保存ダイアログを表示 QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "Unsaved Changes", "Do you want to save changes before exiting?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); if (reply == QMessageBox::Yes) { // 変更を保存する処理をここに実装 qDebug() << "Saving changes..."; return true; } else if (reply == QMessageBox::No) { return true; } else { return false; } } }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include <QFile> #include <QTextStream> #include "MainWindow.h" // カスタムのメッセージハンドラを定義して、アプリケーションのログをファイルに出力する void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QFile file("app_log.txt"); if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) { return; } QTextStream stream(&file); stream << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz "); switch (type) { case QtDebugMsg: stream << "Debug: "; break; case QtInfoMsg: stream << "Info: "; break; case QtWarningMsg: stream << "Warning: "; break; case QtCriticalMsg: stream << "Critical: "; break; case QtFatalMsg: stream << "Fatal: "; break; } stream << msg << " (" << context.file << ":" << context.line << ")" << Qt::endl; file.close(); } int main(int argc, char *argv[]) { qInstallMessageHandler(myMessageHandler); // 例外処理を実装して、予期しないエラーをキャッチしてログに記録する try { QApplication app(argc, argv); MainWindow mainWindow; mainWindow.show(); QObject::connect(&app, &QApplication::aboutToQuit, []() { qDebug() << "Application is about to quit"; // 追加のクリーンアップ処理 }); return app.exec(); } catch (const std::exception& e) { QMessageBox::critical(nullptr, "Error", QString("An unexpected error occurred: %1").arg(e.what())); qCritical() << "Unhandled exception:" << e.what(); return -1; } catch (...) { QMessageBox::critical(nullptr, "Error", "An unknown error occurred"); qCritical() << "Unknown exception occurred"; return -1; } } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの基礎 - 終了処理
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse