だぶるばいせっぷす 新館

ホワイトカラーではないブルーカラーからの視点

【プログラミング】 python奮闘記 その11 ~ボタンを作ってみる

この記事は、現在進行系でゼロからプログラミングを勉強している私が、勉強の一環として進展状況をアウトプットする目的で投稿しています。
その為、間違った記述や無駄な作業が結構多めとなっていますが、『それでも良いから一緒に勉強している気になりたい』という方に向けて書いていますので、予め御了承ください。

前回は、記入欄の設置と、そこから値を取り出して、関数によって数値を加工するというところまでやりました。
ただ、前回までの記述では、関数を動かすことが出来てないので、プログラム上で正常に動くかどうかも分かりません。
プログラム上で動いている事が分かるように、関数を動かすための仕組みを作ろうと思います。
kimniy8.hatenablog.com

このプログラムでは、『見積もり開始』ボタンが押された事をキッカケにして、プログラムが動くようにしたいので、まず、そのボタンを作ります。
ボタンを作るのは、『tkinter』の『Button』で作れます。
質問ボタンという意味で、ボタンの値を入れる変数には『askbutton』という名前を付けてみました。

# ボタン表示
askbutton = tkinter.Button(text="見積開始")
askbutton.place(x=310, y=40)

『text』部分には、ボタンに表示させる文字列が書いてあります。
ボタンの大きさは、文字の長さによって自動的に決めてくれるので、非常に簡単に設置できますね。
placeでは、お馴染み、ボタンの場所を指定しています。
f:id:kimniy8:20180607234826j:plain
ボタン部分の記述は、ボタンの位置が記入欄の横なので、記入欄の次ぐらいに書いておくと良いかも知れません。

次に、ボタンが押された際に実行できるようにする為には

askbutton["command"] = ask_click    

と書きます。
位置としては、メインループの真上ぐらいが良いと思います。
この記述の意味としては、『askbutton』が押された時に『命令(command)』が下され、命令によって、『ask_click』が発動するという意味です。
ボタンが押された際に関数が発動するという状態にしたい場合は、取り合えす『ボタンの変数名["command"] = 関数名』と書いておけば良いと暗記しておけば良いでしょう。
私もまだまだ知識が浅いので、これぐらいの認識しか出来ていません。

これで、ボタンを押すことで関数を実行することは出来るんですが、作った関数が答えを出力する場所を作っていないので、実行したとしても意味がありません。
という事で、何らかの数値を出力するようにしてみましょう。

取り敢えず動く感じが見たいという事で、簡単な出力にしておきます。
表示させるのは、ボール紙の『縦』『横』の大きさだけです。
画面上に変数を表示させるので、まずは、変数に必要な情報を代入していきます。

関数内で変数を定義した場所の下ぐらいの場所で、変数に表示させたい内容を代入していきます。
関数内なので、インデントを合わせる事に注意しましょう。

    b_areay["text"] = "身のボール紙の縦" + str(b_tate) + "mm"
    b_areax["text"] = "身のボール紙の横" + str(b_yoko) + "mm"
    b_areax_f["text"] = "身のボール紙の縦" + str(b_tate_f) + "mm"
    b_areay_f["text"] = "身のボール紙の横" + str(b_yoko_f) + "mm"

変数名の意味合いとしては、ボール紙のローマ字の頭文字と、面積を表す『aera』に、x軸とy軸という意味のx,yをくっつけただけで、_fは『蓋』の略です。
これで、実行できるはずです。早速、数値を適当に入れて実行してみましょう。

このついでに、結果を画面に出す為の場所も作っておきましょう。
ボタン表示の下ぐらいのスペースに、内訳表示としてこう書きます。

# 内訳表示
b_areax = tkinter.Label(text="ボール紙の身の横幅")
b_areax.place(x=10, y=140)
b_areay = tkinter.Label(text="ボール紙の身の縦幅")
b_areay.place(x=180, y=140)

b_areax_f = tkinter.Label(text="ボール紙の蓋の横幅")
b_areax_f.place(x=10, y=200)
b_areay_f = tkinter.Label(text="ボール紙の蓋の縦幅")
b_areay_f.place(x=180, y=200)

もう説明も不要ですね。
ウィンドウに文字を表示させてくれる『tkinter.Label』です。引数である『text=""』の中身は、関数発動前のデフォルトの値として表示される内容で、関数が発動すると、文字の内容は変数の内容に変化します。
つまり、関数が発動前で、変数に何の値も入っていない時は、デフォルト値として『text=""』以降の文が表示されるけど、関数が発動して変数に値が入ると、表示内容が変数の値に変わるって認識で良いと思います。
引数としてなにも設定しない場合は、何も表示されません。

これで、入力した値を元に計算を行い、結果を出力するというプログラムが完成しました。
早速実行してみましょう。
f:id:kimniy8:20180607234914j:plain
はい、見事にエラーが出ました。
私は英語は読めませんが、『b_tate_f = b_long + 5 + b_hi*2 # ボール紙の蓋の縦』の部分で『typeエラー』が出ていて、『str』『not』『int』という言葉が読み取れます。
エラーの種類としては、『str』という文字列と、『int』という整数値という『type』が違う者同士を計算式、厳密には足し算に織り交ぜたことが原因のようです。文字列と掛け算は可能ですしね。
でも変ですよね? 変数『b_tate_f』も『b_hi』も『5』も、全部整数値であるintのハズなのに、なんでエラー?
これは、私が設定した記入欄の問題で、『tkinter.Entry』は、記入欄を作ってくれるんですが、その入力値は文字列になってしまうようなんです。
つまり、数字を入力したとしても、『"100"』という文字として受け取っている為、文字列を足し算がある計算式に入れると、『違うタイプ同士は計算できないよ!』というエラーが出てきたという事。

解決策として、関数開始直後の変数値を、改造します。
改造前がこちら

    b_hi = box_height.get() # 箱の高さ
    b_wid = box_width.get() # 箱の幅
    b_long = box_length.get() # 箱の長さ

そして改造後がこちら

    b_hi = int(box_height.get()) # 箱の高さ
    b_wid = int(box_width.get()) # 箱の幅
    b_long = int(box_length.get()) # 箱の長さ

記入欄である『Entry』の値を格変数に代入する際に、int()で括ることによって、値を整数値に変換しています。
注意としては、()の数は合わせましょう。 最後の部分は、get()の)とint()の)が被ることによって『))』となっています。
これで値の『type』が揃ったはずなので、エラーが出ずに結果が出るはずです。
早速試してみましょう。
f:id:kimniy8:20180607235013j:plain
はい、見事に出ました。
これで、数値を入力して結果を表示するという簡単なプログラムが完成したことになります。
後は、見積もりが出来るようにするために、この関数を改造していくだけですが、それは次回以降にしていきます。
kimniy8.hatenablog.com

今回までで書いたプログラムの全体はこんな感じです。

import tkinter

# ウィンドウ作成
root = tkinter.Tk()
root.title("見積もり")
root.minsize(640, 480)

# 画像表示
canvas = tkinter.Canvas(bg="black", width=640, height=480)
canvas.place(x=0, y=0)


# テキスト表示
heading = tkinter.Label(text="お見積り")
heading.place(x=10, y=10)


# テキストボックス表示
box_width = tkinter.Entry(width=10, bd=4)
box_width.place(x=10, y=40)

box_length = tkinter.Entry(width=10, bd=4)
box_length.place(x=110, y=40)

box_height = tkinter.Entry(width=10, bd=4)
box_height.place(x=210, y=40)

# ボタン表示
askbutton = tkinter.Button(text="見積開始")
askbutton.place(x=310, y=40)


# 内訳表示
b_areax = tkinter.Label(text="ボール紙の身の横幅")
b_areax.place(x=10, y=140)
b_areay = tkinter.Label(text="ボール紙の身の縦幅")
b_areay.place(x=180, y=140)

b_areax_f = tkinter.Label(text="ボール紙の蓋の横幅")
b_areax_f.place(x=10, y=200)
b_areay_f = tkinter.Label(text="ボール紙の蓋の縦幅")
b_areay_f.place(x=180, y=200)


# ボール紙の大きさ
def ask_click():
    b_hi = int(box_height.get()) # 箱の高さ
    b_wid = int(box_width.get()) # 箱の幅
    b_long = int(box_length.get()) # 箱の長さ
    b_tate = b_long + b_hi*2 # ボール紙の長さ
    b_yoko = b_wid + b_hi*2 # ボール紙の幅
    b_tate_f = b_long + 5 + b_hi*2 # ボール紙の蓋の縦
    b_yoko_f = b_wid + 5 + b_hi*2 # ボール紙の蓋の横

    b_areay["text"] = "身のボール紙の身の縦" + str(b_tate) + "mm"
    b_areax["text"] = "身のボール紙の身の横" + str(b_yoko) + "mm"
    b_areax_f["text"] = "身のボール紙の蓋の縦" + str(b_tate_f) + "mm"
    b_areay_f["text"] = "身のボール紙の蓋の横" + str(b_yoko_f) + "mm"

askbutton["command"] = ask_click            
# メインループ
root.mainloop()