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

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

 

サンプルプログラム

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

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

 

nkbp.jp

 

PART3 「割り勘計算機」アプリを作ろう

割り勘アプリを作成し、Frameウィジェット、Comboboxウィジェットの使用方法を理解していきます。

また、「割り勘計算機」の機能は以下の通りです。

・1円単位、10円単位の支払はない

・偉い人は新人の3倍、平社員の2倍の支払

・金額によっては漢字は平社員よりも少し安くする

 

2つの画面を切り替える

画面を切り替えるにはFrameウィジェットを使用します。

サンプルコードは以下の通りです。

・importでtkinterモジュールの呼び出し

・2フレーム間を行き来できるようにそれぞれのフレームにボタンを用意

・rootという名前のオブジェクトを作成し、サイズは250px x 100px

・ウィンドウに表示されるタイトルは「tkrasize Test」

・column(列)とrow(行)に対してそれぞれweight=1

・tk.Frameを使用してrootオブジェクトにフレームを生成

・FrameにLabelとButtonを付加

・同じようにframe_2を生成

・tkraise関数を使用することでframe_1を最前に

 

import tkinter as tk

# button_1のハンドラ関数
def change_no2():
  frame_2.tkraise() # frame_2を前面に出す

# button_2のハンドラ関数
def change_no1():
  frame_1.tkraise() # frame_1を前面に出す

root = tk.Tk()
root.geometry('250x100')
root.title('tkraise Test')

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

# 画面1(frame_1)の生成と配置
frame_1 = tk.Frame(root)
frame_1.grid(row=0, column=0, sticky=tk.NSEW)

# 画面1のウィジェットの生成と配置
label_1 = tk.Label(frame_1, text='画面1です。')
button_1 = tk.Button(frame_1, text='次の画面',
                     command=change_no2)
label_1.pack(pady=10)
button_1.pack(pady=10)

# 画面2(frame_2)の生成と配置
frame_2 = tk.Frame(root)
frame_2.grid(row=0, column=0, sticky=tk.NSEW)

# 画面2のウィジェットの生成と配置
label_2 = tk.Label(frame_2, text='画面2です。')
button_2 = tk.Button(frame_2, text='戻る',
                     command=change_no1)
label_2.pack(pady=10)
button_2.pack(pady=10)

# frame_1を前面に出す
frame_1.tkraise()

root.mainloop()


 

実行結果

「次の画面」ボタンを押すと「画面2です。」が表示されます。

「戻る」ボタンを押すと「画面1です。」が表示されます。

スイッチ

 

Comboboxウィジェット

Comboboxウィジェットを使用する場合は、ttkをimportする必要があります。

以下サンプルコードを見ていきますと、

・メッセージボックスをimport

・クリックしたらメッセージボックスにメッセージとしてComboboxウィジェットの内容を表示

・Comboboxウィジェットは1から5を選択可能

・それ以外の数値は直接入力可能

 

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox

# Buttonのハンドラ関数
def click_get():
  messagebox.showinfo('メッセージ', combo.get())

root = tk.Tk()
root.geometry('250x100')
root.title('Combo Test')

# Comboboxウィジェットの生成と配置
number = ['1','2','3','4','5']
combo = ttk.Combobox(root, state='normal',
                     values=number, width=5)
combo.current(0)
combo.pack(pady=10)

# Buttonウィジェットの生成と配置
button = tk.Button(root, text='表示',
                   command=click_get)
button.pack()

root.mainloop()

 

実行結果

数値を選択し、「表示」ボタンを押すとメッセージボックスにその値が評されました。

 

Combobox



 

割り勘計算機

最後に割り勘計算機アプリを起動してみます。

金額に1000を入力し計算を押すと、400円、300円、200円、100円となりました。

ベース金額=偉い人x3+平社員x2+新人+幹事(x2)なので

1000円を8で割った125円x3=375円 125円x2=250円 125円x1=125円

で、10円、1円を切り上げて400円、300円、200円となりました。残りは幹事が100円支払ってちょうど1000円です。

再計算する場合は「計算に戻る」で戻ります。

 

割り勘

 

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import math

# 計算結果の表示
def calculation_result():
  t = int(total.get())
  e = int(erai.get())
  h = int(hira.get())
  s = int(shin.get())
  kanj = 2
  base = math.floor(t / (e * 3 + h * 2 + s + kanj))
  print("base ",base)
  mErai = 0 if e == 0 else (math.ceil(base*3/100) * 100)
  mHira = 0 if h == 0 else (math.ceil(base*2/100) * 100)
  mShin = 0 if s == 0 else (math.ceil(base*1/100) * 100)
  mKanj = base * kanj
  total2 = mErai * e + mHira * h + mShin * s + mKanj
  mKanj  = mKanj  - (total2 - t)
 
  c = [['偉い人は :', str(mErai)],
       ['平社員は :', str(mHira)],
       ['新人は :', str(mShin)],
       ['幹事は :', str(mKanj)]]
  for i in range(len(out_label)):
    out_label[i][0]['text'] = c[i][0]
    out_label[i][1]['text'] = c[i][1]

  out_frame.tkraise() # 計算結果画面へ切り替え

def change_in():
  in_frame.tkraise() # 入力画面へ切り替え

root = tk.Tk()
root.geometry('300x220')
root.title('割り勘計算機')

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

# 入力画面用フレームの生成と配置
in_frame = tk.Frame(root)
in_frame.grid(row=0, column=0, sticky=tk.NSEW)

# Entryウィジェットの生成
total = tk.Entry(in_frame, width=10)

# Labelウィジェットの生成
s = ('金 額( 円 )', '偉い人(人数)',
     '平社員(人数)', '新 人(人数)',
     '幹 事(1人)')
in_label=
for i in range(len(s)):
  in_label.append(tk.Label(in_frame, text=s[i]))

# Comboboxウィジェットの生成
number = ('1', '2', '3', '4', '5',
          '6', '7', '8', '9', '10')
erai = ttk.Combobox(in_frame, values=number, width=8)
erai.current(0)
hira = ttk.Combobox(in_frame, values=number, width=8)
hira.current(0)
shin = ttk.Combobox(in_frame, values=number, width=8)
shin.current(0)

# Buttonウィジェットの生成
button = tk.Button(in_frame, text='計算',
                   command=calculation_result)

for i in range(2):
  in_frame.columnconfigure(i, weight=1)
for i in range(6):
  in_frame.rowconfigure(i, weight=1)

in_label[0].grid(column=0, row=0)
total.grid(column=1, row=0)
in_label[1].grid(column=0, row=1)
erai.grid(column=1, row=1)
in_label[2].grid(column=0, row=2)
hira.grid(column=1, row=2)
in_label[3].grid(column=0, row=3)
shin.grid(column=1, row=3)
in_label[4].grid(column=0, row=4, rowspan=2 )
button.grid(column=1, row=5, sticky=tk.N)

# 計算結果画面用フレームの生成と配置
out_frame = tk.Frame(root)
out_frame.grid(row=0, column=0, sticky=tk.NSEW)

out_frame.columnconfigure(0, weight=1)
out_frame.columnconfigure(1, weight=1)
for i in range(5):
  out_frame.rowconfigure(i, weight=1)

# Labelウィジェットの生成
out_label =
for i in range(4):
  out_label.append([tk.Label(out_frame, padx=20),
                    tk.Label(out_frame, padx=20)])

# Buttonウィジェットの生成
button = tk.Button(out_frame, text='計算に戻る',
                   command=change_in)

for i in range(len(out_label)):
  out_label[i][0].grid(column=0, row=i, sticky=tk.E)
  out_label[i][1].grid(column=1, row=i, sticky=tk.W)

button.grid(column=0, row=4, columnspan=2, sticky=tk.N)

# frameを前面にする
in_frame.tkraise()

root.mainloop()

 

 

 

 




 

 

 

 

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