Tkinter入门:制作学习进度图

写在前面的话

今日目标,做一个扇贝学习进度图

Tkinter入门:制作学习进度图_第1张图片

功能包括:
1、用Tkinter设置界面,用户需要输入四项信息
​ (1)每天单词的学习计划数量
​ (2)每天阅读的学习计划数量
​ (3)每天听力的学习计划数量
​ (4)输入扇贝ID
2、根据用户输入数据,计算年度学习计划数量
3、根据用户输入的ID,读取扇贝中2020年已经学习的内容。分别计算单词、阅读、听力的总数量
4、利用TkinterCanvas组件,将数据做成进度条

界面预览

Tkinter入门:制作学习进度图_第2张图片

界面设计

老规矩,不想看介绍的,可以直接翻到最后看代码

关于Tkinter入门的Label(显示文本)、gird(布局为网格)、Button(按钮)三个组件操作,可以看Tkinter入门:制作一个日历

今天主要用到的组件是Label(显示文本)、Button(按钮)、Canvas(画框,用于显示进度)、place(放置位置)、Entry(文本输入)

导入库

import ShanbeyRecord
import tkinter as tk
from tkinter.messagebox import showinfo
import time 
  • ShanbeyRecord:用于扇贝查卡
  • tkinter:用于制作界面
  • showinfo:如果信息输入错误,用于显示报错信息
  • time:控制进度条速度

创建窗口

window = tk.Tk()  # 创建主窗口,名字为window
window.title('Progress')  # 窗口名称
window.geometry('700x450')  # 窗口大小
bgcolor = '#F0FFF0' # 背景颜色
fgcolor = 'teal'  # 前景颜色
window.configure(background=bgcolor)  # 给窗口上色

其中窗口颜色,用英文字母teal,或者RGB形式#F0FFF0都可以,至于这个颜色对应的RGB是什么,百度RGB颜色,网上一大堆,你喜欢什么颜色,就改什么。

Tkinter入门:制作学习进度图_第3张图片

显示文字:Label

先显示标题

tk.Label(window, text='2020', background=bgcolor, font=('Helvetica',40,'bold italic'), foreground=fgcolor).place(x=280, y=30)

text='2020':文本内容
background=bgcolor:背景色
font=('Helvetica',40,'bold italic'):字体设置,包括字体+大小+加粗、倾斜
foreground=fgcolor:前景色
place(x=280, y=30):放置的坐标位置

Tkinter入门:制作学习进度图_第4张图片

显示输入信息,每天的目标Your Goal (Every Day)和扇贝IDShanbey ID,设置方式和前面一致

tk.Label(window, text='Your Goal (Every Day)', background=bgcolor, font=('Helvetica',14,'bold italic'), foreground=fgcolor).place(x=50, y=120)
tk.Label(window, text='Shanbey ID', background=bgcolor, font=('Helvetica',14,'bold italic'), foreground=fgcolor).place(x=50, y=170)
Tkinter入门:制作学习进度图_第5张图片

显示输入框:Entry

EntWord = tk.Entry(window, textvariable=tk.StringVar(value='word number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntWord.place(x=300, y=125)
EntRead = tk.Entry(window, textvariable=tk.StringVar(value='read number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntRead.place(x=425, y=125)
EntListen = tk.Entry(window, textvariable=tk.StringVar(value='listen number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntListen.place(x=550, y=125)
EntID = tk.Entry(window, textvariable=tk.StringVar(value='ID:must be number'), width=20, fg=fgcolor, font=('Helvetica',10,'italic'))
EntID.place(x=180, y=175)

textvariable=tk.StringVar(value='word number'):默认显示文字
width=12:输入框宽度
fg=fgcolor:颜色设置
font=('Helvetica',10,'italic'):字体设置
EntWord.place(x=300, y=125):放置位置

Tkinter入门:制作学习进度图_第6张图片

设计进度条:Canvas

# 设置进度条标签
tk.Label(window, text='Word', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=100+150)
tk.Label(window, text='Read', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=150+150)
tk.Label(window, text='Listen', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=200+150)

# 设置进度条
CanvasWord = tk.Canvas(window, width=465, height=22, bg="white")
CanvasWord.place(x=120, y=100+150)
CanvasRead = tk.Canvas(window, width=465, height=22, bg="white")
CanvasRead.place(x=120, y=150+150)
CanvasListen = tk.Canvas(window, width=465, height=22, bg="white")
CanvasListen.place(x=120, y=200+150)

Canvas是画布,下次详细讲。今天就是了解一下基础操作。
width=465:宽度
height=22:高度
bg="white":背景色

Tkinter入门:制作学习进度图_第7张图片

按钮设计:Button

StartButton = tk.Button(window, 
                        text='Let Go!', # 文字
                        font=('Helvetica',14,'bold italic'),  # 字体
                        foreground=fgcolor, # 前景色                           
                        background=bgcolor, # 背景色
                        activebackground='white', # 点击时的背景色
                        activeforeground=fgcolor, # 点击时的前景色
                        relief='raised', # 边框样式
                        command=Start) # 点击时出发的动作,这边定义了一个start函数
StartButton.place(x=550, y=160) # 放置位置
Tkinter入门:制作学习进度图_第8张图片

界面设计就搞定啦~~
接下来我们开始设计具体的事件

事件设计

在Button中,我们最后设置了command=Start,也就是,按下按钮后,要进行一个Start操作。接下来我们来写Start函数

计算目标值

def Start():
    # 获取输入的每天目标
    GoalWord = EntWord.get()
    GoalRead = EntRead.get()
    GoalListen = EntListen.get() 
    
    # 判断是不是输入的是数字,如果不是,窗口提示
    try:
        NumWord = int(GoalWord)
        NumRead = int(GoalRead)
        NumListen = int(GoalListen)
    except:
        showinfo(message='每月目标输入错误,请输入纯数字')
        return False
    
    # 一年有365天
    GoalWord = NumWord*365
    GoalRead = NumRead*365
    GoalListen = NumListen*365
    
    # 获取目标值
    tk.Label(window, text=str(GoalWord), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=100+150)
    tk.Label(window, text=str(GoalRead), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=150+150)
    tk.Label(window, text=str(GoalListen), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=200+150)

当输入正确的数字时,右下角会对应显示一年的目标量

Tkinter入门:制作学习进度图_第9张图片

如果输入错误时,利用showinfo跳出报错窗口

Tkinter入门:制作学习进度图_第10张图片

获取扇贝数据

def Start():
    --------------------
    # 读取扇贝数据    
    ID = EntID.get()
    
    try:
        ShanbeyRecord.ReadRecond(int(ID))
        Record = ShanbeyRecord.ReadRecond(ID)
        Word = Record.Word
        Read = Record.Read
        Listen = Record.Listen        
    except:
        showinfo(message='ID输入错误,请输入纯数字\n'+
                 '可通过扇贝网页版,右上角【我的打卡】,获取打卡网址\n'+
                 '网址是https://www.shanbay.com/checkin/user/*******/\n'+
                 '最后一串数字即为ID')
        return False

这边就不详细将扇贝数据是怎么获取的了,之前爬虫都讲了好多。这边直接调用ShanbeyRecord.py,这个文件附在最后。如果ID输入错误,同样系统会报错。这边要注意,这个ID必须是数字,不能是字母!

Tkinter入门:制作学习进度图_第11张图片

显示进度条

我们单独写一个函数,用来显示进度条。因为单词、听力、阅读的进度条都是一样的,没必要写3遍

# 显示进度条
def ShowProgress(canvas, number, total):
    fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill=fgcolor)
    x = total  # total代表的进度条的总数目,就是目标数字
    n = 465/x  # 465是进度条的尺寸,每一次前进n
    for i in range(number): # number时目前学习的数字
        n = n + 465/x # 每次进度条往前加465/x
        canvas.coords(fill_line, (0, 0, n, 60))
        window.update() # 窗口更新
        time.sleep(1/number)  # 控制进度条的速度

然后在Start函数最后,调用ShowProgress函数

def Start():
    -----------
    ShowProgress(CanvasWord, Word, GoalWord)
    ShowProgress(CanvasRead, Read, GoalRead)
    ShowProgress(CanvasListen, Listen, GoalListen)

界面代码

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 21 16:10:23 2020

@author: zhaoy
"""
import ShanbeyRecord
import tkinter as tk
from tkinter.messagebox import showinfo
import time 

window = tk.Tk()  # 创建主窗口
window.title('Progress')  # 窗口名称
window.geometry('700x450')  # 窗口大小

bgcolor = '#F0FFF0'#'lightcyan' # 背景颜色
fgcolor = 'teal'  #前景颜色
window.configure(background=bgcolor)  # 给窗口上色

# 显示标题
tk.Label(window, text='2020', background=bgcolor, font=('Helvetica',40,'bold italic'), foreground=fgcolor).place(x=280, y=30)

# 显示输入信息框
tk.Label(window, text='Your Goal (Every Day)', background=bgcolor, font=('Helvetica',14,'bold italic'), foreground=fgcolor).place(x=50, y=120)
tk.Label(window, text='Shanbey ID', background=bgcolor, font=('Helvetica',14,'bold italic'), foreground=fgcolor).place(x=50, y=170)
#
EntWord = tk.Entry(window, textvariable=tk.StringVar(value='word number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntWord.place(x=300, y=125)
EntRead = tk.Entry(window, textvariable=tk.StringVar(value='read number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntRead.place(x=425, y=125)
EntListen = tk.Entry(window, textvariable=tk.StringVar(value='listen number'), width=12, fg=fgcolor, font=('Helvetica',10,'italic'))
EntListen.place(x=550, y=125)
EntID = tk.Entry(window, textvariable=tk.StringVar(value='ID:must be number'), width=20, fg=fgcolor, font=('Helvetica',10,'italic'))
EntID.place(x=180, y=175)
#
# 设置进度条标签
tk.Label(window, text='Word', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=100+150)
tk.Label(window, text='Read', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=150+150)
tk.Label(window, text='Listen', background=bgcolor, font=('Helvetica',16,'bold italic'), foreground=fgcolor).place(x=50, y=200+150)
#
# 设置进度条
CanvasWord = tk.Canvas(window, width=465, height=22, bg="white")
CanvasWord.place(x=120, y=100+150)
CanvasRead = tk.Canvas(window, width=465, height=22, bg="white")
CanvasRead.place(x=120, y=150+150)
CanvasListen = tk.Canvas(window, width=465, height=22, bg="white")
CanvasListen.place(x=120, y=200+150)
#
# 显示进度条
def ShowProgress(canvas, number, total):
    fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill=fgcolor)
    x = total  # 未知变量,可更改
    n = 465/x  # 465是矩形填充满的次数
    for i in range(number):
        n = n + 465/x
        canvas.coords(fill_line, (0, 0, n, 60))
        window.update()
        time.sleep(1/number)  # 控制进度条流动的速度
        
def Start():
    # 获取输入的每天目标
    GoalWord = EntWord.get()
    GoalRead = EntRead.get()
    GoalListen = EntListen.get() 
    
    # 判断是不是输入的是数字,如果不是,窗口提示
    try:
        NumWord = int(GoalWord)
        NumRead = int(GoalRead)
        NumListen = int(GoalListen)
    except:
        showinfo(message='每月目标输入错误,请输入纯数字')
        return False
    
    # 一年有365天
    GoalWord = NumWord*365
    GoalRead = NumRead*365
    GoalListen = NumListen*365
    
    # 获取目标值
    tk.Label(window, text=str(GoalWord), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=100+150)
    tk.Label(window, text=str(GoalRead), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=150+150)
    tk.Label(window, text=str(GoalListen), background=bgcolor, font=('Helvetica',13,'bold italic'), foreground=fgcolor).place(x=590, y=200+150)
#
    # 读取扇贝数据    
    ID = EntID.get()
    
    try:
        ShanbeyRecord.ReadRecond(int(ID))
        Record = ShanbeyRecord.ReadRecond(ID)
        Word = Record.Word
        Read = Record.Read
        Listen = Record.Listen        
    except:
        showinfo(message='ID输入错误,请输入纯数字\n'+
                 '可通过扇贝网页版,右上角【我的打卡】,获取打卡网址\n'+
                 '网址是https://www.shanbay.com/checkin/user/*******/\n'+
                 '最后一串数字即为ID')
        return False
#        
    ShowProgress(CanvasWord, Word, GoalWord)
    ShowProgress(CanvasRead, Read, GoalRead)
    ShowProgress(CanvasListen, Listen, GoalListen)
#
# button按钮
# relief must be flat, groove, raised, ridge, solid, or sunken
StartButton = tk.Button(window, 
                        text='Let Go!', 
                        font=('Helvetica',14,'bold italic'), 
                        foreground=fgcolor,                             
                        background=bgcolor,
                        activebackground='white',
                        activeforeground=fgcolor,
                        relief='raised',
                        command=Start)
StartButton.place(x=550, y=160)

window.mainloop()

爬虫代码

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 21 16:50:05 2020

@author: zhaoy
"""

import requests  # 获取网页数据
import datetime
import xlwt
import pandas as pd



class Shanbey(): 
    def __init__(self, name, read, listen):
        self.Word = name
        self.Read = read
        self.Listen = listen
        
def SaveRecond(ID):
    # 准备表格
    workbook = xlwt.Workbook()  #定义workbook
    sheet = workbook.add_sheet('2020')  #添加sheet
    head = ['date', 'bdc','listen','read','time_bdc','time_listen','time_read']
    for h in range(len(head)):
        sheet.write(0, h, head[h])    #把表头写到Excel里面去
    ExcelRow = 1; #定义Excel表格的行数,从第二行开始写入,第一行已经写了表头
    
    # 读取数据
    try:    
        for Page in range(1,10):
            Web = "https://www.shanbay.com/api/v1/checkin/user/"+str(ID)+"/"+"?page="+str(Page)
            Res = requests.get(Web)
            DataEveryPage = Res.json()
            
            End = str(datetime.date(2020,1,1)).split(" ")[0]   
            
            for data in DataEveryPage['data']:
                if data['info']!='':
                    if data['checkin_date'] >= End:
                        sheet.write(ExcelRow, 0, data['checkin_date'])  
                        try:
                            sheet.write(ExcelRow, 1, data['stats']['bdc']['num_today'])
                            sheet.write(ExcelRow, 4, data['stats']['bdc']['used_time'])                   
                        except:
                            sheet.write(ExcelRow, 1, 0) 
                            
                        try:
                            sheet.write(ExcelRow, 2, data['stats']['listen']['num_today'])
                            sheet.write(ExcelRow, 5, data['stats']['listen']['used_time'])                   
                        except:
                            sheet.write(ExcelRow, 2, 0)  
                            sheet.write(ExcelRow, 5, 0)  
                            
                        try:
                            sheet.write(ExcelRow, 3, data['stats']['read']['num_today'])
                            sheet.write(ExcelRow, 6, data['stats']['read']['used_time'])                   
                        except:
                            sheet.write(ExcelRow, 3, 0)  
                            sheet.write(ExcelRow, 6, 0)       
                        ExcelRow += 1
                    else:
                        break
        workbook.save('Summary2020.xls')
        return True
    except:
        return False

def ReadRecond(ID):
    if SaveRecond(ID):
        df = pd.read_excel('Summary2020.xls')
        df['date'] = pd.to_datetime(df['date']) 
        df = df.set_index('date') # 将date设置为index   
        Record = Shanbey(df['bdc'].sum(),df['read'].sum(),df['listen'].sum())      
        return Record 
    else:
        return False

#ID = ********      
#Record = ReadRecond(ID)
#print(Record.Word)

你可能感兴趣的:(Tkinter入门:制作学习进度图)