簡單計數器

這篇文章中,我將介紹一個使用 PySide6(Qt for Python)來開發的圖形介面應用程式,名為「簡單計數器」。它展示了如何用 Python 建立桌面 GUI,並包含以下功能與設計特色:

  • 顯示計數數字:中央大字顯示目前的計數值。
  • +1 按鈕:點擊可讓數字加一。
  • 重設按鈕:可將計數歸零。

前置準備

安裝 Python 3

在開始之前,請確保你的電腦有安裝 Python 3.11 或更新的版本。如果想要確認安裝的版本,可打開終端機輸入:

1
python3 --version

如果你的電腦沒有安裝 Python 或是版本太舊,請到 Python 官網,依照你的作業系統,下載並安裝。

安裝 Visual Studio Code

Visual Studio Code 是一個文字編輯器,支援各種作業系統。如果你的電腦沒有安裝,請到 Visual Studio Code 官網,下載並安裝。


建立專案資料夾

在你的電腦選擇專案要存放的位置,建立一個專案資料夾。這個「簡單計數器」專案,我取名叫 counter_app

虛擬環境

建立虛擬環境

要進入 counter_app 專案資料夾,在終端機輸入:

1
cd counter_app

接下來在這專案資料夾中建立虛擬環境,在終端機輸入:

1
python3 -m venv venv

第二個 venv 是你要建立的虛擬環境資料夾名稱,常見名稱如 venvenv

啟用虛擬環境

如果你是用 Linux 或 macOS,在終端機輸入:

1
source venv/bin/activate

如果你是用 Windows(CMD 命令提示字元),在終端機輸入:

1
venv\Scripts\activate

如果你是用 Windows(PowerShell),在終端機輸入:

1
venv_name\Scripts\Activate.ps1

安裝 PySide6

在終端機輸入:

1
pip install PySide6

安裝作業先告一段落,接下來要開始寫程式碼


基本檔案

啟動 Visual Studio Code 按下 Open Folder 按鈕或是 File > Open Folder…,選擇之前建立的專案資料夾 counter_app 。在 counter_app 專案資料夾,新增一個檔案叫 main.py,後面講的程式碼內容都是寫在 main.py 內。

匯入模組

1
import sys

匯入 Python 的 sys 模組,用來讀取命令列參數,或在應用程式結束時呼叫 sys.exit()

1
2
3
4
5
6
7
8
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QLabel,
    QPushButton,
    QVBoxLayout,
)

PySide6.QtWidgets 模組匯入 GUI 元件類別:

  • QApplication: 應用程式的主控類別。
  • QMainWindow: 主視窗基底類別。
  • QWidget: 所有視覺元件的基底類別。
  • QLabel: 顯示純文字或圖片的元件。
  • QPushButton: 可按的按鈕。
  • QVBoxLayout: 垂直排列子元件的佈局類別。
1
from PySide6.QtCore import Qt

匯入 Qt 列舉型別,提供如 AlignCenter 對齊方式等常數。

設定樣式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
COUNTER_TITLE_STYLE = """
font-size: 40px;
"""

COUNTER_NUMBER_STYLE = """
font-size: 120px;
font-weight: bold;
"""

BUTTON_STYLE = """
font-size: 30px;
padding: 10px;
border: 1px solid black;
color: black;
background-color: white;
"""

WIDGET_STYLE = """
background-color: white;
"""

建立 CSS 格式的 Qt 樣式表。定義標題、計數字體、按鈕、主視窗區塊背景等的樣式。

建立 CounterApp 類別

1
class CounterApp(QMainWindow):

定義一個繼承自 QMainWindow 的應用程式主類別 CounterApp

初使方法

1
2
    def __init__(self):
        super().__init__()

初始化父類別 QMainWindow,設立視窗基本設定。

1
        self.count = 0

設定當前計數的變數,初始為 0。

1
2
3
4
5
        self.counter_title_label = QLabel(text="簡單計數器")
        self.counter_title_label.setStyleSheet(COUNTER_TITLE_STYLE)

        self.count_number_label = QLabel(text=f"{self.count}")
        self.count_number_label.setStyleSheet(COUNTER_NUMBER_STYLE)

建立標題標籤跟顯示目前數字的標籤並套用樣式。

1
2
3
        self.increase_button = QPushButton("+ 1")
        self.increase_button.setStyleSheet(BUTTON_STYLE)
        self.increase_button.clicked.connect(self.increase_count)

建立「+1」按鈕,設定樣式,並連接到 increase_count() 方法。

1
2
3
        self.reset_button = QPushButton("↻ 重設")
        self.reset_button.setStyleSheet(BUTTON_STYLE)
        self.reset_button.clicked.connect(self.reset_count)

建立「重設」按鈕,樣式設定,點擊時呼叫 reset_count() 方法。

1
2
        self.counter_title_label.setAlignment(Qt.AlignCenter)
        self.count_number_label.setAlignment(Qt.AlignCenter)

讓標題與數字標籤在視窗中置中顯示。

1
2
3
4
5
        layout = QVBoxLayout()
        layout.addWidget(self.counter_title_label)
        layout.addWidget(self.count_number_label)
        layout.addWidget(self.increase_button)
        layout.addWidget(self.reset_button)

建立一個垂直排列的佈局,將標籤與按鈕加進去。

1
2
3
        widget = QWidget()
        widget.setStyleSheet(WIDGET_STYLE)
        widget.setLayout(layout)

建立一個容器 QWidget,設定背景顏色,套用垂直佈局。

1
        self.setCentralWidget(widget)

把上面那個組合好的 widget 設為主視窗的中央部件。

更新螢幕方法

1
2
    def update_screen(self, count):
        self.count_number_label.setText(f"{count}")

更新數字顯示的函式,接收一個計數數字並顯示在畫面上。

增加計數方法

1
2
3
    def increase_count(self):
        self.count += 1
        self.update_screen(self.count)

點擊「+1」按鈕時執行的函式:加一後更新畫面。

重設計數方法

1
2
3
    def reset_count(self):
        self.count = 0
        self.update_screen(self.count)

點擊「重設」按鈕時執行的函式:將數字重設為 0 並更新畫面。

1
if __name__ == "__main__":

程式進入點。只有當這個檔案被直接執行時,才會執行以下內容。

1
    app = QApplication(sys.argv)

建立一個 QApplication 實例,傳入命令列參數,初始化整個 Qt 應用程式。

1
2
    window = CounterApp()
    window.show()

建立主視窗,然後顯示出來。

1
    sys.exit(app.exec())

執行 Qt 的事件迴圈,等待使用者操作。程式結束時關閉系統。

完整程式碼

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import sys

from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QLabel,
    QPushButton,
    QVBoxLayout,
)
from PySide6.QtCore import Qt

COUNTER_TITLE_STYLE = """
font-size: 40px;
"""

COUNTER_NUMBER_STYLE = """
font-size: 120px;
font-weight: bold;
"""

BUTTON_STYLE = """
font-size: 30px;
padding: 10px;
border: 1px solid black;
color: black;
background-color: white;
"""

WIDGET_STYLE = """
background-color: white;
"""

class CounterApp(QMainWindow):
    def __init__(self):
        super().__init__()

        self.count = 0

        self.counter_title_label = QLabel(text="簡單計數器")
        self.counter_title_label.setStyleSheet(COUNTER_TITLE_STYLE)

        self.count_number_label = QLabel(text=f"{self.count}")
        self.count_number_label.setStyleSheet(COUNTER_NUMBER_STYLE)

        self.increase_button = QPushButton("+ 1")
        self.increase_button.setStyleSheet(BUTTON_STYLE)
        self.increase_button.clicked.connect(self.increase_count)

        self.reset_button = QPushButton("↻ 重設")
        self.reset_button.setStyleSheet(BUTTON_STYLE)
        self.reset_button.clicked.connect(self.reset_count)

        self.counter_title_label.setAlignment(Qt.AlignCenter)
        self.count_number_label.setAlignment(Qt.AlignCenter)

        layout = QVBoxLayout()
        layout.addWidget(self.counter_title_label)
        layout.addWidget(self.count_number_label)
        layout.addWidget(self.increase_button)
        layout.addWidget(self.reset_button)

        widget = QWidget()
        widget.setStyleSheet(WIDGET_STYLE)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def update_screen(self, count):
        self.count_number_label.setText(f"{count}")

    def increase_count(self):
        self.count += 1
        self.update_screen(self.count)

    def reset_count(self):
        self.count = 0
        self.update_screen(self.count)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = CounterApp()
    window.show()

    sys.exit(app.exec())

執行程式

在終端機輸入:

1
python3 main.py