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と保存する必要があります。




 - フリーソフト紹介 , , ,