➣ Reading Time: 11 minutes

看完這篇文章你會得到的成果圖

前言

這篇我們要來學一個新的東西 QTimer!
QTimer 是獨立於程式運作的計時器,
你可能會想什麼時候會用到?

其實很意外的,真正的程式反而非常經常會需要這個,功能來作為「自動更新」,
我們仔細想想,一般的程式一行接一行執行下去,但萬一有個背景任務,
是隨著時間要定期更新的,我們主程式的流程哪有「突然切換至時間功能,並更新」,這樣的設計
(如果是 step by step 的設計程式,這樣也太難。)

因此我們有 QTimer 的設計,來幫助我們定期更新一些東西,或做一些其他事情。

之後也會介紹 QThread,也同樣的是讓主程式在執行的同時,能夠同時有其他的支線任務可以獨立運行!

之前內容的重點複習 (前情提要)

我們接下來的討論,會基於讀者已經先讀過我 day5 文章 的架構下去進行程式設計
如果還不清楚我程式設計的邏輯 (UI.py、controller.py、start.py 分別在幹麻)
建議先閱讀 day5 文章後再來閱讀此文。

此篇文章的範例程式碼 github

https://github.com/howarder3/ironman2021_PyQt5_photoshop/tree/main/day18_qtimer

UI 設計部份 (UI.py)

這次我們的重點不是放在 UI 設計,我們簡單拉一個作為結果顯示用的 Qlabel 即可。

轉換成 UI.py

一樣的編譯指令,我們加上 -x (也可不加),
我們就可以先檢視看看轉換後的視窗是不是跟我們想像的一樣。

轉換 day18.ui -> UI.py

pyuic5 -x day18.ui -o UI.py

執行看看 UI.py 畫面是否如同我們想像

一樣,這程式只有介面 (視覺上的呈現),沒有任何互動功能

  • 看看我們製作出來的介面
python UI.py

controller 設計部份 (controller.py)

QTimer 的使用方式很簡單,主要我們需要設定一個 timeout 時間,
每經過一次 timeout,我們的程式就會做一次指定的事情

from PyQt5 import QtCore 
from PyQt5.QtWidgets import QMainWindow, QFileDialog
from PyQt5.QtCore import QTimer

import time
import os

from UI import Ui_MainWindow

class MainWindow_controller(QMainWindow):
    def __init__(self):
        super().__init__() # in python3, super(Class, self).xxx = super().xxx
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setup_control()

    def setup_control(self):
        self.timer=QTimer() # init QTimer
        self.timer.timeout.connect(self.run) # when timeout, do run one
        self.timer.start(1) # start Timer, here we set '1ms' while timeout one time
        self.time_counter = 0  # init time counter # for testing: 3599000

    def run(self):
        self.ui.label.setText(str(self.set_time_counter_format(self.time_counter))) # show time_counter (by format)
        self.time_counter += 1 # time_counter + 1


    def set_time_counter_format(self, time_counter):
        ms = time_counter % 1000
        total_sec = max(0, (time_counter - ms)//1000)
        hour = max(0, total_sec//3600)
        minute = max(0, total_sec//60 - hour * 60)
        sec = max(0, (total_sec - (hour * 3600) - (minute * 60)))
        return f"{hour}:{minute:0>2}:{sec:0>2}.{ms:0>3}"

我們先來看一下,最主要的設定 QTimer 部分

設定主程式 setup_control()

  • self.timer=QTimer():初始化 QTimer
  • self.timer.timeout.connect(self.run):當 QTimer 每經過一次 timeout,執行 run 的動作
  • self.timer.start(1):開始 QTimer,這裡的”1″ 代表的是 1ms,所以我們每 1ms 就會 timeout 一次
  • self.time_counter = 0:我們初始化計數器,從 0 開始計數。

設定 run(),每 timeout 就執行一次

  • self.ui.label.setText(str(self.set_time_counter_format(self.time_counter)))):設定格式並顯示時間
  • self.time_counter += 1:計數器 +1 (因為 timeout 一次)

設定時間格式 set_time_counter_format()

  • 這邊就是我自己計算的公式了,有幾個計算上的重點
  • max(0, x):避免計算結果 < 0 導致顯示負數,我們直接給予 0 這個值
  • f”{hour}:{minute:0>2}:{sec:0>2}.{ms:0>3}”: f-string 的 格式設定,我們抓住「:」冒號後的就是格式設定內容,「0」表示補0,「>」表示靠右,「2(3)」表示總共2(3)位。

執行結果

照我們 day5 的程式架構,我們執行

python start.py

於是我們就這樣完成了我們的碼表 (stopwatch)。

此外,我們可以透過更改 counter 的初始值來修正程式錯誤
例如依照我們上面的算式,我們可以設定初始值為 “3599000”,我們可以同時驗證「小時」、「分鐘」、「秒」、能不能正確增加 (因為從約 0:59:50開始)

Reference

⭐Python PyQt5 相關文章整理⭐:
⭐基礎知識與架構篇⭐:
1.【PyQt5】Day 1 – 安裝 PyQt,建立自己的第一支 PyQt5 程式
2.【PyQt5】Day 2 – 利用 Qt designer 建立第一支有自己介面的 PyQt5 程式
3.【PyQt5】Day 4 – 重要的 Qt 程式邏輯觀念,務必先有此觀念後面才會懂自己在幹嘛
4.【PyQt5】Day 5 – 開始來設計我們的 controller.py,改以「程式角度」來說明如何建立 PyQt 的系統
⭐基本元件應用篇⭐:
1.【PyQt5】Day 6 – 我們的第一個 output 手段 – Qlabel
2.【PyQt5】Day 7 – 我們的第一個 input 手段 – QPushButton
3.【PyQt5】Day 8 – 我們的第二個 input 手段 – QLineEdit
4.【PyQt5】Day 9 – 以 QLineEdit, QTextEdit, QPlainTextEdit 作為文字的輸入
6.【PyQt5】Day 14 - 使用 QSlider 製作可拖曳的滑條
8.【PyQt5】Day 19 - 使用 QProgressBar,製作進度條的功能
⭐介面系統控制篇⭐:
5.【PyQt5】Day 10 – 以 QFileDialog 讀取系統的檔案、資料夾
7.【PyQt5】Day 18 / Project 使用 QTimer,自製碼表(計時器) PyQt5 stopwatch DIY
1.【PyQt5】Day 20 - PyQt 最重要的 QThread 概念 / 為什麼 windows, mac, ubuntu (linux) 程式會「沒有回應」?
2.【PyQt5】Day 21 – 透過 PyQt 實現滑鼠監聽總整理,完全掌握滑鼠控制 (listen mouse)
3.【PyQt5】Day 22 – PyQt 視窗的個性化/屬性控制 setWindowFlags,禁止放大縮小、永遠顯示於最上層/最下層
4.【PyQt5】Day 23 – 使用系統內建的調色盤 QColorDialog,來替我們選擇顏色 QColor (Color Picker)
5.【PyQt5】Day 24 / Project 偵測滑鼠目前指示顏色的小工具 (滴管工具), 利用 QCursor 偵測滑鼠, QApplication 取得截圖
⭐影像處理篇⭐:
1.【PyQt5】Day 11 – 以 Qlabel 在 PyQt 中顯示圖片 (基於 QImage 使用 OpenCV)
2.【PyQt5】Day 12 – 建立一個可以縮放圖片大小的顯示器 (基於 QImage 使用 OpenCV)
3.【PyQt5】Day 13 – 使用 QVBoxLayout, QscrollArea 製作出捲軸,以高解析度檢視圖片 (基於 QImage 使用 OpenCV)
4.【PyQt5】Day 15 / Project 與檔案功能整合,製作出可讀取圖片並可縮放的 UI 介面 (使用 PyQt + OpenCV)
5.【PyQt5】Day 16 - 在 PyQt5 中取得圖片座標 (滑鼠位置) mousePressEvent,觀察圖片在 Qt 中產生的方式,對原圖進行座標換算處理
6.【PyQt5】Day 17 / Project 製作標註 roi 工具, 開始導入 OpenCV 作為繪圖引擎, 在圖上畫點並顯示座標
⭐project 篇⭐:
1.【PyQt5】Day 25 / Project 自己做一個影片播放器 DIY video player (結合 PyQt + OpenCV)
2.【PyQt5】Day 26 / Project 替我們影片播放器增加一個顯示進度的滑條 video player add slider (與昨日 bottleneck 處理細節)
3.【PyQt5】Day 27 / Project 製作影片 ROI 標註工具 (PyQt 結合 OpenCV 在圖上畫點畫線)
4.【PyQt5】Day 28 / final project – 1 來搞一個自己的 photoshop 吧!UI 篇 + 純程式架構篇 (結合 PyQt + OpenCV)
5.【PyQt5】Day 29 / final project – 2 來搞一個自己的 photoshop 吧!後段程式細節篇 (結合 PyQt + OpenCV)
6.【PyQt5】Day 30 / final project – 3 來搞一個自己的 photoshop 吧!把每個方法封裝起來製作出還原功能吧! (結合 PyQt + OpenCV)
⭐打包程式篇⭐:
1.【PyQt5】Day 3 – 用 pyinstaller 將 python 程式打包,把每天的成果分享給你的親朋好友
⭐【喜歡我的文章嗎? 歡迎幫我按讚~ 讓基金會請創作者喝一杯咖啡!
如果喜歡我的文章,請幫我在下方【按五下Like】 (Google, Facebook 免註冊),會由 「LikeCoin」 贊助作者鼓勵繼續創作,讀者們「只需幫忙按讚,完全不用出錢」哦!

likecoin-steps