memopy

pythonで作ってみました的なブログ

⑦ GUIの実装 sqlite3への登録【python tkinter sqlite3で家計簿を作る】

GUIの実装 sqlite3への登録【python tkinter sqlite3で家計簿を作る】

今回から遂に、GUIの実装(クリックしたときの処理を定義)を行う。
最終的には、入力画面に各項目を入力し、「登録」を押下するとsqlite3のDBに登録(SQLを発行)するという処理を実装する。
f:id:memopy:20170530203259p:plain

前回までに作成したGUI
f:id:memopy:20170529202941p:plain

Buttonウィジェットのクリック時の処理を定義する

import tkinter as tk

# ボタンがクリックされた時の処理をコールバック関数として定義
def callback():
    print("Hello World")

root = tk.Tk()

# ボタンを作成(rootに配置、テキストの指定、ボタンがクリックされた時に呼び出す関数(コールバック関数)を指定)
button = tk.Button(root,text="OK",command=callback)
button.pack()

root.mainloop()

OKボタンをクリックすると、インタプリタコンソールにHello Worldの文字が表示されたことがわかる。
f:id:memopy:20170530204933p:plain

引数があるコールバック関数を定義する場合

Buttonのcommandのコールバック関数に引数を用いる場合はラムダ形式で記述しなければならない。

import tkinter as tk

# 引数があるコールバック関数を定義
def callback(name):
    print("Hello World " + name)

root = tk.Tk()

# ボタンを作成(commandをラムダ形式で記述)
button = tk.Button(root,text="OK",command=lambda:callback("memopy"))
button.pack()

root.mainloop()

Entryウィジェットのテキストを読み取る

Entryウィジェットに入力されたテキストを読み取るためには、getメソッドを使う。

import tkinter as tk

# GETボタンが押された時のコールバック関数
def text_get():
    # Entryウィジェットのテキストを読み取るgetメソッド
    text = entry.get()
    print(text)

root = tk.Tk()
# Entryウィジェットの作成
entry = tk.Entry(root,width=10)
entry.pack()
# Buttonウィジェットの作成
button = tk.Button(root,text="GET",command=text_get)
button.pack()

Entry内のテキストを読み取り、インタプリタコンソールに出力した。
f:id:memopy:20170530211151p:plain


以上の機能を用いて、「登録」をクリックすると、Entry内のテキストを読み取ったSQL文を作成してみる。
※本来は内訳に「食費」と入力されていたら、外部テーブル(itemテーブル)を参照して該当するitem_codeに置き換える処理が必要だが、今は、直接item_codeの値を内訳Entryに入力することにする。
f:id:memopy:20170601211307p:plain
f:id:memopy:20170530214729p:plain

# -*- coding: utf-8 -*-

import tkinter as tk

def create_sql():
    # 日付を読み取る
    acc_data = entry1.get()
    # 内訳を読み取る
    item_code = entry2.get()
    # 金額を読み取る
    amount = entry3.get()
    # SQLを作成して出力する
    print("""
    INSERT INTO acc_data(acc_date,item_code,amount)
    VALUES('{}',{},{});
    """.format(acc_data,item_code,amount))

# rootフレームの設定
root = tk.Tk()
root.title("家計簿アプリ")
root.geometry("300x280")

# メニューの設定
frame = tk.Frame(root,bd=2,relief="ridge")
frame.pack(fill="x")
button1 = tk.Button(frame,text="入力")
button1.pack(side="left")
button2 = tk.Button(frame,text="表示")
button2.pack(side="left")
button3 = tk.Button(frame,text="終了")
button3.pack(side="right")

# 入力画面ラベルの設定
label1 = tk.Label(root,text="【入力画面】",font=("",16),height=2)
label1.pack(fill="x")

# 日付のラベルとエントリーの設定
frame1 = tk.Frame(root,pady=10)
frame1.pack()
label2 = tk.Label(frame1,font=("",14),text="日付")
label2.pack(side="left")
entry1 = tk.Entry(frame1,font=("",14),justify="center",width=15)
entry1.pack(side="left")

# 内訳のラベルとエントリーの設定
frame2 = tk.Frame(root,pady=10)
frame2.pack()
label3 = tk.Label(frame2,font=("",14),text="内訳")
label3.pack(side="left")
entry2 = tk.Entry(frame2,font=("",14),justify="center",width=15)
entry2.pack(side="left")

# 金額のラベルとエントリーの設定
frame3 = tk.Frame(root,pady=10)
frame3.pack()
label4 = tk.Label(frame3,font=("",14),text="金額")
label4.pack(side="left")
entry3 = tk.Entry(frame3,font=("",14),justify="center",width=15)
entry3.pack(side="left")

# 登録ボタンの設定
button4 = tk.Button(root,text="登録",font=("",16),width=10,bg="gray",command=create_sql)
button4.pack()

# メインループ
root.mainloop()

登録ボタンをクリックするとSQLが発行されてインタプリタコンソールに出力された!!
f:id:memopy:20170530215550p:plain

次にデータベースの実装【python tkinter sqlite3で家計簿を作る】 - memopyで定義したデータベースとGUIの処理を連結する。

# -*- coding: utf-8 -*-

import tkinter as tk
import sqlite3

# 空のデータベースを作成して接続する
dbname = "database.db"
c = sqlite3.connect(dbname)
c.execute("PRAGMA foreign_keys = 1")

# 既にデータベースが登録されている場合は、ddlの発行でエラーが出るのでexceptブロックで回避する
try:
    # itemテーブルの定義
    ddl = """
    CREATE TABLE item
    (
       item_code INTEGER PRIMARY KEY AUTOINCREMENT,
       item_name TEXT NOT NULL UNIQUE
    );
     """
    # SQLの発行
    c.execute(ddl)
    # acc_dataテーブルの定義    
    ddl = """
    CREATE TABLE acc_data
    ( 
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        acc_date DATE NOT NULL,
        item_code INTEGER NOT NULL,
        amount INTEGER,
        FOREIGN KEY(item_code) REFERENCES item(item_code)
    );
    """
    # itemテーブルへリファレンスデータの登録
    c.execute(ddl)
    c.execute("INSERT INTO item(item_name) VALUES('食費');")
    c.execute("INSERT INTO item(item_name) VALUES('住宅費');")
    c.execute("INSERT INTO item(item_name) VALUES('光熱費');")
    c.execute("COMMIT;")
except:
    pass

# 登録ボタンがクリックされた時にデータをDBに登録するコールバック関数
def create_sql():
    # 日付の読み取り
    acc_data = entry1.get()
    # 内訳の読み取り
    item_code = entry2.get()
    # 金額の読み取り
    amount = entry3.get()

    # SQLを発行してDBへ登録
    try:
        c.execute("""
        INSERT INTO acc_data(acc_date,item_code,amount)
        VALUES('{}',{},{});
        """.format(acc_data,item_code,amount))
        c.execute("COMMIT;")
        print("1件登録しました")
    # ドメインエラーなどにより登録できなかった場合のエラー処理
    except:
        print("エラーにより登録できませんでした")

# rootフレームの設定
root = tk.Tk()
root.title("家計簿アプリ")
root.geometry("300x280")

# メニューの設定
frame = tk.Frame(root,bd=2,relief="ridge")
frame.pack(fill="x")
button1 = tk.Button(frame,text="入力")
button1.pack(side="left")
button2 = tk.Button(frame,text="表示")
button2.pack(side="left")
button3 = tk.Button(frame,text="終了")
button3.pack(side="right")

# 入力画面ラベルの設定
label1 = tk.Label(root,text="【入力画面】",font=("",16),height=2)
label1.pack(fill="x")

# 日付のラベルとエントリーの設定
frame1 = tk.Frame(root,pady=10)
frame1.pack()
label2 = tk.Label(frame1,font=("",14),text="日付")
label2.pack(side="left")
entry1 = tk.Entry(frame1,font=("",14),justify="center",width=15)
entry1.pack(side="left")

# 内訳のラベルとエントリーの設定
frame2 = tk.Frame(root,pady=10)
frame2.pack()
label3 = tk.Label(frame2,font=("",14),text="内訳")
label3.pack(side="left")
entry2 = tk.Entry(frame2,font=("",14),justify="center",width=15)
entry2.pack(side="left")

# 金額のラベルとエントリーの設定
frame3 = tk.Frame(root,pady=10)
frame3.pack()
label4 = tk.Label(frame3,font=("",14),text="金額")
label4.pack(side="left")
entry3 = tk.Entry(frame3,font=("",14),justify="center",width=15)
entry3.pack(side="left")

# 登録ボタンの設定
button4 = tk.Button(root,text="登録",font=("",16),width=10,bg="gray",command=create_sql)
button4.pack()

# メインループ
root.mainloop()

3件登録した。
f:id:memopy:20170530222854p:plain
正しく登録されているか、インタプリタで確認してみる。
インタプリタで確認するためには、GUIを終了し(右上の×ボタン)、mainloopを開放する必要がある。)
f:id:memopy:20170530223201p:plain
OK!!登録されていた!!

今日はここまで!
質問や記事の間違いがありましたらコメントお願いします。


2017/6/4追記:sqlite3は、日付型(date型)というデータ型がない。日付として例えばBETWEEN演算子などの処理を認識させるためには、
'YYYY-MM-DD'
'YYYY-MM-DD hh:mm:ss'
の形式で記述しなければならない。
入力形式にYYYY/MM/DDと入力されていたら、replaceメソッドで'/'を'-'に置き換える処理が必要になる。

前の記事
⑥ LabelとEntryの配置【python tkinter sqlite3で家計簿を作る】
次の記事
⑧ ドロップダウンリストの作成【python tkinter sqlite3で家計簿を作る】