########################################## # ToDoアプリGUI_ver2.6.py # 2024/09/15 # -Treeviewの行(レコード)を2色に設定 # --view_todos関数とview_search_todos関数に # 「tree.tag_configure())」追加 # 「tree.insert()」に 「tags」を追加定義 ########################################## ########################################## # ライブラリをインポート --- (1) ########################################## import os import csv import sqlite3 import tkinter as tk from tkinter import ttk from tkinter import messagebox from tkinter import filedialog #from pandas import DataFrame ######################################### # 変数等を宣言 --- (2) ######################################### db_path = "ToDo.sqlite3" #csv_imp_path = "users.csv" csv_exp_path = "exported_users.csv" ######################################### # 関数を宣言 --- (3) ######################################### # 関数(データベースの初期化) def load_todos(): if not os.path.exists(db_path): with sqlite3.connect(db_path) as conn: cur = conn.cursor() query = '''create table myItem( id integer primary key autoincrement, ToDo string, date string )''' cur.execute(query) # 関数(データのインポート) def import_todos(): conn = sqlite3.connect(db_path) cur = conn.cursor() #ファイルダイアログからインポート fTyp = [("","*")] iDir = os.path.abspath(os.path.dirname(__file__)) csv_imp_path = tk.filedialog.askopenfilename(filetypes = fTyp,initialdir = iDir) with open(csv_imp_path, 'r') as f: reader = csv.reader(f) query = '''insert into myItem( ToDo, date ) values(?,?)''' for row in reader: cur.execute(query, ( row[1], row[2])) conn.commit() conn.close() # 関数(データのエクスポート) def export_todos(): conn = sqlite3.connect(db_path) cur = conn.cursor() # if not os.path.exists(csv_exp_path): with open(csv_exp_path, 'w') as f: writer = csv.writer(f) for row in cur.execute('SELECT * FROM myItem'): writer.writerow(row) conn.close() # 関数(データベースからToDoデータ全件取得) def get_todos(): with sqlite3.connect(db_path) as conn: cur = conn.cursor() cur.execute('select * from myItem') rows = cur.fetchall() return rows # 関数(リストボックスにToDoデータ全件表示) def view_todos(tree): #テキストボックスクリア id_text.delete(0, tk.END) ToDo_text.delete(0, tk.END) date_text.delete(0, tk.END) tree.delete(*tree.get_children()) i=0 for row in get_todos(): tree.insert(parent='', index='end', tags=i, iid=row ,values=(str(row[0]), str(row[1]) ,str(row[2]))) if i % 2 == 0: # tagが偶数(レコードは奇数)の場合のみ、背景色の設定 tree.tag_configure(i,background="#e6e6fa")#'yellow' i+=1 # 関数(データベースにデータ追加) def add_todo(ToDo, date, id): with sqlite3.connect(db_path) as conn: cur = conn.cursor() query = '''insert into myItem( ToDo, date ) values(?,?)''' cur.execute(query,(ToDo,date)) conn.commit() # 入力内容クリア clear_text() # 関数(データベースのデータ削除) def delete_todo(ToDo,date,id): with sqlite3.connect(db_path) as conn: cur = conn.cursor() query = 'delete from myItem where id = ?' cur.execute(query,[id]) conn.commit() # 入力内容クリア clear_text() # 関数(データベースのデータ更新) def update_todo(ToDo,date,id): with sqlite3.connect(db_path) as conn: cur = conn.cursor() query = '''update myItem set ToDo = ?, date = ? where id = ?''' cur.execute(query,(ToDo,date,id)) conn.commit() # 入力内容クリア clear_text() # 関数(データベースのデータ検索) def get_search_todos(ToDo,date,id): # if文で条件分岐 # 各テキストボックスに入力された条件で検索 if ToDo != "" : with sqlite3.connect(db_path) as conn: cur = conn.cursor() # プレースホルダ query = '''SELECT * FROM myItem where ToDo like ? ''' cur.execute(query,('%'+ ToDo +'%',)) rows = cur.fetchall() return rows elif date != "" : with sqlite3.connect(db_path) as conn: cur = conn.cursor() # プレースホルダ query = '''SELECT * FROM myItem where date like ? ''' cur.execute(query,('%'+ date +'%',)) rows = cur.fetchall() return rows elif id != "" : with sqlite3.connect(db_path) as conn: cur = conn.cursor() #プレースホルダ query = '''SELECT * FROM myItem where id like ? ''' cur.execute(query,('%'+ id +'%',)) rows = cur.fetchall() return rows # テキストボックスに入力がない場合は、全件表示 else : with sqlite3.connect(db_path) as conn: cur = conn.cursor() cur.execute('select * from myItem') rows = cur.fetchall() return rows # 関数(リストボックスにToDoデータ検索結果表示) def view_search_todos(tree,ToDo,date,id): #テキストボックスクリア id_text.delete(0, tk.END) ToDo_text.delete(0, tk.END) date_text.delete(0, tk.END) #リストボックスの表示クリア tree.delete(*tree.get_children()) #レコードの検索結果をリストボックスに表示 i=0 for row in get_search_todos(ToDo,date,id): tree.insert(parent='', index='end', tags=i, iid=row ,values=(str(row[0]), str(row[1]) ,str(row[2]))) if i % 2 == 0: # tagが偶数(レコードは奇数)の場合のみ、背景色の設定 tree.tag_configure(i,background="#e6e6fa")#'yellow' i+=1 # 関数(テキストボックスの入力内容クリア) def clear_text(): view_todos(tree) # 関数(TREEVIEW上で選択された行から情報を取得) def select_record(event): # 選択行の判別 record_id = tree.focus() # テキストボックス内の値を削除 id_text.delete( 0, tk.END ) ToDo_text.delete( 0, tk.END ) date_text.delete( 0, tk.END ) # 選択行のレコードを取得 record_values = tree.item(record_id, 'values') # テキストボックスに値を挿入 id_text.insert( 0, record_values[0] ) ToDo_text.insert( 0, record_values[1] ) date_text.insert( 0, record_values[2] ) #treeviewの選択解除 tree.selection_remove(tree.selection()) # 関数(HELPメッセージ表示) def help_msg(): tk.messagebox.showinfo(title="HELP", message="【操作説明】\n" +"「追加」ボタン\n" +" 「Todo内容」、「日付」欄に入力されたデータが\n" +" データベースに保存されます。\n" +"\n" +"「削除」ボタン\n" +" 「ID」欄に入力されたIDをもつデータが\n" +" データベースから削除されます\n" +"\n" +"「更新」ボタン\n" +" 登録済みのデータの内容を変更できます。\n" +" データベースに保存されます。\n" +"\n" +"「検索」ボタン\n" +" 「ID」、「Todo内容」、「日付」欄に入力された単語で\n" +" データベースを検索し、その結果を表示します。\n" +"\n" ) ######################################### # データベースを呼び出し --- (4) ######################################### todos = load_todos() ######################################### # GUI メインウィンドウの設定 --- (5-1) ######################################### # rootウィンドウ作成,(タイトル,サイズ)の設定 root = tk.Tk() root.title("ToDoアプリGUI") root.geometry("600x400") # フレームの配置 view_frame = tk.Frame(root) view_frame.pack(anchor=tk.CENTER) text_frame = tk.Frame(root) text_frame.pack(anchor=tk.W) button_frame = tk.Frame(root) button_frame.pack(anchor=tk.CENTER) button2_frame = tk.Frame(root) button2_frame.pack(anchor=tk.CENTER) ######################################### # GUI フレーム(view)の設定 --- (5-2) ######################################### # 列の識別名を指定 column = ('id', 'ToDo', 'date') tree = ttk.Treeview(view_frame, columns=column) # マウスで行を選択したときのイベント tree.bind("<<TreeviewSelect>>", select_record) # 列の設定 tree.column('#0',width=0, stretch='no') tree.column('id', anchor='center', width=50) tree.column('ToDo',anchor='w', width=300) tree.column('date', anchor='center', width=80) # 列の見出し設定 tree.heading('#0',text='') tree.heading('id', text='ID',anchor='center') tree.heading('ToDo', text='ToDo内容', anchor='center') tree.heading('date',text='日付', anchor='center') # ウィジェットの配置 tree.pack(anchor=tk.CENTER,pady=10) ######################################### # GUI フレーム(text)の設定 --- (5-3) ######################################### # テキストボックス(ID)の設定 id_lbl1 = tk.Label(text_frame,text="ID:") id_lbl1.pack(side=tk.LEFT) id_text = tk.Entry(text_frame, width=5) id_text.pack(side=tk.LEFT) # テキストボックス(ToDo内容)の設定 add_lbl1 = tk.Label(text_frame,text="ToDo内容:") add_lbl1.pack(side=tk.LEFT) ToDo_text = tk.Entry(text_frame, width=50) ToDo_text.pack(side=tk.LEFT) # テキストボックス(日付)の設定 add_lbl2 = tk.Label(text_frame,text="日付:") add_lbl2.pack(side=tk.LEFT) date_text = tk.Entry(text_frame, width=15) date_text.pack(side=tk.LEFT) ######################################### # GUI フレーム(button)の設定 --- (5-4) ######################################### # ボタン(ToDoデータ全件表示)の設定 # view_button = tk.Button(button_frame, text="表示", width=20, command=lambda: view_todos(tree)) # view_button.pack(side=tk.LEFT) # ボタン(ToDoデータ追加)の設定 add_button = tk.Button(button_frame, text="追加", width=20, command=lambda: add_todo(ToDo_text.get(),date_text.get(),id_text.get())) add_button.pack(side=tk.LEFT) # ボタン(ToDoデータ削除)の設定 delete_button = tk.Button(button_frame, text="削除", width=20, command=lambda: delete_todo(ToDo_text.get(),date_text.get(),id_text.get())) delete_button.pack(side=tk.LEFT) # ボタン(ToDoデータ更新)の設定 update_button = tk.Button(button_frame, text="更新", width=20, command=lambda: update_todo(ToDo_text.get(),date_text.get(),id_text.get())) update_button.pack(side=tk.LEFT) # ボタン(ToDoデータ検索)の設定 search_button = tk.Button(button_frame, text="検索", width=20, command=lambda: view_search_todos(tree,ToDo_text.get(),date_text.get(),id_text.get()))# search_button.pack(side=tk.LEFT) ######################################### # GUI フレーム(button2)の設定 --- (5-5) ######################################### # ボタン(データインポート)の設定 import_button = tk.Button(button2_frame, text="インポート", width=20, command=lambda: import_todos()) import_button.pack(side=tk.LEFT) # ボタン(データエクスポート)の設定 export_button = tk.Button(button2_frame, text="エクスポート", width=20, command=lambda: export_todos()) export_button.pack(side=tk.LEFT) # ボタン(HELPメッセージ表示)の設定 help_button = tk.Button(button2_frame, text="HELP", width=20, command=lambda: help_msg()) help_button.pack(side=tk.LEFT) ######################################### # GUI Treeviewにレコード一覧を初期表示 --- (5-6) ######################################### view_todos(tree) ######################################### # イベントループ開始 --- (6) ######################################### root.mainloop() |

0 件のコメント:
コメントを投稿