「日経ソフトウェア2022年11月号 特集3 Python デスクトップアプリを作ろう」をやってみた その2

日経ソフトウェア2022年11月号 特集3 Python デスクトップアプリを作ろう」を実行してみました。

 

サンプルプログラム

サンプルプログラムは日経ソフトウェアのWebからダウンロードできます。

以下URLから「本誌バックナンバーを見る」→「2022年11月号」→「「特集3 Pythonでデスクトップアプリを作ろう 後編」(t32211.zip)

 

 

Part2 カレンダー型メモリアプリを作る

 

カレンダー型のメモアプリを作成し、データベースの使用方法を理解していきます。

 

メモリアプリのデータベースを作る

memo.dbとう名前でデータベースを作成します。

日付とメモの2つのデータを入力するテーブルをdailyという名で作成します。

日付に2022_7_26、メモに「本日のメモ\n\n牛乳を買うこと\n髪を切りに行く」と記入します。

以下のようにテーブルにデータを入力します。

?の部分にはdayとmemoの値が入ります。

day = '2022_7_26'
memo = '本日のメモ\n\n牛乳を買うこと\n髪を切りに行く'
sql = 'INSERT INTO daily VALUES (?, ?)'
cur.execute(sql, (day, memo))

 

プログラム例です。

import sqlite3

conn = sqlite3.connect('memo.db')
cur = conn.cursor()

# dailyテーブルの生成
cur.execute("""CREATE TABLE daily(
               date TEXT PRIMARY KEY,
               memo TEXT NOT NULL)""")

# サンプルデータを1件だけ入力
day = '2022_7_26'
memo = '本日のメモ\n\n牛乳を買うこと\n髪を切りに行く'
sql = 'INSERT INTO daily VALUES (?, ?)'
cur.execute(sql, (day, memo))

conn.commit()

# データの確認
for row in cur.execute("SELECT * FROM daily"):
  print(row)

conn.close()

 

実行結果

('2022_7_26', '本日のメモ\n\n牛乳を買うこと\n髪を切りに行く')

 

メモを入力・表示する機能

メモを入力・表示する機能を実装します。

Tkintgerのウィジェットは以下のものがあります。

 

ウィジェット 説明
Button ボタン
Canbas 描画領域
Checkbutton チェックボックス
Combobox コンボボックス
Entry テキストボックス
Frame フレーム(四角いコンテナ)
Label ラベル(1行テキスト)
Labelframe ラベル付きのフレーム
Text テキストボックス(複数行入力)
Listbox リストボックス
Menubutton プルダウンメニュー
Radiobutton ラジオボタン
Notebook タブ切り替え可能なページ
Scale スライドバー
Scrollbasr スクロールバー
Spinbox Entryに値を増減させるスピンボタンがついたもの
Menu ウィンドウメニュー
PreGressbar プログレスバー
Separator 境界線
Treeview ツリー

 

TextとScrollbarを使用したプログラム例です。

import tkinter as tk
from tkinter import messagebox

# ウインドウ(トップレベルTkウィジェット)を生成
root = tk.Tk()
root.geometry('300x180')
root.title('TextとScrollbarのテスト')

# Textウィジェットの生成と配置
text = tk.Text(root, width=38, height=12)
text.grid(row=0, column=0)

# 垂直方向のScrollbarウィジェットの生成と配置
scroll_v = tk.Scrollbar(root, orient=tk.VERTICAL, command=text.yview)
scroll_v.grid(row=0, column=1, sticky=tk.N+tk.S)
text["yscrollcommand"] = scroll_v.set

root.mainloop()


実行結果

長い文章を入力するとスクロールバーが現れました。

メモ

 

カレンダー型メモアプリ

Frameウィジェット、Labelウィジェット、Buttonウィジェット、Textウィジェット、Scrollbarウィジェットを使用します。

 

プログラム例です。

 

import tkinter as tk
import tkinter.ttk as ttk
import datetime as da
import calendar as ca
from tkinter import messagebox
import sqlite3

# 日付を引数にしてメモを取得する関数
def get_memo(day):
  conn = sqlite3.connect('memo.db')
  cur = conn.cursor()
  today_memo = ''
  sql = 'SELECT * FROM daily WHERE date = ?'
  for row in cur.execute(sql, (day,)):
    today_memo = row[1]
  conn.close()
  return today_memo

# 日付がクリックされた時に呼び出される関数
def click(event):
  global click_day
  click_day = event.widget['text']
  n = str(yer[0]) + '_' + str(mon[0]) + '_' + str(click_day)
  title['text'] = make_text_1(yer[0], mon[0], click_day) + 'のメモ'
  text.delete('1.0', 'end')
  text.insert('1.0', get_memo(n))

# 保存ボタンがクリックされた時に呼び出される関数
def save(t_day):
  conn = sqlite3.connect('memo.db')
  cur = conn.cursor()
  sql = 'REPLACE INTO daily VALUES(?, ?)'
  cur.execute(sql, (t_day, text.get('1.0', 'end-1c')))
  conn.commit()
  conn.close()
  messagebox.showinfo('メッセージ', 'データを保存しました。')
  disp(0)

# 引数の日付にメモがあればTrue、なければFalseを返す関数
def check(y, m, d):
  day = str(y) + '_' + str(m) + '_' + str(d)
  if (get_memo(day) != ''):
    return True
  return False

# 日付文字列を作る関数
def make_text_1(y, m, d):
  return str(y) + '年' + str(m) + '月' + str(d) + '日'

def make_text_2(y, m, d):
  return str(y) + '_' + str(m) + '_' + str(d)

# 表示するカレンダーの文字列
WEEK = ['日', '月', '火', '水', '木', '金', '土']
WEEK_COLOUR = ['red', 'black', 'black', 'black',
               'black', 'black', 'blue']

def disp(arg):
  global yer
  global mon

  mon[0] += arg

  if mon[0] < 1:
    mon[0], yer[0] = 12, yer[0] - 1
  elif mon[0] > 12:
    mon[0], yer[0] = 1, yer[0] + 1
  label['text'] = str(yer[0]) + '年' + str(mon[0]) + '月'

  cal = ca.Calendar(firstweekday=6)
 
  for widget in frame.winfo_children():
    widget.destroy()

  r = 0
  for i, x in enumerate(WEEK):
    label_day = tk.Label(frame,
                         text=x,
                         font=('', 10),
                         width=3,
                         fg=WEEK_COLOUR[i])
    label_day.grid(row=r, column=i, pady=1)
  r = 1
  for week in cal.monthdayscalendar(yer[0], mon[0]):
    for i, day in enumerate(week):
      day = ' ' if day == 0 else day
      label_day = tk.Label(frame,
                           text=day,
                           font=('', 10),
                           fg=WEEK_COLOUR[i],
                           borderwidth=1)
      if (yer[0], mon[0], today) == (yer[1], mon[1], day):
        label_day['relief'] = 'solid'
      if check(yer[0], mon[0], day):
        label_day['background'] = 'yellow'
      label_day.bind('<Button-1>', click)
      label_day.grid(row=r, column=i, padx=2, pady=1)
    r = r + 1
   
# ウインドウを生成(リサイズ不可)
root = tk.Tk()
root.title('メモアプリ')
root.geometry('470x250')
root.resizable(0, 0)

# カレンダー用のフレーム
c_frame = tk.Frame(root)
frame = tk.Frame(c_frame)

for n in range(3):
  c_frame.grid_columnconfigure(n, weight=1)

yer  = [da.date.today().year] * 2
mon = [da.date.today().month] * 2
today = da.date.today().day
click_day = today

label = tk.Label(c_frame, font=('', 10))
button_1 = tk.Button(c_frame,
                     text='<',
                     font=('', 10),
                     command=lambda:disp(-1))
button_1.grid(row=0, column=0, pady=10)
label.grid(row=0, column=1)
button_2 = tk.Button(c_frame,
                     text='>',
                     font=('', 10),
                     command=lambda:disp(1))
button_2.grid(row=0, column=2)
frame.grid(row=1, column=0, columnspan=3)

disp(0)

# ここからメモ用のフレーム
d_frame = tk.Frame(root)

# タイトルと保存ボタン
t_frame = tk.Frame(d_frame)
title = tk.Label(t_frame,
                 text=make_text_1(yer[0], mon[0], today) + 'のメモ',
                 font=('', 12))
title.grid(row=0, column=0, padx=20)

button = tk.Button(t_frame, text='保存',
                   command=lambda:save(make_text_2(yer[0], \
                                       mon[0], click_day)))
button.grid(row=0, column=1)
t_frame.grid(row=0, column=0, pady=10)

# メモ用のTextウィジェットとScrollbarウィジェット
text = tk.Text(d_frame, width=30, height=14)
text.grid(row=4, column=0)
scroll_v = tk.Scrollbar(d_frame, orient=tk.VERTICAL, \
                        command=text.yview)
scroll_v.grid(row=4, column=1, sticky=tk.N+tk.S)
text["yscrollcommand"] = scroll_v.set
text.insert('1.0',get_memo(make_text_2(yer[0], mon[0], today)))

c_frame.grid(row=0, column=0, padx=10)
d_frame.grid(row=0, column=1)

root.mainloop()

 

実行結果

実行するとカレンダーが起動します。

カレンダー

メモ欄に文字を記入すると黄色になります。

 

 

データ保存

 

/* -----codeの行番号----- */