C言語GUI入門|GUI電卓の仕様を決める

第6章では、2つの数値を入力して四則演算を実行できるGUI電卓を作成します。

GUIアプリケーションを作るときは、すぐにプログラムを書き始めるのではなく、最初に必要な機能や画面の構成を整理しておくことが大切です。仕様を先に決めておけば、どのウィジェットが必要なのか、どのようなコールバック関数を作ればよいのかが分かりやすくなります。

この記事では、次の内容を決めます。

  • GUI電卓でできること
  • 入力できる値
  • 画面に配置するウィジェット
  • 四則演算の動作
  • 計算結果の表示方法
  • 入力エラーが発生したときの動作
  • クリアボタンを押したときの動作
  • 第6章で完成させる画面のイメージ

この節では、まだcalculator.cのプログラムは作成しません。次の6.2からファイルを準備し、少しずつ機能を追加していきます。

GUI電卓でできることを決めよう

今回作成するGUI電卓では、2つの入力欄に数値を入力し、演算ボタンをクリックして計算します。

実装する機能は次のとおりです。

機能内容
数値の入力2つのGtkEntryに計算したい数値を入力する
足し算1つ目の値と2つ目の値を加算する
引き算1つ目の値から2つ目の値を減算する
掛け算1つ目の値と2つ目の値を乗算する
割り算1つ目の値を2つ目の値で除算する
結果の表示計算結果をGtkLabelに表示する
入力の確認空欄や数値以外の入力を確認する
ゼロ除算の確認0で割ろうとした場合は計算しない
入力内容のクリア入力値と計算結果を初期状態へ戻す

今回の電卓は、複雑な関数を扱う関数電卓ではありません。四則演算の基本を通して、GtkEntryから入力を取得する方法、文字列を数値へ変換する方法、ボタンのクリックを処理する方法などを学ぶことが目的です。

図1:GUI電卓の基本機能

この図から分かること

今回のGUI電卓は、2つの入力欄、4つの演算ボタン、計算結果を表示するラベル、クリアボタンで構成されます。

利用者は、次の順番で電卓を操作します。

  1. 1つ目の数値を入力する
  2. 2つ目の数値を入力する
  3. 実行したい演算ボタンをクリックする
  4. 計算結果を確認する
  5. 必要に応じてクリアボタンをクリックする

入力できる値を決める

GtkEntryへ入力した内容は、数値としてではなく文字列として取得されます。

たとえば、画面に12.5と入力しても、プログラムが最初に受け取るのは数値の12.5ではなく、文字が並んだ12.5です。そのため、計算する前に文字列を数値へ変換しなければなりません。

今回の電卓では、次のような値を入力できる仕様にします。

入力例判定説明
25有効正の整数
-8有効負の整数
3.14有効小数
-0.75有効負の小数
+10有効プラス記号が付いた数値
1e3有効strtodで変換できる指数表記
空欄無効数値が入力されていない
空白だけ無効数値として扱わない
ABC無効数値へ変換できない
12ABC無効数値以外の文字が含まれている
nan無効通常の有限な数値として扱わない
inf無効通常の有限な数値として扱わない

整数だけでなく小数も計算できるようにするため、入力値はdouble型へ変換します。

文字列から数値への変換にはstrtodを使用します。strtodは変換後の値だけでなく、文字列のどこまでを数値として変換できたかも確認できます。そのため、12ABCのような入力を正しくエラーとして扱えます。

四則演算の動作を決める

2つの入力値を、それぞれvalue1とvalue2として考えてみましょう。

各ボタンをクリックしたときの計算方法は次のようになります。

ボタン演算計算内容
足し算加算value1 + value2
引き算減算value1 - value2
掛け算乗算value1 × value2
割り算除算value1 ÷ value2

引き算と割り算では、値の順番が重要です。

たとえば、1つ目の入力欄に10、2つ目の入力欄に2を入力した場合、計算結果は次のようになります。

操作計算表示結果
足し算10 + 2計算結果:12
引き算10 - 2計算結果:8
掛け算10 × 2計算結果:20
割り算10 ÷ 2計算結果:5

2つ目の値から1つ目の値を引いたり、2つ目の値を1つ目の値で割ったりする仕様ではない点に注意しましょう。

必要なウィジェットを整理しよう

今回のGUI電卓では、画面の部品として複数のウィジェットを使用します。

ウィジェット個数役割
GtkApplicationWindow1GUI電卓全体を表示するウィンドウ
GtkGrid1ラベル、入力欄、ボタンを表のように配置する
GtkLabel3入力欄の説明と計算結果を表示する
GtkEntry22つの数値を入力する
GtkButton5四則演算とクリア操作を実行する

GtkLabelは、次の3か所で使用します。

  • 1つ目の数値を案内するラベル
  • 2つ目の数値を案内するラベル
  • 計算結果やエラーメッセージを表示するラベル

GtkButtonは、次の5個を配置します。

  • 足し算ボタン
  • 引き算ボタン
  • 掛け算ボタン
  • 割り算ボタン
  • クリアボタン

画面のレイアウトを決める

ウィジェットはGtkGridを使って表のように配置します。

画面の上から順番に、次のような構成にします。

行左側右側
1行目1つ目の数値を示すラベル1つ目のGtkEntry
2行目2つ目の数値を示すラベル2つ目のGtkEntry
3行目足し算ボタン、引き算ボタン掛け算ボタン、割り算ボタン
4行目計算結果を表示するGtkLabel複数列を使って配置
5行目クリアボタン複数列を使って配置

演算ボタンは4個あるため、実際にはGtkGrid上で横方向に並べます。結果ラベルとクリアボタンは、必要に応じて複数の列にまたがるように配置します。

図2:GUI電卓を構成するウィジェット

この図から分かること

GtkApplicationWindowの中には、レイアウトを管理するGtkGridを1つ配置します。さらに、GtkGridの子ウィジェットとして入力欄、演算ボタン、結果ラベルなどを配置します。

GtkEntryやGtkButtonを直接ばらばらに管理するのではなく、GtkGridへまとめて配置することで、画面を行と列に沿って整えられます。

このウィジェット階層は、6.2で改めて整理し、6.3で実際のプログラムとして作成します。

計算結果の表示方法を決める

計算結果は、画面内のGtkLabelに表示します。

アプリケーションを起動した直後は、次のように表示します。

計算結果:

正常に計算できた場合は、同じラベルを次のように更新します。

計算結果:12.5

計算するたびに新しいラベルを作るのではなく、最初に作成した結果表示用のGtkLabelの文字列を変更します。

結果は、整数と小数の両方を自然に表示できる形式にします。たとえば、計算結果が5の場合は5、3.5の場合は3.5と表示します。必要以上に0が並ばないよう、完成版では表示形式も調整します。

入力エラーが発生したときの動作を決める

GUIアプリケーションでは、利用者が必ず正しい値を入力するとは限りません。入力に問題がある場合は計算を行わず、結果表示用のGtkLabelにエラーメッセージを表示します。

入力欄が空の場合

1つ目の入力欄が空の場合は、次のように表示します。

1つ目の値を入力してください。

2つ目の入力欄が空の場合は、次のように表示します。

2つ目の値を入力してください。

空白文字しか入力されていない場合も、空欄として扱います。

数値以外が入力された場合

数値へ変換できない文字が入力されている場合は、どちらの入力に問題があるのか分かるメッセージを表示します。

1つ目の値を数値で入力してください。

または、次のように表示します。

2つ目の値を数値で入力してください。

ABCだけでなく、12ABCのように数値の後ろへ文字が続いている場合もエラーにします。

0で割ろうとした場合

割り算では、2つ目の値が0の場合に計算できません。

この場合は、計算結果の代わりに次のメッセージを表示します。

0では割り算できません。

0.0や-0.0も0として扱います。

エラーが発生した入力欄へフォーカスを移す

入力エラーが見つかった場合は、問題のあるGtkEntryへフォーカスを移します。利用者は、そのまま値を入力し直せます。

たとえば、2つ目の入力欄が空だった場合は、2つ目のGtkEntryへフォーカスを移します。

演算ボタンをクリックしたときの流れ

演算ボタンにはclickedシグナルを接続します。利用者がボタンをクリックすると、計算を担当するコールバック関数が呼び出されます。

コールバック関数では、次の順番で処理します。

  1. 2つのGtkEntryから文字列を取得する
  2. 入力欄が空でないか確認する
  3. 文字列をdouble型の数値へ変換する
  4. 数値へ正しく変換できたか確認する
  5. 割り算の場合は2つ目の値が0でないか確認する
  6. 選択された四則演算を実行する
  7. 計算結果を文字列に変換する
  8. 結果表示用のGtkLabelを更新する

途中で入力エラーが見つかった場合は、それ以降の計算を行いません。計算結果の代わりにエラーメッセージを表示します。

図3:演算ボタンをクリックしたときの処理

この図から分かること

演算ボタンをクリックしても、すぐに四則演算を実行するわけではありません。最初に文字列を取得し、空欄や数値以外の入力がないことを確認する必要があります。

すべての確認を通過した場合だけ計算を実行し、結果をGtkLabelへ表示します。入力に問題がある場合は、処理を途中で止めてエラーメッセージを表示します。

クリアボタンの動作を決める

クリアボタンをクリックしたときは、GUI電卓を起動直後の状態へ戻します。

実行する処理は次のとおりです。

  • 1つ目のGtkEntryを空にする
  • 2つ目のGtkEntryを空にする
  • 結果ラベルを計算結果:へ戻す
  • 1つ目のGtkEntryへフォーカスを移す

クリア後の画面は、次の状態になります。

項目クリア後の状態
1つ目の入力欄空欄
2つ目の入力欄空欄
結果ラベル計算結果:
キーボードフォーカス1つ目の入力欄

エラーメッセージが表示されている場合も、クリアボタンを押すと計算結果:へ戻します。

操作結果の例を確認しよう

完成後のGUI電卓では、次のような操作ができるようにします。

1つ目の入力2つ目の入力操作表示内容
157足し算計算結果:22
157引き算計算結果:8
157掛け算計算結果:105
153割り算計算結果:5
52割り算計算結果:2.5
-53足し算計算結果:-2
空欄3足し算1つ目の値を入力してください。
ABC3足し算1つ目の値を数値で入力してください。
100割り算0では割り算できません。

今回は実装しない機能

作成する機能の範囲を明確にするため、今回は実装しない機能も決めておきましょう。

実装しない機能内容
数字入力ボタン0から9までのボタンは配置しない
計算履歴過去の計算結果は保存しない
連続計算前回の結果を自動的に次の計算へ利用しない
関数計算平方根、べき乗、三角関数などは扱わない
メモリー機能M+、M-、MRなどは実装しない
キーボードショートカット演算は画面上のボタンで実行する

機能を四則演算に絞ることで、GtkEntry、GtkButton、GtkLabel、GtkGrid、シグナル、コールバック関数といったGTK 4の基本を一つずつ確認できます。

第6章でGUI電卓を完成させる流れ

GUI電卓は、6.1から6.10までを通して段階的に作成します。

節作業内容
6.1GUI電卓の機能と動作を決める
6.2chap06とcalculator.cを準備し、ウィジェットの階層を設計する
6.3GtkEntry、GtkButton、GtkLabel、GtkGridで画面を作る
6.4GtkEntryから入力文字列を取得する
6.5strtodで文字列を数値へ変換する
6.6足し算、引き算、掛け算、割り算を実装する
6.7空欄、数値以外、0による割り算に対応する
6.8入力内容と結果を初期状態へ戻す機能を作る
6.9GTK CSSで文字サイズや余白を整える
6.10プログラム全体を完成させ、コンパイルと動作確認を行う

次の6.2ではC:\cgui\chap06を準備し、calculator.cを作成します。2章ですでにchap06を作成している場合は、ディレクトリの作成を省略し、そのままcalculator.cの準備へ進めます。