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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM