Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.

Getting Started on the Commandline/ja: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=Qt ではじめる <span class="caps">GUI</span> プログラミング=
h1. Qt ではじめる GUI プログラミング


Qt の世界へようこそ - Qt はクロスプラットフォームの <span class="caps">GUI</span> ツールキットです。この入門ガイドでは簡単なメモ帳プログラムの作成を通して基本的な Qt の知識を説明します。このガイドを読み終わるころには Qt の概要および <span class="caps">API</span> ドキュメントを参照しながら開発に必要な情報を集めることができるはずです。
Qt の世界へようこそ - Qt はクロスプラットフォームの GUI ツールキットです。この入門ガイドでは簡単なメモ帳プログラムの作成を通して基本的な Qt の知識を説明します。このガイドを読み終わるころには Qt の概要および API ドキュメントを参照しながら開発に必要な情報を集めることができるはずです。


==Hello Notepad==
== Hello Notepad ==


最初のサンプルではウィンドウにテキストエリアを作成して表示します。これは <span class="caps">GUI</span> を持つもっとも簡単な Qt プログラムと言えます。
最初のサンプルではウィンドウにテキストエリアを作成して表示します。これは GUI を持つもっとも簡単な Qt プログラムと言えます。


[[Image:gs1.png|サンプル1]]
[[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|サンプル1]]


これがソースコードです:
これがソースコードです:


それでは1行ずつ見ていきましょう。最初の2行でサンプルプログラムに必要な2つのクラス、 [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' と [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]'' のヘッダファイルをインクルードしています。すべての Qt のクラスはその名前のヘッダファイルを持っています。
<code><br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;


6行目で [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' オブジェクトを作成しています。このオブジェクトはアプリケーション全体のリソースを管理し、 <span class="caps">GUI</span> を持つ Qt プログラムを動作させるのに欠くことのできない存在です。Qt はコマンドラインオプションを受け取るため、 <code>argv</code> <code>args</code> が必要です。
int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> textEdit.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
<br />それでは1行ずつ見ていきましょう。最初の2行でサンプルプログラムに必要な2つのクラス、 &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html と &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qtextedit.html のヘッダファイルをインクルードしています。すべての Qt のクラスはその名前のヘッダファイルを持っています。
<br />6行目で &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html オブジェクトを作成しています。このオブジェクトはアプリケーション全体のリソースを管理し、 GUI を持つ Qt プログラムを動作させるのに欠くことのできない存在です。Qt はコマンドラインオプションを受け取るため、 &lt;code&amp;gt;argv&amp;lt;/code&amp;gt; と &lt;code&amp;gt;args&amp;lt;/code&amp;gt; が必要です。
<br />8行目で &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qtextedit.html オブジェクトを作成しています。テキスト入力は GUI の視覚的な構成要素の1つです。Qt では通常これらをウィジェットと呼んでいます。ウィジェットは他にもスクロールバー、ラベル、ラジオボタンなどがあります。ウィジェットは他のウィジェットのコンテナ (入れ物) になることができます。たとえばダイアログやメインウィンドウなどです。
<br />9行目でテキスト入力を画面に表示しています。ウィジェットはコンテナとしても機能しますので (たとえばツールバーやメニュー、ステータスバーなどのウィジェットを持つ &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html)、ウィジェット単体を独立したウィンドウに表示することが可能です。ウィジェットはデフォルトでは非表示になっています。 &quot;show()&quot;:http://doc.qt.nokia.com/4.7/qwidget.html#show 関数を使ってウィジェットを表示してください。
<br />11行目で &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html のイベントループを開始します。 Qt アプリケーションが動いているとき、イベントが生成されてアプリケーションのウィジェットに送られます。具体的にはマウスボタンを押し込んだ、キーの押下などのイベントです。テキスト入力のウィジェットでテキストを入力したとき、ウィジェットはキー入力イベントを受け取り、打ち込まれたテキストを描画することで応答します。
<br />アプリケーションの起動は、コマンドプロンプトを開いて、&amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; ファイルのあるディレクトリに移動した後、次のコマンドを入力してプログラムをビルドしてください。
<br /><code><br />qmake -project<br />qmake<br />make<br /></code>
<br />その結果、&amp;lt;code&amp;gt;part1&amp;lt;/code&amp;gt; ディレクトリに実行ファイルが生成されます (Windows の場合は &lt;code&amp;gt;make&amp;lt;/code&amp;gt; のかわりに &lt;code&amp;gt;nmake&amp;lt;/code&amp;gt; を使う必要があります。さらに実行ファイルは &lt;code&amp;gt;part1/debug&amp;lt;/code&amp;gt; または &lt;code&amp;gt;part1/release&amp;lt;/code&amp;gt; に置かれます)。&amp;lt;code&amp;gt;qmake&amp;lt;/code&amp;gt; は Qt のビルドツールで、設定ファイルを受け取ります。 &lt;code&amp;gt;qmake&amp;lt;/code&amp;gt; は &lt;code&amp;gt;-project&amp;lt;/code&amp;gt; オプションを使用するとその設定ファイルを生成してくれます。渡された設定ファイル (拡張子は &lt;code&amp;gt;.pro&amp;lt;/code&amp;gt;) からプログラムをビルドするための &lt;code&amp;gt;make&amp;lt;/code&amp;gt; ファイルを生成します。独自に &lt;code&amp;gt;.pro&amp;lt;/code&amp;gt; ファイルを書く方法については後ほど説明します。
<br />h3. 関連するドキュメント
<br />''' ウィジェットとウィンドウのジオメトリ: &quot;Window and Dialog Widgets&amp;quot;:http://doc.qt.nokia.com/4.7/application-windows.html<br />* イベントとその処理: &quot;The Event System&amp;quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html


8行目で [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]'' オブジェクトを作成しています。テキスト入力は <span class="caps">GUI</span> の視覚的な構成要素の1つです。Qt では通常これらをウィジェットと呼んでいます。ウィジェットは他にもスクロールバー、ラベル、ラジオボタンなどがあります。ウィジェットは他のウィジェットのコンテナ (入れ物) になることができます。たとえばダイアログやメインウィンドウなどです。
== 終了ボタンを追加する ==


9行目でテキスト入力を画面に表示しています。ウィジェットはコンテナとしても機能しますので (たとえばツールバーやメニュー、ステータスバーなどのウィジェットを持つ [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'')、ウィジェット単体を独立したウィンドウに表示することが可能です。ウィジェットはデフォルトでは非表示になっています。 [http://doc.qt.nokia.com/4.7/qwidget.html#show show()] ''[doc.qt.nokia.com]'' 関数を使ってウィジェットを表示してください。
実際のアプリケーションでは通常より多くのウィジェットが必要です。そこで &quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html をテキスト入力の真下に配置してみましょう。このボタンは押されるとメモ帳プログラムが終了します。


11行目で [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' のイベントループを開始します。 Qt アプリケーションが動いているとき、イベントが生成されてアプリケーションのウィジェットに送られます。具体的にはマウスボタンを押し込んだ、キーの押下などのイベントです。テキスト入力のウィジェットでテキストを入力したとき、ウィジェットはキー入力イベントを受け取り、打ち込まれたテキストを描画することで応答します。
[[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|サンプル2]]
 
アプリケーションの起動は、コマンドプロンプトを開いて、<code>.cpp</code> ファイルのあるディレクトリに移動した後、次のコマンドを入力してプログラムをビルドしてください。
 
その結果、<code>part1</code> ディレクトリに実行ファイルが生成されます (Windows の場合は <code>make</code> のかわりに <code>nmake</code> を使う必要があります。さらに実行ファイルは <code>part1/debug</code> または <code>part1/release</code> に置かれます)。<code>qmake</code> は Qt のビルドツールで、設定ファイルを受け取ります。 <code>qmake</code> は <code>-project</code> オプションを使用するとその設定ファイルを生成してくれます。渡された設定ファイル (拡張子は <code>.pro</code>) からプログラムをビルドするための <code>make</code> ファイルを生成します。独自に <code>.pro</code> ファイルを書く方法については後ほど説明します。
 
===関連するドキュメント===
 
* ウィジェットとウィンドウのジオメトリ: [http://doc.qt.nokia.com/4.7/application-windows.html Window and Dialog Widgets] ''[doc.qt.nokia.com]''
* イベントとその処理: [http://doc.qt.nokia.com/4.7/eventsandfilters.html The Event System] ''[doc.qt.nokia.com]''
 
==終了ボタンを追加する==
 
実際のアプリケーションでは通常より多くのウィジェットが必要です。そこで [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] ''[doc.qt.nokia.com]'' をテキスト入力の真下に配置してみましょう。このボタンは押されるとメモ帳プログラムが終了します。
 
[[Image:gs2.png|サンプル2]]


それではソースコードを見ていきます。
それではソースコードを見ていきます。


1行目ではすべての Qt の <span class="caps">GUI</span> クラスを含む [http://doc.qt.nokia.com/4.7/qtgui.html QtGui] ''[doc.qt.nokia.com]'' ヘッダをインクルードしています。
<code><br />#include &lt;QtGui&amp;gt;


10行目では終了ボタンが押されたときにアプリケーションが終了するように Qt のシグナルとスロットの仕組みを使っています。<br /> スロットは実行時に名前 (通常の文字列) で呼び出される機能です。シグナルは呼び出されたときに登録されたスロットを起動する機能です。これを Qt では、スロットをシグナルにつないで、シグナルを送信する、と言います。
int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);
<br /> QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br /> QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);
<br /> QWidget window;<br /> window.setLayout(&amp;layout);
<br /> window.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
<br />1行目ではすべての Qt の GUI クラスを含む &quot;QtGui&amp;quot;:http://doc.qt.nokia.com/4.7/qtgui.html ヘッダをインクルードしています。
<br />10行目では終了ボタンが押されたときにアプリケーションが終了するように Qt のシグナルとスロットの仕組みを使っています。<br />スロットは実行時に名前 (通常の文字列) で呼び出される機能です。シグナルは呼び出されたときに登録されたスロットを起動する機能です。これを Qt では、スロットをシグナルにつないで、シグナルを送信する、と言います。
<br />&quot;quit()&quot;:http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit はアプリケーションを終了する &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html のスロットです。 &quot;clicked()&quot;:http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked は &quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html が押されたときに送信されるシグナルです。静的な &quot;QObject::connect()&quot;:http://doc.qt.nokia.com/4.7/qobject.html#connect 関数はスロットをシグナルにつなぎます。2つのマクロ &lt;code&amp;gt;SIGNAL ()&amp;lt;/code&amp;gt; と &amp;lt;code&amp;gt;SLOT()&lt;/code&amp;gt; はシグナルとスロットの関数シグニチャを受け取ります。そしてシグナルを送信するオブジェクトと受け取るオブジェクトのポインタも渡します。
<br />12行目では &quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html オブジェクトを生成しています。前述の通り、ウィジェットは他のウィジェットを含むことができます。子ウィジェットの位置やサイズを直接指定することもできますが、通常はレイアウトを使うのが簡単です。レイアウトはウィジェットの子要素の位置とサイズを管理します。 例えば &quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html は子要素を縦の列に配置します。
<br />13行目と14行目ではテキスト入力とボタンをそれぞれレイアウトに追加しています。<br />そして17行目でウィンドウにそのレイアウトを設定しています。
<br />h3. 関連するドキュメント
<br />''' シグナルとスロット: &quot;Signals &amp; Slots&amp;quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html<br />* レイアウト: &quot;Layout Management&amp;quot;:http://doc.qt.nokia.com/4.7/layout.html, &quot;Widgets and Layouts&amp;quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, &quot;Layout Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html<br />* Qt のウィジェット: &quot;Qt Widget Gallery&amp;quot;:http://doc.qt.nokia.com/4.7/gallery.html, &quot;Widget Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html


[http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit quit()] ''[doc.qt.nokia.com]'' はアプリケーションを終了する [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' のスロットです。 [http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked clicked()] ''[doc.qt.nokia.com]'' は [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] ''[doc.qt.nokia.com]'' が押されたときに送信されるシグナルです。静的な [http://doc.qt.nokia.com/4.7/qobject.html#connect QObject::connect()] ''[doc.qt.nokia.com]'' 関数はスロットをシグナルにつなぎます。2つのマクロ <code><span class="caps">SIGNAL</span></code> と <code><span class="caps">SLOT</span></code> はシグナルとスロットの関数シグニチャを受け取ります。そしてシグナルを送信するオブジェクトと受け取るオブジェクトのポインタも渡します。
== QWidget の派生クラスを作る ==


12行目では [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] ''[doc.qt.nokia.com]'' オブジェクトを生成しています。前述の通り、ウィジェットは他のウィジェットを含むことができます。子ウィジェットの位置やサイズを直接指定することもできますが、通常はレイアウトを使うのが簡単です。レイアウトはウィジェットの子要素の位置とサイズを管理します。 例えば [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] ''[doc.qt.nokia.com]'' は子要素を縦の列に配置します。
ユーザがアプリケーションを終了するとき、本当に終了したいかどうかを確認するダイアログを表示したいとします。このサンプルでは &quot;QWidget&amp;quot;:http://doc.qt.nokia.com/4.7/qwidget.html の派生クラスを定義して終了ボタンにつなぐためのスロットを追加します。


13行目と14行目ではテキスト入力とボタンをそれぞれレイアウトに追加しています。<br /> そして17行目でウィンドウにそのレイアウトを設定しています。
[[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|サンプル3]]
 
===関連するドキュメント===
 
* シグナルとスロット: [http://doc.qt.nokia.com/4.7/signalsandslots.html Signals &amp; Slots] ''[doc.qt.nokia.com]''
* レイアウト: [http://doc.qt.nokia.com/4.7/layout.html Layout Management] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/widgets-and-layouts.html Widgets and Layouts] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-layouts.html Layout Examples] ''[doc.qt.nokia.com]''
* Qt のウィジェット: [http://doc.qt.nokia.com/4.7/gallery.html Qt Widget Gallery] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-widgets.html Widget Examples] ''[doc.qt.nokia.com]''
 
==QWidget の派生クラスを作る==
 
ユーザがアプリケーションを終了するとき、本当に終了したいかどうかを確認するダイアログを表示したいとします。このサンプルでは [http://doc.qt.nokia.com/4.7/qwidget.html QWidget] ''[doc.qt.nokia.com]'' の派生クラスを定義して終了ボタンにつなぐためのスロットを追加します。
 
[[Image:gs3.png|サンプル3]]


それではソースコードを見ていきます。
それではソースコードを見ていきます。


<code>Q_OBJECT</code> マクロはクラス定義の先頭に置く必要があり、このクラスが <code>QObject</code> であることを宣言します ([http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' を継承しているので当然ではありますが)。 [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' は通常の C++ クラスにさまざまな機能を追加します。特にクラス名とスロット名は実行時に利用されます。同様にスロット引数の種類についても知ることができます。
<code><br />class Notepad : public QWidget<br />{<br /> Q_OBJECT
 
9行目 (実際のソースコードでは13行目) で <code>quit()</code> スロットを宣言しています。<code>slots</code> マクロを使えば簡単です。 これでシグニチャの一致するシグナル (ここでは引数を1つも持たないシグナルなら何でも) を <code>quit()</code> スロットに接続できます。
 
<code>main()</code> 関数で <span class="caps">GUI</span> の構築やスロットの接続を行うかわりに、 <code>Notepad</code> クラスのコンストラクタを使います。
 
上のクラス定義のように、 [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' へのポインタを使います (<code>textEdit</code> と <code>quitButton</code>)。通常、 [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' は常にヒープ上に作成し、それらをコピーはしないようにしてください。
 
ユーザに表示される文字列が [http://doc.qt.nokia.com/4.7/qobject.html#tr tr()] ''[doc.qt.nokia.com]'' 関数で囲まれています。この関数はアプリケーションを他の言語 (英語や中国語) 向けに提供するときに必要になります。ここではこれ以上触れませんが、関連ドキュメントの <code>Qt Linguist</code> を参照してみてください。
 
===関連するドキュメント===
 
* tr() 関数と国際化: [http://doc.qt.nokia.com/4.7/linguist-manual.html Qt Linguist Manual] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/i18n-source-translation.html Writing Source Code for Translation] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/linguist-hellotr.html Hello tr()] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/internationalization.html Internationalization with Qt] ''[doc.qt.nokia.com]''
* QObject と Qt のオブジェクトモデル (Qt の本質を知る): [http://doc.qt.nokia.com/4.7/object.html Object Model] ''[doc.qt.nokia.com]''
* qmake と Qt のビルドシステム: [http://doc.qt.nokia.com/4.7/qmake-manual.html qmake Manual] ''[doc.qt.nokia.com]''
 
===.pro ファイルを作成する===
 
<code>qmake</code> の <code>-project</code> オプションを使うかわりに、このサンプルプログラムのための <code>.pro</code> ファイルを書いてみましょう。
 
以下のシェルコマンドでサンプルプログラムをビルドします。
 
==QMainWindow を使う==
 
[http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'' はメニュバー、ドック、ツールバー、ステータスバーを追加するための独自のレイアウトが備わっているため、多くのアプリケーションがその恩恵を受けるでしょう。中央のエリアにはどのような種類のウィジェットでも配置することができます。今回のサンプルプログラムではテキスト入力がそこに置かれます。
 
[[Image:gs4.png|サンプル4]]
 
それでは新しい <code>Notepad</code> クラスの定義を見ていきましょう。
 
ドキュメントの保存と開く処理のためにさらに2つのスロットを追加しました。これらのスロットは次のセクションで実装します。
 
メインウィンドウにおいてはしばしば同じスロットがさまざまなウィジェットから呼び出されます。具体的にはメニューアイテムとツールバーのボタンなどです。これをより簡単にするために Qt はさまざまなウィジェットに渡されて、1つのスロットに接続される [http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]'' を提供しています。たとえば [http://doc.qt.nokia.com/4.7/qmenu.html QMenu] ''[doc.qt.nokia.com]'' と [http://doc.qt.nokia.com/4.7/qtoolbar.html QToolBar] ''[doc.qt.nokia.com]'' は同じ [http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]'' から メニューアイテムとツールボタンを作成できます。これがどのように動くのかちょっと見てみましょう。
 
これまで通り Notepad クラスのコンストラクタを <span class="caps">GUI</span> の構築に使います。
 
[http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]'' は追加するウィジェットにラベルとして表示されるテキストと共に作成します (今回のサンプルではメニューアイテム)。ツールバーに追加するのであれば、そのアクションに [http://doc.qt.nokia.com/4.7/qicon.html アイコン] ''[doc.qt.nokia.com]'' を持たせておくこともできます。


これでメニューアイテムがクリックされると、アクションが起動し、スロットが呼び出されます。
public:<br /> Notepad();


===関連するドキュメント===
private slots:<br /> void quit();


* メインウィンドウとそのクラス: [http://doc.qt.nokia.com/4.7/mainwindow.html Application Main Window] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-mainwindow.html Main Window Examples] ''[doc.qt.nokia.com]''
private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br /></code>
* <span class="caps">MDI</span> アプリケーション: [http://doc.qt.nokia.com/4.7/qmdiarea.html QMdiArea] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/mainwindows-mdi.html <span class="caps">MDI</span> Example] ''[doc.qt.nokia.com]''


==ドキュメントの保存と読み込み==
&lt;code&amp;gt;Q_OBJECT&amp;lt;/code&amp;gt; マクロはクラス定義の先頭に置く必要があり、このクラスが &lt;code&amp;gt;QObject&amp;lt;/code&amp;gt; であることを宣言します (&quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html を継承しているので当然ではありますが)。 &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html は通常の C++ クラスにさまざまな機能を追加します。特にクラス名とスロット名は実行時に利用されます。同様にスロット引数の種類についても知ることができます。


このサンプルでは1つ前のサンプルで追加した <code>open()</code> と <code>save()</code> の2つのスロットを実装していきます。
9行目 (実際のソースコードでは13行目) で &lt;code&amp;gt;quit()&lt;/code&amp;gt; スロットを宣言しています。&amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt; マクロを使えば簡単です。 これでシグニチャの一致するシグナル (ここでは引数を1つも持たないシグナルなら何でも) を &lt;code&amp;gt;quit()&lt;/code&amp;gt; スロットに接続できます。


[[Image:gs5.png|サンプル5]]
&lt;code&amp;gt;main()&lt;/code&amp;gt; 関数で GUI の構築やスロットの接続を行うかわりに、 &lt;code&amp;gt;Notepad&amp;lt;/code&amp;gt; クラスのコンストラクタを使います。


<code>open()</code> スロットの方からはじめてみましょう:
<code><br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));


まず最初のステップで開くファイル名をユーザに求めています。Qt にはユーザがファイルを選択できるダイアログである [http://doc.qt.nokia.com/4.7/qfiledialog.html QFileDialog] ''[doc.qt.nokia.com]'' があります。上の画像のダイアログは Kubuntu で表示させたものです。静的な [http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName getOpenFileName()] ''[doc.qt.nokia.com]'' 関数はモーダルなファイルダイアログを表示し、ユーザがファイルを選択するまで制御を戻しません。ダイアログは選択されたファイルのファイルパスか、ユーザがキャンセルした場合は空の文字列を返します。
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));


もし何らかのファイル名があるときは [http://doc.qt.nokia.com/4.7/qiodevice.html#open open()] ''[doc.qt.nokia.com]'' を使ってファイルのオープンを試みて、正しく開くことができたら ''true'' を返します。ここではエラー処理について詳しく説明しませんが、関連ドキュメントを参照してみてください。ファイルが開けなかった場合、ここでは [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] ''[doc.qt.nokia.com]'' を使ってエラーメッセージを表示します (詳しくは [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] ''[doc.qt.nokia.com]'' クラスの説明を参照してください)
QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br /></code>
<br />上のクラス定義のように、 &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html へのポインタを使います (&lt;code&amp;gt;textEdit&amp;lt;/code&amp;gt; と &lt;code&amp;gt;quitButton&amp;lt;/code&amp;gt;)。通常、 &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html は常にヒープ上に作成し、それらをコピーはしないようにしてください。
<br />ユーザに表示される文字列が &quot;tr()&quot;:http://doc.qt.nokia.com/4.7/qobject.html#tr 関数で囲まれています。この関数はアプリケーションを他の言語 (英語や中国語) 向けに提供するときに必要になります。ここではこれ以上触れませんが、関連ドキュメントの &lt;code&amp;gt;Qt Linguist&amp;lt;/code&amp;gt; を参照してみてください。
<br />h3. 関連するドキュメント
<br />''' tr() 関数と国際化: &quot;Qt Linguist Manual&amp;quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, &quot;Writing Source Code for Translation&amp;quot;:http://doc.qt.nokia.com/4.7/i18n-source-translation.html, &quot;Hello tr()&quot;:http://doc.qt.nokia.com/4.7/linguist-hellotr.html, &quot;Internationalization with Qt&amp;quot;:http://doc.qt.nokia.com/4.7/internationalization.html<br />* QObject と Qt のオブジェクトモデル (Qt の本質を知る): &quot;Object Model&amp;quot;:http://doc.qt.nokia.com/4.7/object.html<br />* qmake と Qt のビルドシステム: &quot;qmake Manual&amp;quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html


今回はファイルのすべてのデータを [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray] ''[doc.qt.nokia.com]'' として返す [http://doc.qt.nokia.com/4.7/qiodevice.html#readAll readAll()] ''[doc.qt.nokia.com]'' 関数を使っています。 [http://doc.qt.nokia.com/4.7/qbytearray.html#constData constData()] ''[doc.qt.nokia.com]'' は配列のすべてのデータを ''const char*'' で返します ([http://doc.qt.nokia.com/4.7/qstring.html QString] ''[doc.qt.nokia.com]'' にはそのコンストラクタがある)。そして内容がテキスト入力に表示されます。あとは [http://doc.qt.nokia.com/4.7/qiodevice.html#close close()] ''[doc.qt.nokia.com]'' を呼び出してファイルディスクリプタを OS に返します。
=== .pro ファイルを作成する ===


次は <code>save()</code> スロットにとりかかりましょう。
&lt;code&amp;gt;qmake&amp;lt;/code&amp;gt; の &lt;code&amp;gt;<s>project&amp;lt;/code&amp;gt; オプションを使うかわりに、このサンプルプログラムのための &lt;code&amp;gt;.pro&amp;lt;/code&amp;gt; ファイルを書いてみましょう。
<br /><code><br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br /></code>
<br />以下のシェルコマンドでサンプルプログラムをビルドします。
<br /><code><br />qmake<br />make<br /></code>
<br />h2. QMainWindow を使う
<br />&quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html はメニュバー、ドック、ツールバー、ステータスバーを追加するための独自のレイアウトが備わっているため、多くのアプリケーションがその恩恵を受けるでしょう。中央のエリアにはどのような種類のウィジェットでも配置することができます。今回のサンプルプログラムではテキスト入力がそこに置かれます。
<br />[[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|サンプル4]]
<br />それでは新しい &lt;code&amp;gt;Notepad&amp;lt;/code&amp;gt; クラスの定義を見ていきましょう。
<br /><code><br /> #include &lt;QtGui&amp;gt;
<br /> class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT
<br /> public:<br /> Notepad();
<br /> private slots:<br /> void open();<br /> void save();<br /> void quit();
<br /> private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br /> };<br /></code>
<br />ドキュメントの保存と開く処理のためにさらに2つのスロットを追加しました。これらのスロットは次のセクションで実装します。
<br />メインウィンドウにおいてはしばしば同じスロットがさまざまなウィジェットから呼び出されます。具体的にはメニューアイテムとツールバーのボタンなどです。これをより簡単にするために Qt はさまざまなウィジェットに渡されて、1つのスロットに接続される &quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html を提供しています。たとえば &quot;QMenu&amp;quot;:http://doc.qt.nokia.com/4.7/qmenu.html と &quot;QToolBar&amp;quot;:http://doc.qt.nokia.com/4.7/qtoolbar.html は同じ &quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html から メニューアイテムとツールボタンを作成できます。これがどのように動くのかちょっと見てみましょう。
<br />これまで通り Notepad クラスのコンストラクタを GUI の構築に使います。
<br /><code><br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br /></code>
<br />&quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html は追加するウィジェットにラベルとして表示されるテキストと共に作成します (今回のサンプルではメニューアイテム)。ツールバーに追加するのであれば、そのアクションに &quot;アイコン&amp;quot;:http://doc.qt.nokia.com/4.7/qicon.html を持たせておくこともできます。
<br />これでメニューアイテムがクリックされると、アクションが起動し、スロットが呼び出されます。
<br />h3. 関連するドキュメント
<br />''' メインウィンドウとそのクラス: &quot;Application Main Window&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, &quot;Main Window Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html<br />* MDI アプリケーション: &quot;QMdiArea&amp;quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, &quot;MDI Example&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html


テキスト入力の内容をファイルに書き込むとき、 [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'' オブジェクトをラップする [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] ''[doc.qt.nokia.com]'' クラスを使います。テキストストリームは QString をファイルに書き込むことができます。 [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'' はオブジェクト化されていない文字列データ (char*) のみを [http://doc.qt.nokia.com/4.7/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]'' の [http://doc.qt.nokia.com/4.7/qiodevice.html#write write()] ''[doc.qt.nokia.com]'' 関数で受け付けます。
<br />h2. ドキュメントの保存と読み込み
<br />このサンプルでは1つ前のサンプルで追加した &lt;code&amp;gt;open()&lt;/code&amp;gt; と &lt;code&amp;gt;save()&lt;/code&amp;gt; の2つのスロットを実装していきます。
<br />[[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|サンプル5]]
<br />&lt;code&amp;gt;open()&lt;/code&amp;gt; スロットの方からはじめてみましょう:
<br /><code><br /> QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit-&gt;setPlainText(contents);<br /> file.close();<br /> }<br /></code>
<br />まず最初のステップで開くファイル名をユーザに求めています。Qt にはユーザがファイルを選択できるダイアログである &quot;QFileDialog&amp;quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html があります。上の画像のダイアログは Kubuntu で表示させたものです。静的な &quot;getOpenFileName()&quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName 関数はモーダルなファイルダイアログを表示し、ユーザがファイルを選択するまで制御を戻しません。ダイアログは選択されたファイルのファイルパスか、ユーザがキャンセルした場合は空の文字列を返します。
<br />もし何らかのファイル名があるときは &quot;open()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#open を使ってファイルのオープンを試みて、正しく開くことができたら ''true'' を返します。ここではエラー処理について詳しく説明しませんが、関連ドキュメントを参照してみてください。ファイルが開けなかった場合、ここでは &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html を使ってエラーメッセージを表示します (詳しくは &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html クラスの説明を参照してください)。
<br />今回はファイルのすべてのデータを &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/4.7/qbytearray.html として返す &quot;readAll()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#readAll 関数を使っています。 &quot;constData()&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html#constData は配列のすべてのデータを ''const char*'' で返します (&quot;QString&amp;quot;:http://doc.qt.nokia.com/4.7/qstring.html にはそのコンストラクタがある)。そして内容がテキスト入力に表示されます。あとは &quot;close()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#close を呼び出してファイルディスクリプタを OS に返します。
<br />次は &lt;code&amp;gt;save()&lt;/code&amp;gt; スロットにとりかかりましょう。
<br /><code><br /> QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp'''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit</s>&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br /></code>


===関連するドキュメント===
テキスト入力の内容をファイルに書き込むとき、 &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html オブジェクトをラップする &quot;QTextStream&amp;quot;:http://doc.qt.nokia.com/4.7/qtextstream.html クラスを使います。テキストストリームは QString をファイルに書き込むことができます。 &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html はオブジェクト化されていない文字列データ (char*) のみを &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/4.7/qiodevice.html の &quot;write()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#write 関数で受け付けます。


* ファイルと入出力デバイス: [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]''
=== 関連するドキュメント ===

Revision as of 09:19, 24 February 2015

h1. Qt ではじめる GUI プログラミング

Qt の世界へようこそ - Qt はクロスプラットフォームの GUI ツールキットです。この入門ガイドでは簡単なメモ帳プログラムの作成を通して基本的な Qt の知識を説明します。このガイドを読み終わるころには Qt の概要および API ドキュメントを参照しながら開発に必要な情報を集めることができるはずです。

Hello Notepad

最初のサンプルではウィンドウにテキストエリアを作成して表示します。これは GUI を持つもっとも簡単な Qt プログラムと言えます。

サンプル1

これがソースコードです:

<br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;

int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> textEdit.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br />


それでは1行ずつ見ていきましょう。最初の2行でサンプルプログラムに必要な2つのクラス、 "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html と "QTextEdit&quot;:http://doc.qt.nokia.com/4.7/qtextedit.html のヘッダファイルをインクルードしています。すべての Qt のクラスはその名前のヘッダファイルを持っています。
6行目で "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html オブジェクトを作成しています。このオブジェクトはアプリケーション全体のリソースを管理し、 GUI を持つ Qt プログラムを動作させるのに欠くことのできない存在です。Qt はコマンドラインオプションを受け取るため、 <code&gt;argv&lt;/code&gt; と <code&gt;args&lt;/code&gt; が必要です。
8行目で "QTextEdit&quot;:http://doc.qt.nokia.com/4.7/qtextedit.html オブジェクトを作成しています。テキスト入力は GUI の視覚的な構成要素の1つです。Qt では通常これらをウィジェットと呼んでいます。ウィジェットは他にもスクロールバー、ラベル、ラジオボタンなどがあります。ウィジェットは他のウィジェットのコンテナ (入れ物) になることができます。たとえばダイアログやメインウィンドウなどです。
9行目でテキスト入力を画面に表示しています。ウィジェットはコンテナとしても機能しますので (たとえばツールバーやメニュー、ステータスバーなどのウィジェットを持つ "QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html)、ウィジェット単体を独立したウィンドウに表示することが可能です。ウィジェットはデフォルトでは非表示になっています。 "show()":http://doc.qt.nokia.com/4.7/qwidget.html#show 関数を使ってウィジェットを表示してください。
11行目で "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html のイベントループを開始します。 Qt アプリケーションが動いているとき、イベントが生成されてアプリケーションのウィジェットに送られます。具体的にはマウスボタンを押し込んだ、キーの押下などのイベントです。テキスト入力のウィジェットでテキストを入力したとき、ウィジェットはキー入力イベントを受け取り、打ち込まれたテキストを描画することで応答します。
アプリケーションの起動は、コマンドプロンプトを開いて、&lt;code&gt;.cpp&lt;/code&gt; ファイルのあるディレクトリに移動した後、次のコマンドを入力してプログラムをビルドしてください。


<br />qmake -project<br />qmake<br />make<br />


その結果、&lt;code&gt;part1&lt;/code&gt; ディレクトリに実行ファイルが生成されます (Windows の場合は <code&gt;make&lt;/code&gt; のかわりに <code&gt;nmake&lt;/code&gt; を使う必要があります。さらに実行ファイルは <code&gt;part1/debug&lt;/code&gt; または <code&gt;part1/release&lt;/code&gt; に置かれます)。&lt;code&gt;qmake&lt;/code&gt; は Qt のビルドツールで、設定ファイルを受け取ります。 <code&gt;qmake&lt;/code&gt; は <code&gt;-project&lt;/code&gt; オプションを使用するとその設定ファイルを生成してくれます。渡された設定ファイル (拡張子は <code&gt;.pro&lt;/code&gt;) からプログラムをビルドするための <code&gt;make&lt;/code&gt; ファイルを生成します。独自に <code&gt;.pro&lt;/code&gt; ファイルを書く方法については後ほど説明します。
h3. 関連するドキュメント
ウィジェットとウィンドウのジオメトリ: "Window and Dialog Widgets&quot;:http://doc.qt.nokia.com/4.7/application-windows.html
* イベントとその処理: "The Event System&quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html

終了ボタンを追加する

実際のアプリケーションでは通常より多くのウィジェットが必要です。そこで "QPushButton&quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html をテキスト入力の真下に配置してみましょう。このボタンは押されるとメモ帳プログラムが終了します。

サンプル2

それではソースコードを見ていきます。

<br />#include &lt;QtGui&amp;gt;

int main(int argv, char *'''args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);
<br /> QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br /> QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);
<br /> QWidget window;<br /> window.setLayout(&amp;layout);
<br /> window.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br />


1行目ではすべての Qt の GUI クラスを含む "QtGui&quot;:http://doc.qt.nokia.com/4.7/qtgui.html ヘッダをインクルードしています。
10行目では終了ボタンが押されたときにアプリケーションが終了するように Qt のシグナルとスロットの仕組みを使っています。
スロットは実行時に名前 (通常の文字列) で呼び出される機能です。シグナルは呼び出されたときに登録されたスロットを起動する機能です。これを Qt では、スロットをシグナルにつないで、シグナルを送信する、と言います。
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit はアプリケーションを終了する "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html のスロットです。 "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked は "QPushButton&quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html が押されたときに送信されるシグナルです。静的な "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect 関数はスロットをシグナルにつなぎます。2つのマクロ <code&gt;SIGNAL ()&lt;/code&gt; と &lt;code&gt;SLOT()</code&gt; はシグナルとスロットの関数シグニチャを受け取ります。そしてシグナルを送信するオブジェクトと受け取るオブジェクトのポインタも渡します。
12行目では "QVBoxLayout&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html オブジェクトを生成しています。前述の通り、ウィジェットは他のウィジェットを含むことができます。子ウィジェットの位置やサイズを直接指定することもできますが、通常はレイアウトを使うのが簡単です。レイアウトはウィジェットの子要素の位置とサイズを管理します。 例えば "QVBoxLayout&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html は子要素を縦の列に配置します。
13行目と14行目ではテキスト入力とボタンをそれぞれレイアウトに追加しています。
そして17行目でウィンドウにそのレイアウトを設定しています。
h3. 関連するドキュメント
シグナルとスロット: "Signals & Slots&quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html
* レイアウト: "Layout Management&quot;:http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts&quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples&quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html
* Qt のウィジェット: "Qt Widget Gallery&quot;:http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples&quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html

QWidget の派生クラスを作る

ユーザがアプリケーションを終了するとき、本当に終了したいかどうかを確認するダイアログを表示したいとします。このサンプルでは "QWidget&quot;:http://doc.qt.nokia.com/4.7/qwidget.html の派生クラスを定義して終了ボタンにつなぐためのスロットを追加します。

サンプル3

それではソースコードを見ていきます。

<br />class Notepad : public QWidget<br />{<br /> Q_OBJECT

public:<br /> Notepad();

private slots:<br /> void quit();

private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br />

<code&gt;Q_OBJECT&lt;/code&gt; マクロはクラス定義の先頭に置く必要があり、このクラスが <code&gt;QObject&lt;/code&gt; であることを宣言します ("QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html を継承しているので当然ではありますが)。 "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html は通常の C++ クラスにさまざまな機能を追加します。特にクラス名とスロット名は実行時に利用されます。同様にスロット引数の種類についても知ることができます。

9行目 (実際のソースコードでは13行目) で <code&gt;quit()</code&gt; スロットを宣言しています。&lt;code&gt;slots&lt;/code&gt; マクロを使えば簡単です。 これでシグニチャの一致するシグナル (ここでは引数を1つも持たないシグナルなら何でも) を <code&gt;quit()</code&gt; スロットに接続できます。

<code&gt;main()</code&gt; 関数で GUI の構築やスロットの接続を行うかわりに、 <code&gt;Notepad&lt;/code&gt; クラスのコンストラクタを使います。

<br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));

connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));

QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br />


上のクラス定義のように、 "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html へのポインタを使います (<code&gt;textEdit&lt;/code&gt; と <code&gt;quitButton&lt;/code&gt;)。通常、 "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html は常にヒープ上に作成し、それらをコピーはしないようにしてください。
ユーザに表示される文字列が "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr 関数で囲まれています。この関数はアプリケーションを他の言語 (英語や中国語) 向けに提供するときに必要になります。ここではこれ以上触れませんが、関連ドキュメントの <code&gt;Qt Linguist&lt;/code&gt; を参照してみてください。
h3. 関連するドキュメント
tr() 関数と国際化: "Qt Linguist Manual&quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation&quot;:http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr()":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalization with Qt&quot;:http://doc.qt.nokia.com/4.7/internationalization.html
* QObject と Qt のオブジェクトモデル (Qt の本質を知る): "Object Model&quot;:http://doc.qt.nokia.com/4.7/object.html
* qmake と Qt のビルドシステム: "qmake Manual&quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html

.pro ファイルを作成する

<code&gt;qmake&lt;/code&gt; の <code&gt;project&lt;/code&gt; オプションを使うかわりに、このサンプルプログラムのための <code&gt;.pro&lt;/code&gt; ファイルを書いてみましょう。


<br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br />


以下のシェルコマンドでサンプルプログラムをビルドします。


<br />qmake<br />make<br />


h2. QMainWindow を使う
"QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html はメニュバー、ドック、ツールバー、ステータスバーを追加するための独自のレイアウトが備わっているため、多くのアプリケーションがその恩恵を受けるでしょう。中央のエリアにはどのような種類のウィジェットでも配置することができます。今回のサンプルプログラムではテキスト入力がそこに置かれます。
サンプル4
それでは新しい <code&gt;Notepad&lt;/code&gt; クラスの定義を見ていきましょう。


<br /> #include &lt;QtGui&amp;gt;
<br /> class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT
<br /> public:<br /> Notepad();
<br /> private slots:<br /> void open();<br /> void save();<br /> void quit();
<br /> private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br /> };<br />


ドキュメントの保存と開く処理のためにさらに2つのスロットを追加しました。これらのスロットは次のセクションで実装します。
メインウィンドウにおいてはしばしば同じスロットがさまざまなウィジェットから呼び出されます。具体的にはメニューアイテムとツールバーのボタンなどです。これをより簡単にするために Qt はさまざまなウィジェットに渡されて、1つのスロットに接続される "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html を提供しています。たとえば "QMenu&quot;:http://doc.qt.nokia.com/4.7/qmenu.html と "QToolBar&quot;:http://doc.qt.nokia.com/4.7/qtoolbar.html は同じ "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html から メニューアイテムとツールボタンを作成できます。これがどのように動くのかちょっと見てみましょう。
これまで通り Notepad クラスのコンストラクタを GUI の構築に使います。


<br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br /> }<br />


"QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html は追加するウィジェットにラベルとして表示されるテキストと共に作成します (今回のサンプルではメニューアイテム)。ツールバーに追加するのであれば、そのアクションに "アイコン&quot;:http://doc.qt.nokia.com/4.7/qicon.html を持たせておくこともできます。
これでメニューアイテムがクリックされると、アクションが起動し、スロットが呼び出されます。
h3. 関連するドキュメント
メインウィンドウとそのクラス: "Application Main Window&quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples&quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html
* MDI アプリケーション: "QMdiArea&quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example&quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html


h2. ドキュメントの保存と読み込み
このサンプルでは1つ前のサンプルで追加した <code&gt;open()</code&gt; と <code&gt;save()</code&gt; の2つのスロットを実装していきます。
サンプル5
<code&gt;open()</code&gt; スロットの方からはじめてみましょう:


<br /> QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp '''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit-&gt;setPlainText(contents);<br /> file.close();<br /> }<br />


まず最初のステップで開くファイル名をユーザに求めています。Qt にはユーザがファイルを選択できるダイアログである "QFileDialog&quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html があります。上の画像のダイアログは Kubuntu で表示させたものです。静的な "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName 関数はモーダルなファイルダイアログを表示し、ユーザがファイルを選択するまで制御を戻しません。ダイアログは選択されたファイルのファイルパスか、ユーザがキャンセルした場合は空の文字列を返します。
もし何らかのファイル名があるときは "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open を使ってファイルのオープンを試みて、正しく開くことができたら true を返します。ここではエラー処理について詳しく説明しませんが、関連ドキュメントを参照してみてください。ファイルが開けなかった場合、ここでは "QMessageBox&quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html を使ってエラーメッセージを表示します (詳しくは "QMessageBox&quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html クラスの説明を参照してください)。
今回はファイルのすべてのデータを "QByteArray&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html として返す "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll 関数を使っています。 "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData は配列のすべてのデータを const char* で返します ("QString&quot;:http://doc.qt.nokia.com/4.7/qstring.html にはそのコンストラクタがある)。そして内容がテキスト入力に表示されます。あとは "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close を呼び出してファイルディスクリプタを OS に返します。
次は <code&gt;save()</code&gt; スロットにとりかかりましょう。


<br /> QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp'''.h)&quot;));
<br /> if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit</s>&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br />

テキスト入力の内容をファイルに書き込むとき、 "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html オブジェクトをラップする "QTextStream&quot;:http://doc.qt.nokia.com/4.7/qtextstream.html クラスを使います。テキストストリームは QString をファイルに書き込むことができます。 "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html はオブジェクト化されていない文字列データ (char*) のみを "QIODevice&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html の "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write 関数で受け付けます。

関連するドキュメント