zoukankan      html  css  js  c++  java
  • 利用Eric+Qt Designer编写倒计时时钟

    【前言】前几日通过编写命令行通讯录,掌握了Python的基本语法结构,于是开始向更高水平冲击,利用Eric与Qt Designer 编写一个带界面的小程序。本次实操中也确实遇到了不少问题,通过学习也都解决了,达到了学习进步的目的。
    【吐槽】写博客比编程序难多了,程序写了一下午,博客写了一整天,这么费力的写出来,希望可以帮助到一些刚开始学习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 (类元组)。

    方法

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

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

    >>> 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创建窗体

    1. 在Eric“项目浏览器”的“窗体”中,单击右键,选择【新建窗体】
    2. 选择窗体类型“主窗口”,点击【OK】
    3. 输入窗体文件名,点击【Save】
    4. 在项目浏览器中,右键点击新建的.ui窗体文件,选择【在Qt设计师中打开】
    5. 打开Qt Designer后,会有几个基本的窗口,你自己的窗口“MainWindow”、“窗口部件盒”、“对象查看器”、“属性编辑器”,其他的窗口可从菜单栏“视图”窗口选择。
      拖拽“MainWindows”设置窗口的初始大小
      从“窗口部件盒”拖4个Widget到“MainWindow”
    6. 在“MainWindow”4个Widget以外的地方单击右键,选择【布局】-【水平布局】
    7. 在一个Widget上单击右键,选择【提升为】
    8. 在“提升的类名称”中输入要创建的自定义的widget类名称,点击【添加】
    9. 选中“提升的类”中新建的那个类,点击【提升】
    10. 选中Widget组件,在右侧的“属性编辑器”中将objectName改为mpl···Widget
    11. 保存文件,退出Qt Designer。
    12. 右击Eric“项目浏览器”中的.ui窗体文件,选择【编译窗体】,生成文件Ui_countdownmainwindow.py
    13. 打开生成的文件,将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小讲堂

  • 相关阅读:
    浪潮之巅阅读笔记01
    2018年春季个人阅读计划
    问题账户需求分析
    需求工程解析图收获
    《软件需求分析》阅读笔记
    《软件需求》阅读笔记之三
    《小账本》开发日志 第六天
    《小账本》开发日志 第五天
    [POI2009]KAM-Pebbles BZOJ1115 [ 待填坑 ] 博弈
    打谷机 BZOJ 1603 模拟
  • 原文地址:https://www.cnblogs.com/kallan/p/5797815.html
Copyright © 2011-2022 走看看