Tkinter入门:制作学习进度图

写在前面的话

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

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

界面预览

界面设计

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

关于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颜色,网上一大堆,你喜欢什么颜色,就改什么。

显示文字: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):放置的坐标位置

显示输入信息,每天的目标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)

显示输入框: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):放置位置

设计进度条: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":背景色

按钮设计: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) # 放置位置

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

事件设计

在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)

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

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

获取扇贝数据

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必须是数字,不能是字母!

显示进度条

我们单独写一个函数,用来显示进度条。因为单词、听力、阅读的进度条都是一样的,没必要写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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350