4
3

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で作成!令和6年度共通テストのn進数タイマー

Last updated at Posted at 2024-09-19

はじめに

Screenshot 2024-09-19 at 15-30-27 - 2024_or_19_sugaku1A.pdf.png
 今回の記事では、Pythonを使って令和6年度共通テストのn進数タイマーを、デザインにも凝って要件定義、仕様策定、実装の3つに分けて解説します!これを実装するにあたり、@Tadataka_Takahashi様のPythonで作るポップなポモドーロタイマーを一部参考にして実装しました!

1.要件定義

 まず、n進数タイマーについて基本的な要件を定義します。

1.1機能要件

 1.タイマーを3つ用意する。
 2.スタートした時点では000と表示する。
 3.タイマーがスタートした後、表示される数が1秒ごとに1ずつ増やす。
 4.3桁で表示できる最大の数が表示された1秒後に、表示が000に戻る。
 5.タイマーの表示が000に戻った後も、3~4を繰り返す。
 6.タイマーの開始、停止、リセット、設定機能。

1.2非機能要件

 1.ユーザーフレンドリーなインターフェース
 2.視覚的にわかりやすいデザイン
 3.操作が直感的で簡単であること
 4.プログラムの安定性と信頼性

2.仕様策定

 要件に基づき、具体的な仕様を決定します。

2.1タイマー仕様

 ・タイマーは1秒ごとにカウントアップ
 ・設定で決めた進数に応じて繰り上げ

2.2タイマーのUI仕様

スクリーンショット 2024-09-19 160250.png
 ・ウィンドウサイズ:1000x400

 ・表示要素:
  ◦タイトル
  ◦3つのタイマー
  ◦現在の時間

 ・操作要素:
  ◦開始
  ◦停止
  ◦リセット
  ◦設定

2.3設定仕様

 ・タイマーの進数を設定
 ・決定で変更

2.4設定UI仕様

スクリーンショット 2024-09-19 163109.png
 ・ウィンドウサイズ:450x300

 ・表示要素:
  ◦タイトル
  ◦3つのタイマーの進数の設定ラベル

 ・操作要素:
  ◦3つのタイマーの進数の設定テーブル
  ◦決定

2.5デザイン仕様

 ・カラーパレット
  ◦背景色:寒色(#87cefa)
  ◦メインカラー:鮮明な色(#4169e1)
  ◦アクセントカラー:補色となるような色(#ff7f50)
 ・フォント: 読みやすいサンセリフフォント(例:Helvetica)

3.実装

 仕様に基づき、Pythonコードを実装します。以下は実装例です。

main.py
import tkinter as tk
from tkinter import ttk, messagebox

class CountUpTimer:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("n進数タイマー")
        self.window.config(padx=20, pady=20, bg="#87cefa")
        self.window.geometry("1000x400")

        self.bases = [10, 10, 10]  # デフォルトの進数(左から 10 10 10進数)
        self.timers_running = False  # タイマーのスタート初期値化
        self.timer_values = [0, 0, 0]  # タイマーの値の初期値化
        self.timer_labels = []
        self.setup_ui()

    def setup_ui(self):
        # フォントとカラーの設定
        TITLE_FONT = ("Helvetica", 28, "bold")
        TIMER_FONT = ("Helvetica", 64, "bold")
        BUTTON_FONT = ("Helvetica", 14, "bold")
        MAIN_COLOR = "#4169e1"
        SECONDARY_COLOR = "#7fffd4"
        ACCENT_COLOR = "#ff7f50"
        
        self.title_label = tk.Label(text="n進数タイマー", fg=MAIN_COLOR, bg="#87cefa", font=TITLE_FONT)
        self.title_label.pack()

        # タイマーフレームのコンテナ
        self.timer_frame_container = tk.Frame(self.window, bg="#87cefa")
        self.timer_frame_container.pack(pady=20)

        # タイマーフレームとラベル
        for i in range(3):
            frame = tk.Frame(self.timer_frame_container, bg="#0000cd", bd=2, relief="raised")
            frame.pack(side=tk.LEFT, padx=10)
            label = tk.Label(frame, text="000", fg=MAIN_COLOR, bg="#0000cd", font=TIMER_FONT, width=5)  # Fixed width
            label.pack(pady=20)
            self.timer_labels.append(label)

        # ボタン群のフレーム
        self.button_frame = tk.Frame(self.window, bg="#87cefa")
        self.button_frame.pack(pady=20)

        # ボタンたち
        self.start_button = tk.Button(self.button_frame, text="開始", padx=30, pady=10, command=self.start_timers, font=BUTTON_FONT, bg=SECONDARY_COLOR, width=10)
        self.start_button.pack(side=tk.LEFT, padx=5)

        self.stop_button = tk.Button(self.button_frame, text="停止", padx=30, pady=10, command=self.stop_timers, font=BUTTON_FONT, bg=SECONDARY_COLOR, width=10)
        self.stop_button.pack(side=tk.LEFT, padx=5)

        self.reset_button = tk.Button(self.button_frame, text="リセット", padx=30, pady=10, command=self.reset_timers, font=BUTTON_FONT, bg=SECONDARY_COLOR, width=10)
        self.reset_button.pack(side=tk.LEFT, padx=5)

        self.option_button = tk.Button(self.button_frame, text="設定", padx=30, pady=10, command=self.option_setup, font=BUTTON_FONT, bg=ACCENT_COLOR, width=10)
        self.option_button.pack(side=tk.LEFT, padx=5)

    def start_timers(self):
        if not self.timers_running:
            self.timers_running = True
            self.update_timers()

    def stop_timers(self):
        self.timers_running = False

    def reset_timers(self):
        self.timers_running = False
        self.timer_values = [0, 0, 0]
        self.update_timer_labels()

    def update_timers(self):
        if self.timers_running:
            for i in range(3):
                self.timer_values[i] += 1
                # 進数に基づいた繰り上げ
                if self.timer_values[i] >= self.bases[i] ** 3:
                    self.timer_values[i] = 0
            self.update_timer_labels()
            self.window.after(1000, self.update_timers)  # カウントアップ

    def update_timer_labels(self):
        for i, label in enumerate(self.timer_labels):
            value = self.timer_values[i]
            label.config(text=self.convert_to_base(value, self.bases[i]))

    def convert_to_base(self, value, base):
        chars = "0123456789ABCDEF"
        result = ""
        for _ in range(3):
            result = chars[value % base] + result
            value //= base
        return result.zfill(3)

    def option_setup(self):
        # 新しいウィンドウの作成
        settings_window = tk.Toplevel(self.window)
        settings_window.title("設定")
        settings_window.config(bg="#87cefa")
        settings_window.geometry("450x300")

        LABEL_FONT = ("Helvetica", 18)
        BUTTON_FONT = ("Helvetica", 14, "bold")
        ACCENT_COLOR = "#ff7f50"

        label = tk.Label(settings_window, text="各タイマーの進数を設定してください。", font=LABEL_FONT, bg="#87cefa")
        label.grid(row=0, column=0, columnspan=3, pady=10)

        base_selectors = []
        for i in range(3):
            timer_label = tk.Label(settings_window, text=f"タイマー {i+1} の進数: ", font=LABEL_FONT, bg="#87cefa")
            timer_label.grid(row=i + 1, column=0, padx=10, pady=10)

            base_options = [str(n) for n in range(2, 17)]  # Options from base 2 to 16
            base_selector = ttk.Combobox(settings_window, values=base_options, font=("Helvetica", 14), width=5)
            base_selector.set(str(self.bases[i]))  # Set default value
            base_selector.grid(row=i + 1, column=1, padx=10, pady=10)
            base_selectors.append(base_selector)

        apply_button = tk.Button(settings_window, text="決定", command=lambda: self.apply_settings(base_selectors, settings_window), font=BUTTON_FONT, bg=ACCENT_COLOR)
        apply_button.grid(row=4, column=0, columnspan=3, pady=20)

    def apply_settings(self, selectors, window):
        try:
            for i, selector in enumerate(selectors):
                base = int(selector.get())
                if base < 2 or base > 16:
                    raise ValueError
                self.bases[i] = base
            window.destroy()
        except ValueError:
            messagebox.showerror("入力エラー", "2から16の間の数値を入力してください。")

    def run(self):
        self.window.mainloop()

if __name__ == "__main__":
    timer = CountUpTimer()
    timer.run()

4.実装のポイント

 n進数タイマーの実装について、以下のポイントに注意しました。

4.1クラスベースの設計

 CountUpTimerクラスを中心に、アプリケーションの全機能をまとめ、再利用性と保守性を向上させた。

4.2UIデザインの考慮

 色やフォントを適切に選択し、視覚的に魅力的なインターフェースを作成した。また、ボタンのサイズや配置を工夫し、使いやすさを向上させた。

4.3無効な入力の防止

 無効な進数入力に対するエラーハンドリングを行い、プログラムの安全性を向上させた。

4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?