2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

『Python2年生 デスクトップアプリ開発のしくみ』をやってみた

2
Posted at

概要

『Python2年生 デスクトップアプリ開発のしくみ 体験してわかる!会話でまなべる!』
は、Pythonを使ったデスクトップアプリ開発の基本を初心者向けに解説している本です。Pythonのインストールから、テキストの表示、計算、テキストや画像ファイルの出力、じゃんけんのような簡単なゲームまで、作り方を説明してくれます。
少しPythonを触ったことがあるのですが、デスクトップアプリの作り方はわからなかったので、試しにやってみることにしました。
この記事は、やった内容や感想の備忘録になります。

最初の壁「外部ライブラリが使えない」

本では主にPySimpleGUIを使用してデスクトップアプリを作っているのですが、そもそもこのライブラリはプロジェクト終了しており、新規にインストールすることができなくなっています。

最初はそれに気づかずインストールを試してエラーとなっていました……
代替としてFreeSimpleGUIというライブラリが使えるので、本の内容は問題なく進めることができます。
(出版社の正誤表にもしっかり記載されていました)

1章・2章:問題なくクリア

1章「Pythonでアプリを作ろう」
2章「アプリ作りの基本」
については、プログラミングの基礎はわかっていることもあり、問題なくクリアしました。

ウィンドウ内に要素の配置するやり方が、FleeSimpleGUIはかなり直感的で、わかりやすかったです。
[]が1つの行を指し、その中の[]要素が横に並ぶイメージです。

layout = [
    [sg.Input('フタバ', key='in',size=(30,1),justification='center')],
    [
        sg.Button('挨拶する', key='meetingBtn'),
        sg.Text(key='txt',size=(50,1),justification='right')
    ]
]

image.png

驚いたのは、FreeSimpleGUIでは画面レイアウトの配色を選べること。
下記を実行すると、配色テーマの一覧を見ることができます。

import FreeSimpleGUI as sg
sg.theme_previewer()

image.png

使い勝手にはそんなに影響しないですが、こういうところで遊べるのはうれしいです。

3章・4章:スムーズにクリア

3章「計算アプリを作ろう」
4章「時計アプリを作ろう」
では、数字と時刻を扱いました。

割り勘アプリやBMI計算などで、小数点の扱いもやることができたのはありがたかったです。
時計やストップウォッチを作る際には、時刻同士の加算減算を試せたので、今後何かに役立てそうだと思いました。

5章「ファイル操作アプリを作ろう」:正答コードに忠実に作ってクリア

5章「ファイル操作アプリを作ろう」
では、

  • テキストファイルの読み込み・編集・名前を付けて保存
  • 画像ファイルの読み込み・モノクロにして保存
  • QRコードの作成

などを行いました。
ライブラリのおかげで、ファイル保存用ウィンドウや入力されたファイル名の取得などがとても簡単にできたので驚きでした。

ただ、このあたりになってくると処理が長くなり、何度かエラーになって詰まるところがありました。
しかしこの本のありがたいところは、 正答となるコードの全文が載っている ことです。
最終手段として本のコードを全部書き写せば、動かすことができます。
これはとても安心できる要素でした。

5章の内容を1つのアプリにまとめて、以下画像のようなデスクトップアプリを作ることができました。

image.png

6章「ゲームアプリを作ろう」:正答コードとの対決

6章「ゲームアプリを作ろう」では、

  • おみくじ
  • じゃんけん
  • 足し算ゲーム(足し算の問題を自動で出し、回答してもらう)
  • 数当てゲーム(回答より大きい、回答より小さいのヒントを出しつつ、特定の数を当ててもらう)
  • 31ゲーム(相手の答えから+3以内の数字を交互に言っていき、31に達したら負け)

を作る方法が説明されていました。
しかしここまでこなした結果大体の書き方はわかってきたので、おみくじ、じゃんけん以降はゲームの要件だけ見て内容を勝手に作っていく方式でやってみました。これはこれで楽しかったです。
ただ31ゲームについては、必勝できる数の選択条件などで正答コードを参考にしたので、ほぼ正答コードと同じコードになりました。

以降で、本に載っているコードと自分で書いたコードを比較してみます。

足し算ゲーム

本に載っている正答(出題・判定処理のみ、一部省略)

def question():
    global playFlag, ans
    a = random.randint(0,100)
    b = random.randint(0,100)
    ans = a + b
    win["txt1"].update(f"問題:{a} + {b} = ?")
    playFlag= True

def anscheck():
    global playFlag
    if v["in1"].isdecimal() == False:
        win["txt2"].update("数字を入力してね。")
    else:
        mynum = int(v["in1"])
        if mynum == ans:
            win["txt2"].update("正解です。入力ボタンを押すと次の問題が出るよ。")
            playFlag = False
        else:
            win["txt2"].update(f"{mynum}じゃないよ")

question()
while True:
    e, v = win.read()
    if e == "btn":
        if playFlag == False:
            question()
        else:
            anscheck()
    if e == None:
        break
win.close()

対して自分で書いたコード。

def createFormula():
    global formulaAnswer
    num1 = random.randint(0,9)
    num2 = random.randint(0,9)
    formulaAnswer = int(num1 + num2)
    txt = f"{num1} + {num2} = ?"
    window["formulaText"].update(txt)

def answerFormula():
    if values['inFormulaAnswer'].isdecimal() == False:
        window["formulaResultText"].update("回答を入力してください。")

    else :
        inFormulaAnswer = int(values['inFormulaAnswer'])
        if formulaAnswer == inFormulaAnswer:
            # 成功した場合
            window["formulaResultText"].update("正解です。では次の問題です。")
            createFormula()
        else :
            window["formulaResultText"].update("不正解です。")

createFormula()
while True:
    event,values = window.read()
    if event == 'formulaAnswerButton':
        answerFormula()
    if event == None:
        break
window.close()
  • ボタンクリック時の動きが異なる。
    正答コード:状態により出題・判定を切り替えている
    自分が書いたコード:常に判定しかしておらず、出題は判定に続けて行っている。

数当てゲーム

本に載っている正答(出題・判定処理のみ、一部省略)

def question():
    global playFlag, ans, count
    ans = random.randint(1,100)
    count = 0
    win["txt1"].update("")
    playFlag = True

def anscheck():
    global playFlag, count
    if v["in1"].isdecimal() == False:
        win["txt1"].update("数字を入力してね。")
    else:
        count = count + 1
        mynum = int(v["in1"])
        if mynum == ans:
            win["txt1"].update(f"{count}回目:当たり!入力ボタンでまた遊べるよ")
            playFlag = False
        elif mynum < ans:
            win["txt1"].update(f"{count}回目:もっと大きいよ")
        else:
            win["txt1"].update(f"{count}回目:もっと小さいよ")

question()
while True:
    e, v = win.read()
    if e == "btn":
        if playFlag == False:
            question()
        else:
            anscheck()
    if e == None:
        break
win.close()

対して自分で書いたコード。

def createGuess():
    global guessAnswer
    guessAnswer = random.randint(0,10)

def answerGuess():
    global guessCount
    if values['inGuessAnswer'].isdecimal() == False:
        window["guessText"].update("回答を入力してください。")

    else :
        inGuessAnswer = int(values['inGuessAnswer'])
        guessCount = guessCount + 1
        if int(guessAnswer) == inGuessAnswer:
            # 成功した場合
            window["guessText"].update(f"{guessCount}回目で正解です。では次の問題です。")
            createGuess()
        elif int(guessAnswer) > inGuessAnswer:
            window["guessText"].update(f"{guessCount}回目、不正解です。回答より大きい数になります。")
        else :
            window["guessText"].update(f"{guessCount}回目、不正解です。回答より小さい数になります。")

createGuess()
while True:
    event,values = window.read()
    if event == 'guessAnswerButton':
        answerGuess()
    if event == None:
        break
window.close()

足し算ゲームと同様に、ボタンクリック時の動きが異なるという違いがあるが、他はほぼ同じ。

感想など

Pythonでのデスクトップアプリは、外部ライブラリのおかげかJavaでのデスクトップアプリ作成よりも簡単に作ることができました。
また本自体も読みやすかったので、Pythonを使って動くものを作りたい時に参考にするにはとても良い本だと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?