通過tkinter(ttk)視覺化計算拼單每個人的優惠價

2020-09-29 11:01:10

背景

在日常生活中,常常會遇到因平臺優惠最低價比較高,所以需要和朋友拼單購買的情況,如買外賣時的滿減優惠、天貓雙十一「滿400減xxx」等活動。在計算費用時,需要計算各自需要支付給買單人的價格。我本人就是常常和單位同事一起拼單點漢堡王外賣,享受55-20、120-55等優惠。
所以通過這個場景可以練習部分GUI及其他python技巧,並增加計算效率。

效果圖

剛開啟時的頁面

在這裡插入圖片描述
在這裡插入圖片描述

計算後的頁面,頁面也根據賬單結果的長度,做了自適應

在這裡插入圖片描述

賬單結果頁面適合截圖發到群裡

在這裡插入圖片描述

python程式碼

# -*- coding: UTF-8 -*-
from datetime import datetime
import tkinter as tk
from tkinter import ttk #比一般的tk更好用,有部分新增的功能,如tab切換


choiselist = ["小A","小B","小C","小D","小E","小F","小G","小H","小I"] #人員名單
nmax = len(choiselist)
path = "19.png" #圖片路徑

windows=tk.Tk() #建立視窗
windows.title('優惠均衡計價器') #視窗名
windows.geometry('430x%s' % (nmax*30+120)) #根據名單長度適應視窗初始大小
windows.resizable(height=True) #高度可變


#建立tab切換元件
tabControl = ttk.Notebook(windows)
tab1 = ttk.Frame(tabControl)
tabControl.add(tab1, text='填寫資訊')
tab2 = ttk.Frame(tabControl)
tabControl.add(tab2, text='賬單結果')
tabControl.pack(expand=1, fill="both")

#建立第一個tab頁面
tab1_win = ttk.LabelFrame(tab1)
tab2_win = ttk.LabelFrame(tab2)
tab1_win.grid(column=0, row=0, padx=8, pady=4) #通過padx、pady引數留一部分空白間距
tab2_win.grid(column=0, row=0, padx=8, pady=4)

## 第二個tab頁中元素
cal_text = tk.StringVar() #定義一個動態的文字
cal_text.set("暫無資料")
tk.Message(tab2_win, textvariable=cal_text, width=400).grid(row=0, column=0) #新建結果文字
photo = tk.PhotoImage(file=path)

## 設定多組,用exec()函數,迴圈取變數名
for i in range(nmax):
    ii = i+1
    exec('label%s1 = ttk.Label(tab1_win, text="%s、 姓名:").grid(column=0, row=%s, sticky="W")' % (ii, ii, i))
    exec('label%s2 = ttk.Label(tab1_win, text=choiselist[i]).grid(column=1, row=%s, sticky="W")' % (ii, i))
    exec('label%s3 = ttk.Label(tab1_win, text="商品金額:").grid(column=2, row=%s, sticky="E")' % (ii, i))
    exec('entry%s = ttk.Entry(tab1_win, width=16)' % ii)# 建立一個金額輸入框
    exec('entry%s.grid(column=3, row=%s, padx=2)' % (ii, i))# 在這裡因為要get()Entry中的值,所以需要單獨.grid()
    exec('entry%s.insert(0,"0")' % ii) # 預設為"0"

## 按鍵B_add對應的程式,計算各成員金額,並輸入至tab2中
def cal(nmax):
    list_money=[]
    global photo #需要全域性呼叫photo 不然無法顯示
    total = 0
    nn = 0
    for i in range(nmax):
        dict = {}
        exec("dict['money1'] = float(entry%s.get())" %(i+1)) #因為Entry的名稱是不固定的,所以要用exec()函數調取
        dict["name"] = choiselist[i]
        total += dict['money1']
        list_money.append(dict) #寫入列表中
        if dict['money1'] > 0: #為視窗適應做準備
            nn += 1
    fact = float(entry_fact.get()) #獲取實際總付款額
    if total != 0:
        rate = fact / total
        for ii in range(nmax):
            list_money[ii]["money2"] = list_money[ii]["money1"] * rate
        now = datetime.now().strftime('%Y-%m-%d   %H:%M:%S') # 獲取當前時間,並用strftime格式化
        text = "賬單時間:" + now + "\n" + "商品總價:%.2f元" % total +"      折扣:%.2f " % (rate*100) +"% \n\n個人賬單如下:"
        ## 只展示實際下單的人
        for dict in list_money:
            if dict["money1"] != 0:
                text = text + "\n" + dict["name"]+"    商品價值:%.2f" % dict["money1"] + "          應付款:%.2f" % dict["money2"]
            else:
                continue
        text = text + "\n  \n"+ "付款碼如下,請儘快付款,謝謝!"
        tk.Label(tab2_win, image=photo).grid(row=1, column=0)  # 把圖片通過標籤類展示出來
        ## 視窗適應
        xx = nmax*30+120
        yy = nn * 15 + 400
        if xx < yy:
            windows.geometry('430x%s' % yy)
    else:
        text = "請輸入正確字元"
    cal_text.set(text) #將text更新至 cal_text 中

## 輸入實際總付款額入口
label_fact = ttk.Label(tab1_win, text="實際總付款額:").grid(column=2, row=nmax, sticky='E')
entry_fact = ttk.Entry(tab1_win, width=16)
entry_fact.grid(column=3, row=nmax, padx=2)
ttk.Label(tab1_win, text=" ").grid(column=2, row=nmax+1)#建立空白行
##設定按鍵
B_add=tk.Button(tab1_win, text="開始計算", width=20, command=lambda:cal(nmax)).grid(column=3, row=nmax+2, padx=3)

windows.mainloop()#生成前端視窗