利用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小講堂

相關文章
相關標籤/搜索