0
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?

【初心者向け】PythonでGUIアプリケーションを作成する

Last updated at Posted at 2024-11-25

はじめに

PythonのGUIライブラリの Tkinter を使用して、じゃんけんゲームを作成しました。
「Python じゃんけん」と検索すると、基礎から応用まで多くの解説記事を見つけることができます。

しかしながら、その記事の多くはCLIベースのアプリケーションであり、GUIをどのように作りこむかまで解説している記事はあまり多くないことが分かりました。
そこで今回は、じゃんけんのGUIアプリケーションを作成し、記事へまとめることにしました。

筆者はPython初心者で、今回が初めてのアプリケーションの開発経験でした。
今回学んだことを整理する意味合いも込めて、GUIアプリケーションの作成手順や、苦戦した部分についてまとめています。
この記事を読んでいる皆さんにとって参考になれば幸いです。

この記事で分かること
・Tkinterの基本操作
・Python初心者(筆者)がじゃんけんゲームを作成して
 つまづいたポイントとその解決策

使用環境:Windows11, Python3.12.4
前提:アプリケーションはローカルで動かす

じゃんけんアプリ

使用モジュール、ライブラリについて

random:
疑似乱数を生成するモジュールです。今回はCPU側のじゃんけんの手を決める際に使用しました。
Tkinter:
PythonのGUIライブラリの一つです。 Pythonに標準で入っているライブラリのため、新たにインストールする必要がありません。シンプルな文法かつ学習コストが低い点から、今回のアプリケーション作成に適していると考えました。
PIL(Pillow):
画像ファイルの読み込みや修正といった画像処理を行うPythonライブラリです。

   Image: 画像の読み込みや保存、加工を行います。
  ImageTk: ImageオブジェクトをTkinterが理解できるオブジェクトに変更し、
        画面に表示します。

PILは標準ライブラリではないので、別途インストールが必要です。

pip install Pillow

Tkinterでウィンドウを作成

まずはアプリを動かすウィンドウを表示させます。
必要なモジュールをインポートし、以下のようなコードを書きます。

import tkinter as tk 
import random as rd
from PIL import Image, ImageTk
# ウィンドウの表示
root = tk.Tk()
root.geometry("500x500")
root.title("じゃんけんゲーム")
root.resizable(0,0)
...
# この間にプログラムが入ります
...
# ウィンドウのループ処理
root.mainloop()
.geometry("<横幅>×<高さ>"):
ウィンドウの大きさをピクセルで指定します。
.title("アプリケーション名"):
アプリケーションのタイトルを表示します。
.resizable(x,y):
xy方向にウィンドウの拡大が可能かを設定します。(0=不可, 1=可)
.mainloop():
アプリケーションの待機とイベントの処理を行います。ユーザーがクリックや入力などのアクション(イベント)を起こすまで、アプリケーションはウィンドウを開いたままにする必要があります。そこで、mainloopメソッド内の処理をループし続けることでウィンドウを表示させています。

ウィンドウを表示させることができました。
ここからじゃんけんに必要な画像やボタンを追加します。


ウィジェットの表示

ボタンや画像、テキストフィールドなどの画面上のパーツをウィジェットと呼びます。
作成したウィンドウにウィジェットを配置するために、以下のコードを書きます。

# グーボタン作成
buttonR = tk.Button(root, text="グー")
buttonR.place(x=80, y=300)


# グー画像の挿入
imageR = Image.open('imgs/gu.png')
imageR = ImageTk.PhotoImage(imageR)
tk.Label(root, image=imageR).place(x=0, y=230)


# テキストの挿入
text_labal = tk.Label(root, text='最初はグー! じゃんけん!', font = ("Arial", 18, "bold"), anchor="center")
text_labal.place(x=120, y=200)
tk.Label(親要素, テキストなどのオプション):
テキストや画像などのウィジェットを表示させます。
.place(x,y):
作成したウィジェットを特定の位置(x,y座標)に配置します。

じゃんけんに必要なウィジェットを追加していくと、以下のように見た目になります。

Tkinter(8.6~)はPNGに対応しています。
しかし標準ではJPEGに対応できないため、JPEGファイルを使用するにはPILのインストールが必要になります。

今回は画像処理や加工のためにPILをインストールしているので、JPEGファイルでも対応可能です。

JPEG画像を使用したい方はこちらの記事が参考になります。


じゃんけん勝敗の定義

じゃんけんの手の出し方は全部で9通りなので、その勝敗を辞書型で配列に格納します。
この定義をもとに勝敗判定を行います。

hands = [グー, チョキ, パー]
win, draw, lose = '勝ち', 'あいこ', '負け'
Rules = {
    (0,0): draw, (0,1): win, (0,2): lose,
    (1,0): lose, (1,1): draw, (1,2): win,
    (2,0): win, (2,1): lose, (2,2): draw
}

勝敗の表示

random関数を使用することで、相手のじゃんけんの手をランダムに決めています。
Rulesを参照してプレイヤーとCPUの手に対応する勝敗を判定し、それに対応したテキストと画像を表示します。

images = [imageR, imageS, imageP]

def judge(player):
    cpu = random.randint(0,2)

    result = Rules[(player, cpu)]

    CPUimage.configure(image=images[cpu])

    if result == draw:
        text_labal.configure(text= 'あいこでしょ!', fg = "purple",)
                             
    elif result == win:
        text_labal.configure(text= '勝ち!', fg = "red",)
        showRetry()

    else:
        text_labal.configure(text= '負け!', fg = "blue",)
        showRetry()

つまづいた点

①じゃんけんの手の素材を変更すると、画像サイズとレイアウトが大幅にくずれた


使用するじゃんけんの手の画像を変更したところ、上のように画像が大きく表示され、レイアウトがくずれてしまいました。コード内で画像サイズは調整していたのですが、調べてみたところそのサイズ調整に使用した関数が原因であると分かりました。

原因:subsample関数を用いてサイズ調整をしたから
subsample(n) は引数に指定した整数倍分、解像度を縮小して画像サイズを変更する関数です。よって使用するファイルの元のサイズによって変更後の画像サイズは異なって見えます。

解決策:resize関数を用いてピクセル単位で画像サイズを指定する
resize((横幅,高さ)) と指定することで、ウィンドウやウィジェットの大きさに合わせた細かい調整ができました。 使用する画像ファイルをすべて決まった比率で縮小したいときなどは、subsample関数が役立つと思います。

# 変更前
imageR = tk.PhotoImage(file = "imgs/gu.png").subsample(7)
tk.Label(root, image=imageR).place(x=20, y=250)


# 変更後
imageR = Image.open('imgs/gu.png').resize((140,140))
imageR = ImageTk.PhotoImage(imageR)
tk.Label(root, image=imageR).place(x=20, y=250)

(左)subsample(右)resizeを用いた画像サイズの調整


両者を比較すると、どちらも同程度の画像サイズで表示されていますが、その画質に差があることが分かります。subsample関数は、画像の解像度を縮小して新たなオブジェクトを生成する関数なので、もとの画像サイズより極端に小さくすると画質の粗さが目立ってしまうかもしれません。


②勝敗が決まった後でも他の手のボタンが機能し、後出しが可能になってしまう


解決策:勝敗が付いたら手のボタンが機能しないようにする
じゃんけんで後出しができてしまうとゲームとして成り立ちませんね。勝ちか負けになったらリトライボタンを表示し、手のボタンは押すことができなくなるよう設定します。

retryButton = tk.Button(root, text='リトライ', command=retry)

def showRetry():
    retryButton.place(x= 220, y=150)
    buttonR['state'] = 'disabled'
    buttonS['state'] = 'disabled'
    buttonP['state'] = 'disabled'

retryボタンが押された際に、無効になったボタンをもとに戻します。

def retry():
    retryButton.place_forget()
    buttonR['state'] = 'active'
    buttonS['state'] = 'active'
    buttonP['state'] = 'active'
    text_labal.configure(text='最初はグー! じゃんけん!')

まとめ

今回はPythonでGUIアプリケーションを作成しました。
一つずつ基本知識を学びながら作成をしたので、個人的には苦戦した部分が多くありました。やはり解説記事や動画を見るだけでなく、実際に手を動かすことでPythonに関する知識や理解を深めることができたと感じます。

Pythonを勉強してみたいという方は、ぜひ今回の記事を参考にしてアプリケーション作成に挑戦してみてください。

0
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
0
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?