コンテンツにスキップ

Pythonアプリ(7):電卓を作ろう!

電卓を作ろう

デスクトップアプリの定番、電卓を作ってみましょう。

tentoapp-07-01.png

数字や記号のボタンをクリックすると上に表示され、“=”ボタンで結果が出るようにします。

1. 数字ボタンを並べよう

まず、0から9までの数字を格子状に並べます。 カレンダーのときとは少し違うやり方をしてみましょう。

from tentoapp import *
app = App()
le = Label(app)
le.grid(0,0)
le.colspan = 4
for i in range(10):
b = Button(app)
b.text = str(i)
col = i % 3
row = i // 3 + 1
b.grid(col, row)
app.start()

tentoapp-07-03.png

1.1 計算式を表示する

計算式の作成部分
le = Label(app)
le.grid(0,0)
le.colspan = 4

計算式の表示部分はLabelにします。 横に4マスぶんの大きさにするので、 le.colspan = 4 のように、colspan(コルスパン)を設定します。

1.2 数字ボタンを表示する

数字ボタンの作成部分
for i in range(10):
b = Button(app)
b.text = str(i)
col = i % 3
row = i // 3 + 1
b.grid(col, row)

0-9までの数字ボタンはfor文で作成します。 range(10) は0-9までの数字を返します。 ここでは、横方向の位置(col)と縦方向の位置(row)の決め方に注目してください。カレンダーのときはfor文を二重にして(二重ループ)で作りましたが、実は簡単な計算でcolとrowを求めることができます。

数字がどこに並ぶかを考えると、下の図のようになります。

tentoapp-07-04.png

まず、colから考えてみましょう。0と3と6はcolが0です。0と3と6は3で割ると余りが0になる数です。また、1と4と7はcolが1ですが、これは3で割ると余りが1になる数ですね。同じように2と5と8は3で割ると余りが2になる数です。すると、colは 数字を3で割った余り で計算できることになります。これをPythonのコードであらわすと col = i % 3 となります。

次にrowを見てみましょう。0と1と2はrowが0です。これは0と1と2はどれも3より小さいからです。言いかえると、0と1と2は3がひとつも含まれないからです。3と4と5は3で割ると3が1個しか含まれず、rowが1になります。6と7と8は3で割ると3が2個含まれるのでrowは2です。すると、rowは 数字に3がいくつ含まれるか で計算できることになります。数字を3で割って少数を切り捨てればよいのです。Pythonだとふつうの割り算は / ですが、 // を使うと少数を切り捨てた整数だけが返されます。そこで、 row = i // 3 とすればよいのです。 実際のコードで row = i // 3 + 1 と最後に+1してあるのは、1行目には計算式を表示するからです。

2. 計算記号のボタンを作ろう

次に計算記号のボタンを作ります。“=”だけはちょっと性格が違うので別に作ります。

from tentoapp import *
app = App()
le = Label(app)
le.text = ""
le.grid(0,0)
le.colspan = 4
for i in range(10):
b = Button(app)
b.text = str(i)
col = i % 3
row = i // 3 + 1
b.grid(col, row)
kigou = ["+","-","*","/"]
row = 1
for k in kigou:
b = Button(app)
b.text = k
b.grid(3,row)
row += 1
beq = Button(app)
beq.text = "="
beq.grid(3,5)
app.start()

tentoapp-07-01.png

2.1 四則演算のボタンを追加する。

足し算(+)、引き算(-)、掛け算(*)、割り算(/)のボタンを作ってみましょう。

(部分)
kigou = ["+","-","*","/"]
row = 1
for k in kigou:
b = Button(app)
b.text = k
b.grid(3,row)
row += 1

リストkigouに記号を入れ、for文でひとつひとつ作っていきます。どれも一番右側のマスに置くのでcolは3で固定です。

2.2 =のボタンを作る

“=”のボタンだけはクリックしたときの動作が違うので別に作ります。位置は右側の一番下です。

一部
beq = Button(app)
beq.text = "="
beq.grid(3,5)

3. ボタンを動作させよう。

次にボタンをクリックしたら動くようにします。ボタンはたくさんあるので、ひとつひとつに関数を作ると大変です。そこで、“=”以外のボタンを押したときの関数と“=”のボタンを押したときの関数の2個だけで済むようにします。

from tentoapp import *
app = App()
def btnclick(e):
text = e.widget.text
le.text += text
def beqclick():
le.text = eval(le.text)
le = Label(app)
le.text = ""
le.grid(0,0)
le.colspan = 4
for i in range(10):
b = Button(app)
b.text = str(i)
col = i % 3
row = i // 3 + 1
b.onclick = btnclick
b.grid(col, row)
kigou = ["+","-","*","/"]
row = 1
for k in kigou:
b = Button(app)
b.text = k
b.onclick = btnclick
b.grid(3,row)
row += 1
beq = Button(app)
beq.text = "="
beq.onclick = beqclick
beq.grid(3,5)
app.start()

tentoapp-07-02.png

3.1 “=”以外のボタンの動作

まず、“=”以外のボタンの動作を作ります。

btnclick関数
def btnclick(e):
text = e.widget.text
le.text += text

btnclick() 関数は“=”以外のボタンをクリックすると動作するように設定しますが、どのボタンがクリックされたかがわからないと困ります。そこで、btnclick関数に 引数(ひきすう)e をつけます。このeにはクリックされたときの情報が入っています。 e.widget で、クリックされたウィジェット(ここではボタン)がわかるので、その text プロパティを読み出せばボタンの文字を取り出せます。あとは、 le.text += text でその文字を計算式の表示部分のラベルに追加しています。

部分
b.onclick = btnclick

2つあるfor文の中に上記のコードを入れて、実際にボタンをクリックしたらbtnclick関数が呼ばれるようにしましょう。

3.2 “=”ボタンの動作

次に“=”ボタンの動作を作ります。

beqclick関数
def beqclick():
le.text = eval(le.text)

ここでは、 eval(イーバル) という関数を使っています。計算式に表示された文字列をevalで処理して、その結果をもう一回計算式の表示ラベルに入れています。 evalは、計算式を渡すと実際にその計算をやってくれるという大変便利な関数なのです。

部分
beq.onclick = beqclick

onclickプロパティを設定するのも忘れずに!

やってみよう!

1. ボタンの幅を調整しよう☆

ボタンがちょっと全体的に横長なので、フォントサイズや横幅を調整してください。

2. クリアボタンをつけよう☆☆

このままだと、新しい計算をするときにはもういちどアプリを立ち上げ直す必要があります。クリアボタン(C)をつけて、計算式を消せるようにしましょう。

3. 数字を並べ替えよう☆☆☆

ふつうの電卓は、下に小さい数字が来て、上に大きい数字が並ぶようになっています。ユーザが違和感を抱かないように数字を並べ替えてください。

4. 計算の結果が残るようにしよう☆☆☆

一番下に計算式とその結果が何件か残るようにしてください。

12*3+5=41
45+5/2=47.5

のように表示されると良いですね。