利用Eric+Qt Designer编写倒计时时钟

【前言】前几日经过编写命令行通信录,掌握了Python的基本语法结构,因而开始向更高水平冲击,利用Eric与Qt Designer 编写一个带界面的小程序。本次实操中也确实遇到了很多问题,经过学习也都解决了,达到了学习进步的目的。
【吐槽】写博客比编程序难多了,程序写了一下午,博客写了一成天,这么费力的写出来,但愿能够帮助到一些刚开始学习Python的朋友。因为我不是科班出身,编程纯属业余爱好,因此也是一边学一边编的,有不足的地方还请批评指正。python

1.目标

编写一个倒计时时钟程序,用饼图的形式显示一天、一周、一个月以及一年已通过了多少时间还剩多少时间,用于提醒人珍惜时间。编程

2.实现方法

  • 因为准库time模块不能继承,建立一个新的时间的类,使用标准库time模块来进行时间的相关操做。
  • 使用Eric与Qt Designer开发
  • 使用matplotlib的pie函数绘制饼图

3.菜鸟难点

  1. 对time模块不熟悉,不知如何使用。
  2. Qt Designer的使用。
  3. Qt中添加matplotlib组件窗口。

3.1 time模块

time 模块提供了一些处理日期和一天内时间的函数。它是创建在 C 运行时库的简单封装。
给定的日期和时间能够被表示为浮点型(从参考时间, 一般是 1970.1.1 到如今通过的秒数,即 Unix 格式),或者一个表示时间的 struct (类元组)。canvas

方法

3.1.1 time()

返回从1970.1.1 到如今通过的秒数小程序

>>> import time
>>> time.time()
1471794516.136771

3.1.2 localtime()

返回元组形式的时间,后端

>>> import time
>>> time.localtime()
time.struct_time(tm_year=2016, tm_mon=8, tm_mday=21, tm_hour=23, tm_min=49, tm_sec=57, tm_wday=6, tm_yday=234, tm_isdst=0)
名称 含义
tm_year
tm_mon
tm_mday
tm_hour
tm_min
tm_sec
tm_wday 周几(0-6)
tm_yday 一年中的第几天
tm_isdst -1表明系统判断是否为夏时令
0表明非夏时令
1表明夏时令

3.1.3 ctime()

返回字符串形式的时间浏览器

>>> import time
>>> time.ctime()
'Sun Aug 21 23:50:56 2016'

3.1.4 strptime()

将字符串形式的时间转换成元组形式的时间微信

符号 含义
%y 两位数年份(00-99 )
%Y 四位数年份(000-9999 )
%m 月份(01-12)
%d 日期 0-31
%H 24小时制小时数( 0-23 )
%I 12小时制小时数( 01-12 )
%M 分钟数(00-59)
%S 秒(00-59)
%a 本地星期简化名称
%A 本地星期完整名称
%b 本地月份简化名称
%B 本地月份完整名称
%c 本地相应的日期表示和时间表示
%j 年内的第几天(001-366)
%p 本地A.M.或 P.M.
%U 一年中的星期数(00-53),星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53),星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区名称
%% %号
>>> import time
>>> time.strptime('20160821','%Y%m%d')
time.struct_time(tm_year=2016, tm_mon=8, tm_mday=21, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=234, tm_isdst=-1)

3.1.5 strftime()

将元组形式的字符串按照指定格式转换成字符串形式app

>>> import time
>>> time.strftime('%Y%m%d',(2016,8,21,0,0,0,6,234,0))
'20160821'

3.1.6 mktime()

讲元组形式的时间转换成从19700101累计的秒数编辑器

>>> import time
>>> time.mktime((2016,8,21,0,0,0,6,234,0))
1471708800.0

3.2 Eirc与Qt Designer的使用

本部分结合项目编写一块儿讲解。函数

3.3Qt中添加matplotlib组件窗口

在Qt中添加matplotlib组件窗口须要建立一个新的类mplwidget,在这个类中建立matplotlib的画布,而后在Qt designer中添加一个普通的Widget,而后将这个widget提高为咱们所建的类mplwidget。

4.项目编写

4.1 建立项目

  1. 打开Eric,单击菜单栏【项目】-【新建】
  2. 输入“项目名称”,选择“项目文件夹”,点击【OK】

    4.2建立窗体

  3. 在Eric“项目浏览器”的“窗体”中,单击右键,选择【新建窗体】
  4. 选择窗体类型“主窗口”,点击【OK】
  5. 输入窗体文件名,点击【Save】
  6. 在项目浏览器中,右键点击新建的.ui窗体文件,选择【在Qt设计师中打开】
  7. 打开Qt Designer后,会有几个基本的窗口,你本身的窗口“MainWindow”、“窗口部件盒”、“对象查看器”、“属性编辑器”,其余的窗口可从菜单栏“视图”窗口选择。
    拖拽“MainWindows”设置窗口的初始大小
    从“窗口部件盒”拖4个Widget到“MainWindow”
  8. 在“MainWindow”4个Widget之外的地方单击右键,选择【布局】-【水平布局】
  9. 在一个Widget上单击右键,选择【提高为】
  10. 在“提高的类名称”中输入要建立的自定义的widget类名称,点击【添加】
  11. 选中“提高的类”中新建的那个类,点击【提高】
  12. 选中Widget组件,在右侧的“属性编辑器”中将objectName改成mpl···Widget
  13. 保存文件,退出Qt Designer。
  14. 右击Eric“项目浏览器”中的.ui窗体文件,选择【编译窗体】,生成文件Ui_countdownmainwindow.py
  15. 打开生成的文件,将from mplpiewidget import MplPieWidget 剪切至class Ui_MainWindow(object):上面,保存文件。

    4.4 自定义Widget类的编写

  • 单击Eric工具栏新建按钮,建立一个空白文档,保存为名为‘mplpiewidget.py’的文件。
  • 伪代码
# 导入PyQt5的图形界面组件模块QtGui,非图形类模块QtCore,基础界面控件模块QtWidgets,
# 导入matplotlib库中qt5后端,用于实如今qt5的组件里绘制matplotlib图像。
# 导入matplotlib的figure模块,figure模块包含全部画图的元素。
# 建立matplotlib的画布类MplCanvas,继承于qt5agg的figurecanvas
    #初始化
        #建立figure,Axis
        #超类初始化
        #将widget设置成expandable,随窗口变化
        #系统更新widget设置
#建立自定义widget类MplPieWidget,继承于QtWidget.QWidget
    #初始化
        #超类初始化
        #建立MplCanvas实例画布
        #建立垂直布局的容器
        #在容器中添加画布
        #设置垂直布局生效
  • 编写代码
# 导入PyQt5的图形界面组件模块QtGui,非图形类模块QtCore,基础界面控件模块QtWidgets,
from PyQt5 import QtGui, QtCore, QtWidgets
# 导入matplotlib库中qt5后端,用于实如今qt5的组件里绘制matplotlib图像。
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# 导入matplotlib的figure模块,figure模块包含全部画图的元素。
from matplotlib.figure import Figure

# 建立matplotlib的画布类MplCanvas,继承于qt5agg的figurecanvas
class MplCanvas(FigureCanvas):

    #初始化
    def __init__(self):
        #建立figure,Axis
        self.fig= Figure()
        self.ax= self.fig.add_subplot(111)
        #超类初始化
        FigureCanvas.__init__(self,self.fig)
        #将widget设置成expandable,随窗口变化
        FigureCanvas.setSizePolicy(self,\
            QtWidgets.QSizePolicy.Expanding,\
            QtWidgets.QSizePolicy.Expanding)
        #系统更新widget设置
        FigureCanvas.updateGeometry(self)

#建立自定义widget类MplPieWidget,继承于QtWidget.QWidget
class MplPieWidget(QtWidgets.QWidget):

    #初始化
    def __init__(self, parent= None):
        #超类初始化
        QtWidgets.QWidget.__init__(self,parent)
        #建立MplCanvas实例画布
        self.canvas= MplCanvas()
        #建立垂直布局的容器
        self.vbl= QtWidgets.QVBoxLayout()
        #在容器中添加画布
        self.vbl.addWidget(self.canvas)
        #设置垂直布局生效
        self.setLayout(self.vbl)

4.4 Time类编写

  • 单击Eric工具栏新建按钮,建立一个空白文档,保存为名为‘mytime.py’的文件。
  • 伪代码
#导入time模块
#建立Time类
    #获取如今的年、月、日、时、分、秒、星期以及今天是今年的第几天
    #将值赋给year,month,day,hour,minute,second,weekday,yearday

    #建立一个方法,根据是否是闰年返回今年的总天数
        #if year可以被400整除:
            #天数为366
        #elif year能被100整除:
            #天数为365
        #elif year能被4整除:
            #天数为366
        #else:
            #天数为365
        #返回天数
    #建立本年天数变量daysOfYear

    #建立一个方法,返回本月天数
        #if month是1,3,5,7,8,10,12月:
            #天数为31
        #elif month是4,6,9,11月:
            #天数是30
        #elif 今年是闰年:
            #天数为29
        #else:
            #天数为28
        #返回天数

    #建立本月天数变量daysOfMonth

    #建立一个方法,将字符串形式时间转换成时间戳
        #将year,month,day转换成字符串连在一块儿
        #将时间戳形式时间返回

    #将今天的时间(时分秒)换算成秒数
  • 编写代码
#导入time模块
import time

#建立Time类
class Time(object):

    #获取如今的年、月、日、时、分、秒、星期以及今天是今年的第几天
    #将值赋给year,month,day,hour,minute,second,weekday,yearday
    localTime= time.localtime()
    year,month,day,hour,minute,second,weekday,yearday= localTime[0:-1]

    #建立一个方法,根据是否是闰年返回今年的总天数
    def totalDaysOfYear(year):
        #if year可以被400整除:
        if year% 400== 0:
            #天数为366
            totalDays= 366
        #elif year能被100整除:
        elif year% 100== 0:
            #天数为365
            totalDays= 365
        #elif year能被4整除:
        elif year% 4== 0:
            #天数为366
            totalDays= 366
        #else:
        else:
            #天数为365
            totalDays= 365
        #返回天数
        return totalDays

    #建立本年天数变量daysOfYear
    daysOfYear= totalDaysOfYear(year)

    #建立一个方法,返回本月天数
    def totalDaysOfMonth(month):
        #if month是1,3,5,7,8,10,12月:
        if month in [1,3,5,7,8,10,12]:
            #天数为31
            totalDays= 31
        #elif month是4,6,9,11月:
        elif month in [4,6,9,11]:
            #天数是30
            totalDays= 30
        #elif 今年是闰年:
        elif self.daysOfYear== 366:
            #天数为29
            totalDays= 29
        #else:
        else:
            #天数为28
            totalDays= 28
        #返回天数
        return totalDays

    #建立本月天数变量daysOfMonth
    daysOfMonth= totalDaysOfMonth(month)

    #建立一个方法,将字符串形式时间转换成时间戳
    def transformTime(year,month,day):
        #将year,month,day转换成字符串连在一块儿
        nowtime= str(year)+ '-'+ str(month)+ '-'+ str(day)
        #将时间戳形式时间返回
        return time.mktime(time.strptime(nowtime,'%Y-%m-%d'))

    #将今天的时间(时分秒)换算成秒数
    secondsOfTheDay= time.time()- transformTime(year,month,day)

4.5 主程序编写

1.Eric“项目浏览器”右击.ui文件选择【生成对话框代码】

2.选择【新建】类名

3.单击【OK】,项目中生成名为countdownmainwindow.py的文件

4.编辑countdownmainwindow.py

  • from .Ui_countdownmainwindow import Ui_MainWindow改成from Ui_countdownmainwindow import Ui_MainWindow
  • 导入咱们写的Time类

from mytime import Time

  • 建立一个绘制饼图的方法
def plotPie(self,widget,list,colors):
        widget.canvas.ax.clear()
        widget.canvas.ax.pie(list,explode= None, labels= None, colors= colors, \
        labeldistance= 1.1, autopct= None,shadow= False, \
        startangle= 90, pctdistance= 0.6)
        widget.canvas.draw()
  • 建立列表,用于绘制饼图及设置饼图颜色
#建立年列表=[今年剩余天数,已过天数]
    yearList= [Time.daysOfYear- Time.yearday, Time.yearday]
    yearColorsList= ['blue','gray']
    #建立月列表=[本月剩余天数,已过天数]
    monthList= [Time.daysOfMonth- Time.day, Time.day]
    monthColorsList= ['blue','gray']
    #建立周列表=[本周剩余天数,已过天数]
    weekList= [6-Time.weekday, Time.weekday+1]
    weekColorsList= ['blue','gray']
    #建立日列表-[本天剩余秒数,已过秒数]
    dayList= [24*60*60- Time.secondsOfTheDay, Time.secondsOfTheDay]
    dayColorsList= ['blue','gray']
  • 在__init__方法中添加绘制饼图的方法
def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.plotPie(self.mplYearWidget,ListOfPie.yearList,['blue','gray'])
        self.plotPie(self.mplMonthWidget,ListOfPie.monthList,['blue','gray'])
        self.plotPie(self.mplWeekWidget,ListOfPie.weekList,['blue','gray'])
        self.plotPie(self.mplDayWidget,ListOfPie.dayList,['blue','gray'])
  • 在最后添加以下代码,将主窗口显示出来。
if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication
    
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())
  • 完整代码为:
# -*- coding: utf-8 -*-

"""
Module implementing MainWindow.
"""

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow
from countdown import ListOfPie
from Ui_CountdownMainWindow import Ui_MainWindow


class MainWindow(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.plotPie(self.mplYearWidget,ListOfPie.yearList,['blue','gray'])
        self.plotPie(self.mplMonthWidget,ListOfPie.monthList,['blue','gray'])
        self.plotPie(self.mplWeekWidget,ListOfPie.weekList,['blue','gray'])
        self.plotPie(self.mplDayWidget,ListOfPie.dayList,['blue','gray'])

        
    def plotPie(self,widget,list,colors):
        widget.canvas.ax.clear()
        widget.canvas.ax.pie(list,explode= None, labels= None, colors= colors, \
        labeldistance= 1.1, autopct= None,shadow= False, \
        startangle= 90, pctdistance= 0.6)
        widget.canvas.draw()

if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication
    
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

4.6 程序的调试与运行

  • F5键为调试程序
    选中主程序调试,调试整个项目,若是没有错误直接运行
  • F2键为直接运行程序

5 程序演示


本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。

想观看Matplotlib教学视频,了解更多Matplotlib实用技巧可关注

微信公众帐号: MatplotlibClass

今日头条号:Matplotlib小讲堂

相关文章
相关标签/搜索