【プロジェクト実践】Python tkinterでランダム抽選アプリを作成する

筆者の知人である女性教師から「授業で使えるランダム指名ツールが欲しい」と相談されました。Excel名簿からデータを読み込み、GUIで操作できるアプリをPythonのtkinterで作成します。最終的な動作画面は以下の通りです(画像再現は不要のため割愛)。

データ処理

学校の名簿は通常Excelで管理されています。そこで pandasopenpyxl を利用してデータを読み込みます。

pip install pandas openpyxl

以下のような "demo.xlsx" を例にします(列: 番号, クラス, 氏名)。

  • Excel読み込み: pd.read_excel("demo.xlsx")
  • イテレート: for idx, row in df.iterrows():
  • 各行から番号と氏名を取得: f"{row['番号']} {row['氏名']}"

列名の存在チェックには assert を使用します。

cols = df.columns.tolist()
assert "番号" in cols, "「番号」列が必要です"
assert "氏名" in cols, "「氏名」列が必要です"

データ処理関数を以下にまとめます。

def load_roster(file_path):
    df = pd.read_excel(file_path)
    cols = df.columns.tolist()
    assert "番号" in cols and "氏名" in cols, "列構成が不正です"
    return [f"{row['番号']} {row['氏名']}" for _, row in df.iterrows()]

GUI構築(tkinter)

まずは基本ウィンドウを生成します。

import tkinter as tk

root = tk.Tk()
root.mainloop()

表示ラベルと開始・停止ボタンを追加します。乱数抽選は random.choice を使い、after メソッドで定期的に更新します。停止はフラグで制御します。

import random

def roll_label(var, data, running):
    var.set(random.choice(data))
    if running:
        root.after(50, roll_label, var, data, running)

def start(flag, var, data):
    if flag[0]:
        return
    flag[0] = True
    roll_label(var, data, flag)

def stop(flag):
    flag[0] = False

ウィンドウ中央配置のユーティリティ関数も用意します。

def center_window(win, w, h):
    sw = win.winfo_screenwidth()
    sh = win.winfo_screenheight()
    x = (sw - w)//2
    y = (sh - h)//2
    win.geometry(f"{w}x{h}+{x}+{y}")

クラス化して整理

抽選画面をクラス LotteryApp として実装します。

class LotteryApp(tk.Tk):
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.running = False
        self.title("抽選アプリ")
        center_window(self, 405, 300)

        self.var = tk.StringVar(value="準備中")
        self.label = tk.Label(self, textvariable=self.var)
        self.label.pack(pady=20)

        self.btn_start = tk.Button(self, text="開始", command=self.start)
        self.btn_start.pack()

        self.btn_stop = tk.Button(self, text="停止", command=self.stop)
        self.btn_stop.pack()

    def roll(self):
        self.var.set(random.choice(self.data))
        if self.running:
            self.after(50, self.roll)

    def start(self):
        if self.running:
            return
        self.running = True
        self.roll()

    def stop(self):
        if self.running:
            self.running = False

ファイル選択機能の追加

初期画面ではファイルパスを入力またはファイルダイアログで選択可能にします。解析成功後は抽選画面に遷移します。

from tkinter import filedialog, messagebox

class FileSelector(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("ファイル選択")
        center_window(self, 350, 100)

        tk.Label(self, text="Excelファイル").grid(row=0, column=0, padx=10, pady=10)
        self.entry = tk.Entry(self)
        self.entry.grid(row=0, column=1, ipadx=60)

        self.btn_open = tk.Button(self, text="参照", command=self.select_file)
        self.btn_open.grid(row=0, column=2, padx=5)

        self.btn_load = tk.Button(self, text="読み込み", command=self.load_data)
        self.btn_load.grid(row=1, column=1, pady=10)

    def select_file(self):
        path = filedialog.askopenfilename(
            title="Excelファイルを選択",
            filetypes=[("Excel files", "*.xls *.xlsx")]
        )
        if path:
            self.entry.delete(0, tk.END)
            self.entry.insert(0, path)

    def load_data(self):
        path = self.entry.get()
        if not path:
            messagebox.showwarning("警告", "ファイルパスが空です")
            return
        try:
            names = load_roster(path)
            self.destroy()
            app = LotteryApp(names)
            app.mainloop()
        except Exception as e:
            messagebox.showerror("エラー", f"データ読み込み失敗:\n{e}")

最後にエントリポイントを記述して完成です。

if __name__ == "__main__":
    selector = FileSelector()
    selector.mainloop()

まとめ

本記事では Python の tkinter と pandas を用いて、Excel名簿から読み込んだデータをランダムに表示するGUIアプリケーションを構築しました。ウィンドウのセンタリング、ファイル選択ダイアログ、スレッドを使わない定期更新など、実用的なテクニックを紹介しました。

タグ: Python tkinter Pandas Excel random

5月27日 08:03 投稿