Python3作るアンケートフォーム【GUI応用編】
2015/11/04
第四回目のPython3記事です。
今回は、前回のおさらいをするとともに、もっさりした一本のコードをさっぱりさせます。
Python初心者の人達の理解に役立ったら幸いです。
記事前半では、コードの解説。
後半から、前回のコードとの比較をします。
graphics.pyライブラリーを用いて、Python3でGUIを表示しました。
今回もこのライブラリーを用いますので、持ってない無い方は上記のリンクから落として下さい。
オープンソース、ありがたいですね。
前回の コード同様、このコードも動作はしますが、完璧ではありません。
が、ベストをつくして書いてます。
from graphics import * def main(): global win win = GraphWin('Form Window',400,400) display_Submit() quesArray = ['Enter your name','Enter your gender'] answers = display_Question(quesArray) answers += display_Question(chck_Gen(answers)) writeToFile(answers) def writeToFile(args): ans = args str_ans = 'Name: %s, Age: %s, Relationships: %s, Phone: %s, Email: %s'%(ans[0],ans[1],ans[2],ans[3],ans[4]) file = open(ans[0]+'.txt','w') file.write(str_ans) file.close() def chck_Gen(ans): if ans[1].lower() == 'male': ques2Array = ['Do you have a girlfriend','Enter your phone number','Enter your email address'] elif ans[1].lower() == 'female': ques2Array = ['Do you have a boyfriend?','Enter your phone number','Enter your email address'] else: ques2Array = ['Do you have a partner?','Enter your phone number','Enter your email address'] return ques2Array def display_Submit(): submitBtnTxt = Text(Point(320,110),'Submit') submitBtnTxt.draw(win) submitBtn = Rectangle(Point(290,100),Point(350,120)) submitBtn.draw(win) def display_Question(arr_Question): quesArray = arr_Question ansArray = [] for i in range(len(quesArray)): submit = False quesMessage = Text(Point(160,50),'Q.'+str(i+1)+': '+quesArray[i]) quesMessage.draw(win) inp = Entry(Point(150,70),20) inp.draw(win) while submit == False: click = win.getMouse() if 300 <= click.getX() <= 340 and 100 <= click.getY() <=120: submit = True answer = inp.getText() ansArray.append(answer) quesMessage.undraw() inp.undraw() return ansArray main()
上記のコードを、コピペしてform_gui.pyと名付けて保存し、開いてみて下さい。
え?英語じゃねーか?
こういう所から英語に慣れましょう。
動かない方は、graphics.pyをダウンロードして、form_gui.pyと同じディレクトリーに入れて試して下さい。
ステップステップに、コードを観ていきたいと思います。
from graphics import *
ダウンロードした、graphics.pyライブラリーを導入します。
def main(): global win win = GraphWin('Form Window',400,400) display_Submit() quesArray = ['Enter your name','Enter your gender'] answers = display_Question(quesArray) answers2 = display_Question(chck_Gen(answers)) mergedAns = answers + answers2 writeToFile(mergedAns)
今回のmainは、ウィンドウを表示し、送信ボタンを表示し、質問を表示し、答えを保持し、答えによって質問を変え、結果をファイルに保存させてます。
global win
globalというキーワードはwinという変数をグローバル変数にします。
これにより、他の関数も引数なしで参照が出来ます。
しかし、この方法はあまり、推奨されません。なぜなら、どこからでも参照出来るということは、予期しない誤作動を招きかねません。
Pythonを含め多くのプログラミング言語において、変数の参照範囲は重要なコンセプトです。
変数の参照範囲は、スコープと呼ばれ、参照範囲外の場合(スコープ外)その変数は参照が出来ないのです。
main()の中の変数は、main()の中だけでこそ、有効だが、globalは全てのスコープの中に入る事になります。
win = GraphWin('Form Window',400,400)
GraphWinという関数は、graphics.pyライブラリーに入ってる関数です。
display_Submit()
display_Submit()という関数を呼び出しています。
この関数は、32行面から始まる関数を呼び出しています。
観てみましょう。
def display_Submit(): submitBtnTxt = Text(Point(320,110),'Submit') submitBtnTxt.draw(win) submitBtn = Rectangle(Point(290,100),Point(350,120)) submitBtn.draw(win)
def display_Submit():
で関数の定義を始めましょう。
sumitBtnTxtを作って表示し、submitBtnを作って表示しているだけですね。
quesArray = ['Enter your name','Enter your gender'] answers = display_Question(quesArray)
質問の配列を作って、display_Questionという関数に渡します。
観てみましょう。
def display_Question(arr_Question): quesArray = arr_Question ansArray = [] for i in range(len(quesArray)): submit = False quesMessage = Text(Point(160,50),'Q.'+str(i+1)+': '+quesArray[i]) quesMessage.draw(win) inp = Entry(Point(150,70),20) inp.draw(win) while submit == False: click = win.getMouse() if 300 <= click.getX() <= 340 and 100 <= click.getY() <=120: submit = True answer = inp.getText() ansArray.append(answer) quesMessage.undraw() inp.undraw() return ansArray
display_Questionは引数を一つ取ります。
受け取った質問の配列を元に、ループします。
ちなみにこのロジックだと、Qの後の数字が正しく表示されません。
基本的に前回と、全く同じ構造です。
answers += display_Question(chck_Gen(answers))
出来上がったanswers変数を、chck_Gen(answers)に渡して、さらにそれを、display_Questionに渡します。
返された答えを、answersに足し入れます。
def chck_Gen(ans): if ans[1].lower() == 'male': ques2Array = ['Do you have a girlfriend','Enter your phone number','Enter your email address'] elif ans[1].lower() == 'female': ques2Array = ['Do you have a boyfriend?','Enter your phone number','Enter your email address'] else: ques2Array = ['Do you have a partner?','Enter your phone number','Enter your email address'] return ques2Array
chck_Gen()関数は、引数を一つとり、答えの結果によって、返す質問の配列を変えています。
この手法の場合、すべてのケースをコードに書かないといけません。
writeToFile(answers)
帰ってきた答えを、writeToFile()関数に飛ばします。
def writeToFile(args): ans = args str_ans = 'Name: %s, Age: %s, Relationships: %s, Phone: %s, Email: %s'%(ans[0],ans[1],ans[2],ans[3],ans[4]) file = open(ans[0]+'.txt','w') file.write(str_ans) file.close()
この関数は、フォーマットして、ファイルに書き込みます。
文字列のフォーマットのルールは単純です。
' 'の間には、文字列が入ります。
' ' または" "は文字列である、という事を意味しています。
num = 1とnum = "1"は、前者はintであるのに対して後者はstringです。
入れたい文字の所を、%sと置き換えます。%は置き換えのための印でsはStringの略です。
' 'のあとに%(入れたい言葉の変数) と書くことで表示出来ます。
今回は、さっくりと、前回のコードを綺麗に関数にして書き直しました。
前回のコードを観てみましょう。
from graphics import * win = GraphWin('Form Window',400,400) message =Text(Point(160,20),'Welcome. Please answer following questions.') message.draw(win) quesArray = ['Enter your name','Enter your gender'] ques2Array = ['Enter your age','Enter your phone number','Enter your email address'] ansArray = [] submitBtnTxt = Text(Point(320,110),'Submit') submitBtnTxt.draw(win) submitBtn = Rectangle(Point(290,100),Point(350,120)) submitBtn.draw(win) for i in range(len(quesArray)): submit = False quesMessage = Text(Point(160,50),'Q.'+str(i+1)+': '+quesArray[i]) quesMessage.draw(win) inp = Entry(Point(150,70),20) inp.draw(win) while submit == False: click = win.getMouse() if 290 <= click.getX() <= 350 and 100 <= click.getY() <=120: submit = True answer = inp.getText() ansArray.append(answer) quesMessage.undraw() inp.undraw() if ansArray[1].lower() == 'male': quesMessage = Text(Point(160,50),'Q.3: '+ques2Array[0]) elif ansArray[1].lower() == 'female': quesMessage = Text(Point(160,50),'Q.3: '+ques2Array[1]) else: quesMessage = Text(Point(160,50),'Q.3: '+ques2Array[2]) quesMessage.draw(win) submit = False inp = Entry(Point(150,70),20) inp.draw(win) while submit == False: click = win.getMouse() if 290 <= click.getX() <= 350 and 100 <= click.getY() <=120: submit = True answer = inp.getText() ansArray.append(answer) quesMessage.undraw() inp.undraw() message.undraw() message =Text(Point(160,20),'Thank you.') message.draw(win) for i in range(len(ansArray)): print(ansArray[i]) if win.getMouse(): win.close()
長いですね。
このコードが長い理由は、二回目の質問のあたり(41行目あたり)が、少し前の20行目あたりが同じですね。
同じ所は、まとめてしまいます。それが、display_Question()関数になります。
無理に関数に分ける必要もありません。(しかし、ここでは無理にわけてます)
これは、繰り返す作業が多い場合に非常に有効です。
Pythonはスクリプト型言語と言います。言ったことをやってくれる言語です。
つまり、台本(スクリプト)を書けば、実行してくれるのです。
今後、Androidアプリでやる言語はJavaになります。
Javaはオブジェクト指向のプログラミング言語です。
一方で、JavaScriptはオブジェクト指向のスクリプト言語です。
どれもCという言語から生まれた言語です。
ついでにLinuxもCで出来てます。
Cが出来たら仕事あります。(2015年現在)
たとえば、Python3の場合print()で表示します。JavaScriptはalart()またはconsole.log()で表示します。
Javaの場合、まずクラスを作ります。
public class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); } }
そして、これをHelloWorldApp.javaと保存する必要があります。