シェルスクリプトマガジン

香川大学SLPからお届け!(Vol.94掲載)

著者:川本真子

 私は最近、To Doリストを管理するGU(I Graphical User Interface)アプリをPythonで作成しました。作成には、Pythonの標準GUIライブラリの「Tkinter」(https://docs.python.org/ja/3/library/tkinter.html)を用いています。今回は、そのGUIアプリの実装について紹介します。

シェルスクリプトマガジン Vol.94は以下のリンク先でご購入できます。

図7 フレーム配置用のコード

# フレームの作成
fr_title = tk.Frame(root, width=650, height=40, bd=5, relief='solid')
fr_genre = tk.Frame(root, width=650, height=45, bd=5, relief='solid')
fr_add   = tk.Frame(root, width=650, height=70, bd=5, relief='solid')
fr_op    = tk.Frame(fr_add, width=100, height=65, bd=5, relief='solid')
fr_must  = tk.Frame(root, width=325, height=260, bd=5, relief='solid')
fr_mlist = tk.Frame(fr_must, width=315, height=190, bd=5, relief='solid')
fr_want  = tk.Frame(root, width=325, height=260, bd=5, relief='solid')
fr_wlist = tk.Frame(fr_want, width=315, height=190, bd=5, relief='solid')
# フレームのサイズを固定
fr_title.grid_propagate(False)
fr_add.grid_propagate(False)
fr_op.grid_propagate(False)
fr_genre.grid_propagate(False)
fr_must.grid_propagate(False)
fr_mlist.grid_propagate(False)
fr_want.grid_propagate(False)
fr_wlist.grid_propagate(False)
# フレームを配置
fr_title.grid(row=0, column=0, columnspan=2, sticky=tk.EW)
fr_genre.grid(row=1, column=0, columnspan=2, sticky=tk.EW)
fr_add.grid(row=2, column=0, columnspan=2, sticky=tk.EW)
fr_must.grid(row=3, column=0)
fr_want.grid(row=3, column=1)

図9 グローバル変数を定義するコード

btnge = 'sc'
color = '#A8EEFF'
la_text = '学校のTo Do'
textlist = []

図10 ウィジェット配置用のコード

# fr_genreのウィジェット
buttonsc = tk.Button(fr_genre, text="学校", state=tk.DISABLED, bg='#A8EEFF', font=font1,
                     command=lambda:genre(buttonli, buttonsc, 'sc', la_title, label_ge, label_m, label_w))
buttonli = tk.Button(fr_genre, text="生活", state=tk.NORMAL, bg='#FFF9A8', font=font1,
                     command=lambda:genre(buttonsc, buttonli, 'li', la_title, label_ge, label_m, label_w))
# fr_titleのウィジェット
la_title = tk.Label(fr_title, text="今日のTo Do", bg=color, font=font1)
# fr_addのウィジェット
label_ge = tk.Label(fr_add, text=la_text, bg=color, font=font1)
entry = tk.Entry(fr_add, width=30, font=font1)
rad = tk.StringVar()
rad.set('Must')
radio_m = tk.Radiobutton(fr_op, text='Must', font=font1, value='Must', variable=rad)
radio_w = tk.Radiobutton(fr_op, text='Want', font=font1, value='Want', variable=rad)
button_add = tk.Button(fr_add, text="追加", font=font1, command = lambda:add(rad))
# fr_mustのウィジェット
label_m = tk.Label(fr_must, text="Must", bg=color, font=font1)
de_must = tk.Button(fr_must, text="削除", font=font1, command=lambda:deletion('Must'))
# fr_wantのウィジェット
label_w = tk.Label(fr_want, text="Want", bg=color, font=font1)
de_want = tk.Button(fr_want, text="削除", font=font1, command=lambda:deletion('Want'))
# ウィジェットと残りのフレームの配置
la_title.grid()
buttonsc.grid(row=0, column=0)
buttonli.grid(row=0, column=1)
label_ge.grid(row=0, column=0)
entry.grid(row=0, column=1)
fr_op.grid(row=0, column=2)
button_add.grid(row=0, column=3)
radio_m.grid(row=0, column=0)
radio_w.grid(row=1, column=0)
label_m.grid()
fr_mlist.grid()
de_must.grid()
label_w.grid()
fr_wlist.grid()
de_want.grid()

図12 クラスと関数を定義するコード

class Text:
  def __init__(self, box, de, fr, te, ch, pr, ge):
    self.box = box # チェックボックスの変数
    self.de = de   # 完了は「fin」、未完了は「unfin」
    self.fr = fr   # チェックボックスの表示フレーム
    self.te = te   # To Doの内容
    self.ch = ch   # チェックの有無
    self.pr = pr   # MustかWantか
    self.ge = ge   # 学校か生活か

def add(rad):
  text = tk.StringVar()
  text.set((entry.get()))
  entry.delete(0, tk.END)
  check = tk.StringVar()
  check.set('0')
  if rad.get() == 'Must':
    frame = fr_mlist
    priority = 'Must'
  else:
    frame = fr_wlist
    priority = 'Want'
  box = tk.Checkbutton(frame, textvariable=text,
                       variable=check, font=font1)
  tex=Text(box, 'unfin' ,frame, text, check, priority, btnge)
  textlist.append(tex)
  todo()

def todo():
  i = 0
  for t in textlist:
    if t.de == 'unfin':
      if t.ge == btnge:
        t.box.grid(row=i, sticky = tk.W)
    i += 1

def deletion(pri):
  for t in textlist:
    if t.pr == pri:
      if t.ge == btnge:
        if t.ch.get() == '1':
          t.de = 'fin'
          t.box.destroy()
  todo()

def genre(button, buclick, gen, la_title,
          label_ge, label_m, label_w):
  button['state'] = tk.NORMAL
  buclick['state'] = tk.DISABLED
  global btnge
  global color
  global la_text
  btnge = gen
  if (gen == 'sc'):
    color = '#A8EEFF'
    la_text = '学校のTo Do'
  else:
    color = '#FFF9A8'
    la_text = '生活のTo Do'
  la_title['bg'] = color
  label_ge['bg'] = color
  label_ge['text'] = la_text
  label_m['bg'] = color
  label_w['bg'] = color
  # チェックボックスを破棄して再作成
  for t in textlist:
    t.box.destroy()
    t.box = tk.Checkbutton(t.fr, textvariable=t.te,
                           variable = t.ch, font=font1)
  todo()