2
2

【Python】ttkbootstrapでGUIアプリ制作&改修

Last updated at Posted at 2024-03-20

GUIアプリの概要

以前投稿したアプリを改修したのでそれを共有したいと思います。
以前投稿したアプリは以下の記事になります。

ttkbootstarpのGoogle検索をしたら二番目にヒットします。
是非合わせてお読み下さい。

改良点

ソースコードをクラスで作成
QRコードの作成を自分で指定した場所に作成できるように改修
日記を書けるように改修

アプリ概要

QRコード

image.png

勤怠計算

image.png

日記

image.png

Tab Two

image.png

Windowsカラー変更

image.png

基本設計書

1. 概要

このプログラムは、Tkinterを使用してGUIアプリケーションを作成するためのサンプルです。主な機能としては、QRコードの生成、勤怠計算、日記の保存、日付とウィンドウの色の変更があります。
ttkbootstarapで使用できる機能をまとめて実装しています。

2. 機能要件

①QRコードの生成
②勤怠計算
③日記の保存
④日付の取得
⑤ウィンドウの色の変更

3. クラス構造

  • Application: GUIアプリケーションのメインクラス
    • qr_create(): QRコード生成タブの作成
    • attendance(): 勤怠計算タブの作成
    • Tab_one(): 日記タブの作成
    • Tab_Two(): タブ2の作成
    • Window_change(): ウィンドウの色変更タブの作成
    • main(): アプリケーションの実行を開始するメソッド

4. メソッド仕様

  • qr_create():
    • QRコード生成ボタンをクリックすると、入力されたURLからQRコードを生成し、保存する
  • attendance():
    • 勤怠計算ボタンをクリックすると、出勤時間、退勤時間、休憩時間から労働時間を計算する
  • Tab_one():
    • 保存ボタンをクリックすると、入力された日記をテキストファイルに保存する
  • Tab_Two():
    • 日付取得ボタンをクリックすると、選択された日付を表示する
  • Window_change():
    • テーマを変更すると、ウィンドウの外観が変更される

ソースコード

import tkinter as tk
from tkinter import filedialog
from ttkbootstrap import (
    Button,
    Label,
    Checkbutton,
    Combobox,
    DateEntry,
    Menu,
    Menubutton,
    Notebook,
    Frame,
    Window,
    Style,
    dialogs,
)
import qrcode
from datetime import datetime
from tkinter.filedialog import asksaveasfilename


class Application:
    def __init__(self, root):
        self.root = root
        self.root.title("Notebook")
        self.root.geometry("500x400")
        self.notebook = Notebook(root, bootstyle="light")
        self.notebook.pack(pady=20)
        self.my_date_label = Label()
        self.qr_create()
        self.attendance()
        self.Tab_one()
        self.Tab_Two()
        self.Window_change()

    def qr_create(self):
        def btn_click():
            S = self.Url_text.get()
            img = qrcode.make(S)
            path = asksaveasfilename(initialdir=dir)
            img.save(f"{path}.png")

        tab_qr = Frame(self.notebook)
        self.notebook.add(tab_qr, text="QRコード作成")

        self.Url_lbl = Label(tab_qr, text="URL")
        self.Url_lbl.place(x=70, y=100)

        self.Url_text = tk.Entry(tab_qr, width=30)
        self.Url_text.place(x=130, y=100)

        btn = Button(
            tab_qr, text="QRコード生成", bootstyle="success", command=btn_click
        )
        btn.place(x=180, y=150)

    def attendance(self):
        def btn_click():
            self.total_value.delete(0, tk.END)
            start = self.start_value.get()  # 出勤時間
            last = self.last_value.get()  # 退勤時間
            rest = self.rest_value.get()  # 休憩時間
            FMT = "%H:%M:%S"
            tdelta = datetime.strptime(last, FMT) - datetime.strptime(start, FMT)
            tdelta_cgange = str(tdelta)
            tdelta_1 = datetime.strptime(tdelta_cgange, FMT) - datetime.strptime(
                rest, FMT
            )
            self.total_value.insert(0, str(tdelta_1))

        def btn_clear():
            self.start_value.delete(0, tk.END)
            self.last_value.delete(0, tk.END)
            self.rest_value.delete(0, tk.END)
            self.total_value.delete(0, tk.END)

        def thing():
            cal = dialogs.Querybox()
            self.my_date_label = Label(
                tab_attendance,
                text=f"日付: {cal.get_date()}",
                bootstyle="inverse success",
            )
            self.my_date_label.place(x=5, y=10)

        tab_attendance = Frame(self.notebook)
        self.notebook.add(tab_attendance, text="勤怠計算")

        lbl_massage = Label(tab_attendance, text="勤務時間を入力して下さい。")
        lbl_massage.place(x=145, y=60)

        start_lbl = Label(tab_attendance, text="出勤時間")
        start_lbl.place(x=70, y=100)

        last_lbl = Label(tab_attendance, text="退勤時間")
        last_lbl.place(x=70, y=130)

        rest_lbl = Label(tab_attendance, text="休憩時間")
        rest_lbl.place(x=70, y=160)

        total_lbl = Label(tab_attendance, text="労働時間")
        total_lbl.place(x=70, y=190)

        self.start_value = tk.Entry(tab_attendance, width=30)
        self.start_value.place(x=145, y=100)

        self.last_value = tk.Entry(tab_attendance, width=30)
        self.last_value.place(x=145, y=130)

        self.rest_value = tk.Entry(tab_attendance, width=30)
        self.rest_value.place(x=145, y=160)

        self.total_value = tk.Entry(tab_attendance, width=30)
        self.total_value.place(x=145, y=190)

        btn = Button(
            tab_attendance, text="勤 怠 計 算", bootstyle="success", command=btn_click
        )
        btn.place(x=155, y=230)

        btn = Button(
            tab_attendance, text="ク リ ア", bootstyle="success", command=btn_clear
        )
        btn.place(x=155, y=270)

        btn = Button(
            tab_attendance, text="日 付 選 択", bootstyle="success", command=thing
        )
        btn.place(x=370, y=10)

    def Tab_one(self):
        def daiary():
            mb = dialogs.Messagebox.okcancel("ファイルを保存しますか?")
            if mb == "OK":
                s = self.my_text.get(0.0, tk.END)
                self.my_text.delete(0.0, tk.END)
                path = filedialog.asksaveasfilename(defaultextension=".txt")
                if not path:
                    return
                with open(path, "w", encoding="utf-8") as f:
                    f.write(s)

        tab1 = Frame(self.notebook)
        self.notebook.add(tab1, text="日記")

        my_label = Label(tab1, text="日記を書いてね!!", font=("Helvetica", 18))
        my_label.pack(pady=20)

        self.my_text = tk.Text(tab1, width=70, height=10)
        self.my_text.pack(pady=10, padx=10)

        my_button = Button(
            tab1, text="保存", bootstyle="danger outline", command=daiary
        )
        my_button.pack(pady=20)

    def Tab_Two(self):
        tab2 = Frame(self.notebook)
        self.notebook.add(tab2, text="Tab Two")

        days = [
            "Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday",
            "Sunday",
        ]
        my_combo = Combobox(tab2, bootstyle="success", values=days)
        my_combo.pack(pady=20)
        my_combo.current(0)

        def date_get():
            self.my_date_label = Label(
                tab2, text=f"日付取得: {self.my_date.entry.get()}"
            )
            self.my_date_label.pack(pady=10)

        self.my_date = DateEntry(tab2, firstweekday=0, bootstyle="success")
        self.my_date.pack(pady=20)

        my_date_button = Button(
            tab2, text="日付取得", bootstyle="success", command=date_get
        )
        my_date_button.pack(pady=10)

    def Window_change(self):
        tab3 = Frame(self.notebook)
        self.notebook.add(tab3, text="Windowカラー変更")

        val2 = tk.IntVar()
        my_check = Checkbutton(
            tab3,
            bootstyle="success, round-toggle",
            text="OK?",
            variable=val2,
            onvalue=1,
            offvalue=0,
        )
        my_check.pack(pady=20)

        val3 = tk.IntVar()
        my_check = Checkbutton(
            tab3,
            bootstyle="warning, square-toggle",
            text="No?",
            variable=val3,
            onvalue=1,
            offvalue=0,
        )
        my_check.pack(pady=10)

        # メニューラベル(Tab Three)
        def stuff(x):
            self.my_menu_label.config(
                text=f"あなたが選んだ言語は:{x}", bootstyle="inverse success"
            )

        self.my_menu_label = Label(tab3, text="あなたが選んだ言語は:")
        self.my_menu_label.place(x=25, y=20)

        self.my_menu = Menubutton(tab3, bootstyle="success", text="メニュー")
        self.my_menu.pack(pady=20)

        inside_menu = Menu(self.my_menu)
        item_ver = tk.StringVar()

        for x in ["python", "java", "C", "PHP", "Ruby", "JavaScript", "C++"]:
            inside_menu.add_radiobutton(
                label=x, variable=item_ver, command=lambda x=x: stuff(x)
            )
        self.my_menu["menu"] = inside_menu

        # テーマを変更する関数
        def change_theme(event):
            global style
            theme = combo_var.get()
            style = Style(theme=theme)

        # テーマコンボボックスを作成
        themes = [
            "cosmo",
            "flatly",
            "journal",
            "litera",
            "lumen",
            "minty",
            "pulse",
            "sandstone",
            "united",
            "yeti",
            "morph",
            "simplex",
            "cerculean",
            "solar",
            "superhero",
            "darkly",
            "cyborg",
            "vapor",
        ]

        combo_var = tk.StringVar()  # コンボボックスにデータをセットする。
        combo = Combobox(tab3, values=themes, textvariable=combo_var)
        combo.set("Windowの色を選択")
        combo.place(x=310, y=10)
        combo.bind(
            "<<ComboboxSelected>>", change_theme
        )  # コンボボックスの選択イベントにchange_theme関数をバインド

    def main(self):
        self.root.mainloop()


if __name__ == "__main__":
    root = Window(themename="darkly")
    app = Application(root)
    app.main()

2
2
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
2