2009年4月23日

[PyQt 教學] Part 6: 物件導向的寫法

[PyQt 教學] Part 5: Signals & Slots mechanism

到目前為止,我們都是用 procedure-oriented 的方式寫 PyQt code。對於本就是 object-oriented 的 GUI framework 來說,物件導向寫法貌似更加自然,是必需要學會的。


將先前那個 connect 的例子改成 class 型式:( code )

#!/usr/bin/env python

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWidget(QWidget):
    def __init__(self, parent = None):
        super(MyWidget, self).__init__(parent)
        self.createLayout()
        self.spinBox.valueChanged.connect(self.slider.setValue)
        self.slider.valueChanged.connect(self.spinBox.setValue)
    
    def createLayout(self):
        self.spinBox = QSpinBox()
        self.spinBox.setPrefix("$")
        self.spinBox.setRange(0, 100)
        
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 100)
        
        layout = QHBoxLayout()
        layout.addWidget(self.spinBox)
        layout.addWidget(self.slider)
        self.setLayout(layout)


app = QApplication(sys.argv)

widget = MyWidget()
widget.show()

app.exec_()


第 7 行:我們定義出 MyWidget 這個新的 class,繼承自外觀空白一片的 QWidget,好讓我們自行塞入東西。內含兩個 memfunc:建構式 __init__() 和自行設計的函式 createLayout()

第 14 行:開始定義 createLayout()。Python 的 instance method 必帶一個 self 參數。

第 15~20 行:搞出 self.spinBoxself.slider 兩個 property,並設定之。

第 22~25 行:設定版面。setLayout() 這個 method 繼承自 QWidgetself.setLayout(layout)layout 設給 MyWidget 自身的版面。( 原本的版面是繼承自 QWidget,空白一片...... )

第 8 行:開始定義建構式。因為我們的 class 不需要寄生在其它 widget 中,所以設定參數 parent = None,以成為 top-level window。

第 9 行:讓 MyWidget 的建構式調用 parent class 的建構式。這個過程是必備的,因為繼承得來的 __init__() 已被覆寫,Python 不會再自動調用 parent class 的建構式;QWidget 未被初始化的話,MyWidget 一開就會瞬間爆炸。

super() 這樣的語法,讓 Python 能自動判別 MyWidget 的 parent class,避免直接寫死在程式碼內。

第 10 行:呼叫 instance method createLayout()

第 11~12 行:建立 connection,讓兩個 widget 能互相影響。

第 30~31 行:建構出 MyWidget 的 instance 並顯示出來。

需要特別注意的地方,就是內部物件到底該不該加前綴 self. 以變成 property 吧!我個人的心得是:取決關鍵在於該物件會不會被跨函式存取。例如 spinBoxslider 是在 createLayout() 中建構,但也會在 __init__() 中被存取到,所以必需成為 property。而 layout 用完沒事就可以滾了,所以只活在 createLayout() 中無所謂。

當然啦,程式架構與流程解法並不是唯一的,所以寫成這樣也是可以的,省下一卡車的 self.。怎樣的寫法在各種情境中比較合情合理,就有賴自行判斷了。


平常寫 PyQt 程式,建議都用物件導向的方式,自創 widget class 後再利用之。困難嗎?老樣子,pattern 記起來,轉換就很快了。

下次來寫個稍微有用的玩意兒吧......

[PyQt 教學] Part 7: 聚砂成塔

1 則留言:

  1. 感謝blog主寫的詳盡教學<(_ _)>
    我把在學PyQt時,關於class這塊讓人比較搞不清楚的部份寫得更詳細一點,如果有人看不懂可以參考:
    http://kuanyui.github.io/2014/09/13/learn-python-via-pyqt/#more

    回覆刪除