CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
こんにちは、吉政創成 菱沼です。
今回も「いちばんやさしいPython入門教室(大澤 文孝氏著) 」を片手に勉強していきます。
さて前回は、ゲームを終了させるボタンの作り方と、Tkinterで作成した画面とヒット&ブローのプログラムをくっつけたところまでで終了しました。今回は、まだ残っているユーザーが入力してきた値の履歴が表示される部分を追加します。またボタンを使ってちょっとした機能も追加してみました。どうぞお付き合いいただければ幸いです。
完成とするにはユーザーの入力履歴と、入力された値に対するヒットとブローの数を表示する部分が必要です。
ちなみに前回までに作ったのが左側、最終的に目指す画面が右側です。(実際の画面より縮小しています。)
というわけで、この右側の画像のように、履歴を表示する部分をどのようにつければいいのかをまずは確認します。
引用----
P.176
履歴の表示には、テキストボックスという部品を使います。しかし、今のウィンドウサイズでは、テキストボックスを入れるだけのスペースがありません。そこで、まずはウィンドウを大きくしましょう。
(中略)
>>>root.geometry("400x150")
のように、「400×150」のサイズだったものを、
>>>root.geometry("600x400")
に変更します。
そして広がった場所に、テキストボックスを使って配置します。引数には、「配置先のウィンドウ」と「フォント」を指定します。テキストボックスを作るには、Textメソッドを実行します。ここではフォントサイズを14ポイントにしました。
そして作ったテキストボックスを「rirekibox」という変数に代入しました。
Textメソッドの使用例
>>> rirekibox = tk.Text(root, font=("Helvetica", 14))
作成したら、このテキストボックスを「# ウィンドウを作る」の命令群の下に「# 履歴表示のテキストボックスを作る」とコメントをつけて追記します。
------
TextメソッドはTkinterにある複数行の文字列が入力できるもので、ここではプログラムから文字列が引き渡されていますが、直接文字を入力することもできるものになります。
ということで、実際にやってみました。
画面全体のサイズは幅600、縦400です。
テキストエリアの設置位置はX(横軸)が400で、幅は200なので、400+200=600で全体の幅になりますね。Y(縦軸)の設定が0で、高さは400ということで、右端にぴったりテキストエリアがくっつく感じです。
実行してみると、たしかに右側にぴったり履歴欄が追加されました。
Textエリアを追加したものの、このままではただの箱なので、履歴を表示されるようにプログラムの部分を変更してあげなくてはいけません。
引用----
P.178
今までのプログラムでは、判定結果を「# ヒット数とブロー数を表示」以下、
>>> tmsg.showinfo("ヒント", "ヒット " + str(hit) + "/" + "ブロー " + str(blow))
として、ダイアログで表示していたので、この部分を変更します。
テキストボックスに文字を追加するには、insertメソッドを使います。最初の引数に「tk.END」を指定すると、「末尾」に挿入できます。そこで、次のように書き換えます。
Memo)ここではtkinterを「import tkinter as tk」のように「tk」という名前でインポートしているので「tk.END」です。他の名前でインポートした場合は「その名前.tk」です。
>>>rirekibox.insert(tk.END, b + " /H:" + str(hit) + " B:" + str(blow) + "\n")
-----
ということだそうなので、該当の箇所を変更してみます。
変更した後に適当に打ち込んでみました。
表示されるようになりました!やったー!!完成です!!
ところで、「tk.END」についてですが、これは「文書の最後の文字の位置」という意味を持つ、あらかじめ定義されたインデックスだそうです。
インデックスといえば、値の最初は[0]で、順番に[1][2]...とインデックス番号がつけられていきます。最後尾から数える場合には[-1]から始めて順番に[-2][-3]...と続けられます。文字数を数えなくても末尾が指定できるので便利ですねー。
あらかじめ定義されたものは「tk.END」以外にもありました。
<定義されたインデックス名>
インデックス | 意味 |
Tk.INSERT | 挿入カーソルのある位置 |
Tk.CURRENT | マウスポインタに一番近い文字位置 |
Tk.END | 文書の最後の文字の次の位置 |
Tk.SEL_FIRST | 選択範囲の最初の位置 |
Tk.SEL_LAST | 選択範囲の最後の位置 |
詳しくは参考リンクをご参照ください。
さて、引用文内にあったinsertメソッドについても調べてみました。これは指定した位置に要素を挿入することができるメソッドで、以下の書式で書かれるそうです。
>>>リスト名.insert(インデックス, 要素)
これを先ほど追加した文に当てはめてみますと、こうなります。
ここでは文末を指定していますが、例えば2行目に追加したいなら「'2.0'」と書けば、「2行目の0文字目」といったように、細かく指定もできるようです。
ここではinsertしか使っていませんが、他にget(取得)、delete(削除)、index(現在のカーソル位置)が使えるそうです。
具体的な使い方は参考リンクをご参照ください。
参考:Tkinter、Textウィジェットの使い方|Narito Blog
さてテキストで説明されているゲームはこれで完成しているのですが、せっかくなのでゲームを終了するボタンと、Entry(数字を入れる部分)に入力した値を消すボタンをつけてみたいと思います。こんな感じで追加してみました。
tkinterのEntryの値を削除するにはdeleteというメソッドを使用します。どこから消すかという指定はインデックス番号でもいいですし、先ほどの「tk.END」でもできます。
最初の文字のインデックス番号は[0]なので、文末を意味する「tk.END」と組み合わせれば「0,tk.END」となります。
このプログラムでは最大の文字数が4文字なので、[3]を指定しても消せますが、ゲームをしている人がうっかりさんだった場合は4文字以上入力する可能性もあるので、「tk.END」を指定しておけば確実に削除できます。
ちなみに、値の削除はdel文というものもあるようです(ここで使えるかは試していませんが...)。del文なら、インデックスで範囲を指定する以外に、スライスで範囲指定をすることもできるようです。あることだけはとりあえず覚えておこうと思います...。
例)[2]~[6]を削除したい:del x[2:6]
[3]までを削除したい :del x[:3]
del関数を使った範囲指定について詳しく知りたい方は参考リンクをご参照ください。
参考:Pythonでリスト(配列)の要素を削除するclear, pop, remove, del|note.nkmk.me
(インデックス・スライスで位置・範囲を指定して削除: delの項目)
ゲームが正解すると画面が消えるプログラムになっていますが、飽きて辞めたくなったら押せるボタンです。もちろん、ウィンドウの×ボタンでも消えるので、要らないといえば要らないボタンでもあります。が、とりあえずせっかくなのでやってみました。
これは前回学んだ方法のまま追加しています。まず「Btc_close」という関数をdefで自作します。
関数Btc_closeで行うのは、「メッセージボックス:askyesno」の「はい」をクリックしたときに返されるのは「True」ですが、この「True」が返されたときにゲームを終了するというif文を設定しています。
そしてできたのが↓の画面。フォントはこっそりメイリオに変更しています。
クリアボタンを押したらテキストボックスの中から文字が消えるのも確認済みです。
ちなみに、チェックボタンを押したらテキストボックスの数字も消えてくれたら楽でいいんじゃないの?と思ったので、クリアボタンでつかった「editbox1.delete(0,tk.END)」を「ButtonClick」関数に追加してみたら思った通り、答えを投入するたびに毎回消えてくれるようになりました。楽だなあ。
テキストにないことを追加したりと寄り道をしまくりましたが、とりあえずこれでヒット&ブローの作成は終了です。
追加してみたい機能はほかにもありしますが、それは時間を見つけてやり方を学んで追加してみたいと思います。
それでは今回はこちらで終了です。次回から新しい章に入っていきます。
最後に一応、プログラムの全体像を載せておきます。短縮版に置き換えた部分の元のコードは青点線で囲んで配置しました。長いので、ご興味ある方はご参照ください。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes