注:文中譯者的話將用方括號(hào)【】標(biāo)出。
這一部分我們將學(xué)習(xí)PyQt中一些基本的函數(shù)。
一個(gè)簡(jiǎn)單的例子
這是一個(gè)能夠顯示出一個(gè)窗口的簡(jiǎn)單例子。目前為止我們已經(jīng)可以對(duì)這個(gè)窗口干很多事情了,比如說改變它的尺寸,最大化,最小化……干這些事情本來需要寫很多代碼,但是PyQt已經(jīng)幫我們寫好啦【開心】,由于干這些事情的代碼在絕大多數(shù)應(yīng)用中都會(huì)重復(fù)使用,所以沒有必要一遍一遍地寫這些代碼。
我們可以感受到PyQt4是一個(gè)很高級(jí)的工具庫(kù),如果我們用一些比較低級(jí)的工具庫(kù)的話,完成下面這些代碼干的事情可能需要敲幾百行代碼!
# -*- coding: utf-8 -*-
"""
In this example, we create a simple
window in PyQt4.
"""
import sys
from PyQt4 import QtGui
def main():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
上面這些代碼可以在屏幕中顯示出一個(gè)小窗口,大家試一試。接下來我們一句一句地講解這些代碼。
import sys
from PyQt4 import QtGui
這里我們導(dǎo)入了一些必要的組件,其中基本的GUI部件是包含在QtGui模塊中的。
app = QtGui.QApplication(sys.argv)
每一個(gè)PyQt4應(yīng)用都必須創(chuàng)建一個(gè)應(yīng)用(application)對(duì)象,這個(gè)應(yīng)用對(duì)象位于QtGui模塊中。其中的sys.argv參數(shù)是由命令行參數(shù)組成的列表(list)。Python腳本也可以從shell中運(yùn)行,這是我們控制腳本啟動(dòng)的一種方式。【這里暫時(shí)不理解也沒有關(guān)系,影響不大,記住要?jiǎng)?chuàng)建application就行】
w = QtGui.QWidget()
QtGui.QWidget是PyQt4所有用戶接口對(duì)象中的基礎(chǔ)類庫(kù)。我們?cè)谶@里調(diào)用了QtGui.QWidget的默認(rèn)構(gòu)造函數(shù),這個(gè)構(gòu)造沒有父對(duì)象。我們把沒有父對(duì)象的部件(widget)叫做窗口(window)?!具@里對(duì)于父對(duì)象暫時(shí)也不需要理解,理解不到也沒關(guān)系。這句中我們就是創(chuàng)造了一個(gè)沒有父對(duì)象的部件,也就是創(chuàng)建了一個(gè)窗口w?!?/p>
w.resize(250, 150)
很好理解,resize()方法可以調(diào)整部件的大小,我們把它調(diào)整成了250px寬,150px高。
w.move(300, 300)
move()方法將我們的部件移動(dòng)到了屏幕上坐標(biāo)為x=300,y=300的地方?!咀ⅲ浩聊坏淖鴺?biāo)是以左上角為原點(diǎn)的,橫著是x軸,豎著是y軸。】
w.setWindowTitle('Simple')
這里我們?cè)O(shè)定了部件(其實(shí)是個(gè)窗口)的標(biāo)題,標(biāo)題將在標(biāo)題欄中顯示。
w.show()
show()方法使我們創(chuàng)建的部件能夠在屏幕上顯示出來。部件先在內(nèi)存(memory)中被創(chuàng)建,之后再被顯示到屏幕上。
sys.exit(app.exec_())
在顯示了窗口之后,我們進(jìn)入了程序的主循環(huán),并且開始處理時(shí)間。主循環(huán)從窗口接收事件并對(duì)部件進(jìn)行處理。如果我們調(diào)用exit()函數(shù)或者關(guān)閉最主要的部件,主循環(huán)將終止。這里的sys.exit()調(diào)用保證程序完全退出。
值得一提的是exec_()中有一個(gè)下劃線,為什么呢?因?yàn)閑xec是一個(gè)Python關(guān)鍵字,因此加了下劃線。
最后,我們運(yùn)行程序,就會(huì)得到下面這個(gè)簡(jiǎn)單的窗口。
應(yīng)用的圖標(biāo)
應(yīng)用圖標(biāo)是那個(gè)在應(yīng)用窗口左上角顯示的那個(gè)東西。下面這個(gè)例子展示了如何在PyQt4中定制應(yīng)用圖標(biāo)。我們還會(huì)介紹一些新的函數(shù)。
# -*- coding: utf-8 -*-
"""
This example shows an icon
in the titlebar of the window.
"""
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Icon')
self.setWindowIcon(QtGui.QIcon('web.png'))
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
是不是感覺畫風(fēng)突變?那是因?yàn)槲覀冊(cè)诘谝粋€(gè)例子中使用的是過程式編程風(fēng)格。Python語(yǔ)言同時(shí)支持過程式編程和面向?qū)ο缶幊田L(fēng)格,上面這個(gè)例子就是用面向?qū)ο蟮木幊田L(fēng)格編寫的。而你需要知道,用PyQt4編程就以為著面向?qū)ο缶幊?OOP)【為什么要用面向?qū)ο蟮木幊田L(fēng)格?務(wù)必百度一下。】
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
...
在面向?qū)ο蟮木幊讨凶钪匾娜齻€(gè)東西是類(classes),數(shù)據(jù)(data)和方法(methods)。這里我們創(chuàng)建了一個(gè)新的類叫做Example,括號(hào)中的QtGui.QWidget表明這個(gè)Example類是從QtGui.QWidget類繼承來的。這意味著我們?yōu)樾骂悓憳?gòu)造函數(shù)時(shí)需要調(diào)用被繼承類的構(gòu)造函數(shù)。super(Example, self)返回了Example的父對(duì)象(即QtGui.QWidget),接著我們調(diào)用了父對(duì)象的構(gòu)造函數(shù)。注意__init__ 是Python中的構(gòu)造函數(shù)。
self.initUI()
這里我們調(diào)用了一個(gè)我們自己寫的initUI()函數(shù)來創(chuàng)建GUI。
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Icon')
self.setWindowIcon(QtGui.QIcon('web.png'))
由于我們是繼承 QtGui.QWidget類,我們的新類其實(shí)就是一個(gè)部件(widget),有widget的所有方法,這三個(gè)方法就都出自widget。
我們先來介紹一下setGeometry這個(gè)方法,它做了兩件事情:將部件定位并設(shè)定了它的大小【其實(shí)就是resize和move的混合函數(shù)】。前兩個(gè)參數(shù)是部件相對(duì)于父元素的x,y坐標(biāo)【這里其實(shí)是個(gè)窗口(window),沒有父元素記得嗎?所以是屏幕上的x,y坐標(biāo)?!?,后兩個(gè)參數(shù)是部件的寬和高。
接下來說一下setWindowIcon這個(gè)方法,它設(shè)定了應(yīng)用的圖標(biāo)。為了做到這一點(diǎn),我們創(chuàng)建了一個(gè)QtGui.QIon對(duì)象,創(chuàng)建時(shí)的參數(shù)就是我們想要的圖標(biāo)的路徑。
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
啟動(dòng)代碼放在了main函數(shù)中,我們先創(chuàng)建一個(gè)應(yīng)用(application),然后創(chuàng)建我們定義的新類Example的一個(gè)實(shí)例ex。
【注意if __name__ == '__main__' 這個(gè)Python中慣用的定義入口點(diǎn)的方式?!?
最后的效果就是這個(gè)樣子,圖標(biāo)變啦:
顯示提示欄
我們可以讓鼠標(biāo)移到部件上時(shí)顯示提示信息。
# -*- coding: utf-8 -*-
"""
This example shows a tooltip on
a window and a button
"""
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Tooltips')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
在這個(gè)例子中,我們使兩個(gè)部件可以顯示提示信息。
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
這個(gè)方法設(shè)置了一個(gè)用來顯示提示信息的字體,我們使用大小10px的SansSerif字體。
self.setToolTip('This is a <b>QWidget</b> widget')
為了創(chuàng)建一個(gè)提示框,我們調(diào)用setTooltip()這個(gè)方法,我們還可以使用html標(biāo)簽【厲害吧】。
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
這里我們創(chuàng)建了一個(gè)按鈕,并給它加上了提示框(Tooltip)。
btn.resize(btn.sizeHint())
btn.move(50, 50)
我們?cè)O(shè)定了按鈕的大小,位置。其中sizeHint()方法返回了一個(gè)推薦的大小。
最后運(yùn)行出來是這個(gè)樣子的:
關(guān)閉窗口
最顯然的一種關(guān)閉窗口的辦法當(dāng)然是點(diǎn)擊窗口右上角的那個(gè)叉叉。在下一個(gè)例子中,我們將會(huì)展示怎樣程序性地關(guān)閉窗口,比如設(shè)置一個(gè)有關(guān)閉窗口作用的按鈕。我們還會(huì)簡(jiǎn)單地接觸到信號(hào)(與)槽系統(tǒng)(signals and slots)。
我們?cè)诶又幸褂玫腝tGui.QPushButton的構(gòu)造函數(shù)原型是這樣的:
QPushButton(string text, QWidget parent = None)
其中text參數(shù)是按鈕上顯示的文字。parent參數(shù)是部件的父對(duì)象,在這里就是我們要把按鈕放在什么上,本例中是一個(gè)QtGui.QWidget【其實(shí)是一個(gè)窗口(window)】。
# -*- coding: utf-8 -*-
"""
This program creates a quit
button. When we press the button,
the application terminates.
"""
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
qbtn = QtGui.QPushButton('Quit', self)
qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
在本例中,我們創(chuàng)造了一個(gè)有退出作用的quit按鈕,只要鼠標(biāo)點(diǎn)擊這個(gè)按鈕,應(yīng)用就終止運(yùn)行了。
from PyQt4 import QtGui, QtCore
這里我們需要QtCore中的一個(gè)對(duì)象,所以需要額外引入這個(gè)模塊。
qbtn = QtGui.QPushButton('Quit', self)
這里我們創(chuàng)造了一個(gè)按鈕(push button),它是QtGui.QPushButton類的一個(gè)實(shí)例。第一個(gè)參數(shù)是按鈕上的文字,第二個(gè)參數(shù)是父對(duì)象,這里就是我們創(chuàng)建的Example了,也就是self,它繼承自QtGui.QWidget類【Example沒有父對(duì)象,是一個(gè)窗口(window),記得嗎】。
qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
PyQt4中的事件處理系統(tǒng)是由信號(hào)槽機(jī)制(signals and slots)實(shí)現(xiàn)的。如果我們點(diǎn)擊了這個(gè)按鈕,就會(huì)發(fā)出“clicked”這個(gè)信號(hào)。QtCore.QCoreApplication這個(gè)東西包含了程序的主循環(huán),它處理和分派所有的事件,而instance()方法返回的是目前的實(shí)例(insatnce)。注意到QtCore.QCoreApplication隨著QtGui.QApplication的創(chuàng)建而創(chuàng)建,而由于我們這里用connect()函數(shù)將“clicked”事件和可以終止應(yīng)用的quit()函數(shù)聯(lián)系(connect)在了一起,所以點(diǎn)擊按鈕,應(yīng)用終止。這種交流在兩個(gè)對(duì)象之間完成:發(fā)送者和接受者,其中發(fā)送者是按鈕,接受者是應(yīng)用本身?!具@里只要大家對(duì)connect方法有個(gè)感性的認(rèn)識(shí)就可以了】
運(yùn)行出來就是這個(gè)樣子:
消息框(Message Box)
默認(rèn)情況下,如果我們點(diǎn)擊了程序右上角的叉叉,
QtGui.QWidget部件就會(huì)被關(guān)閉。但有時(shí)我們想要改變這種默認(rèn)的行為,比如說,如果我們?cè)诰庉嬕恍〇|西,關(guān)閉窗口時(shí)我們想要彈出一個(gè)消息框來確認(rèn)是否退出。
# -*- coding: utf-8 -*-
"""
This program shows a confirmation
message box when we click on the close
button of the application window.
"""
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Message box')
self.show()
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
根據(jù)類定義,如果關(guān)閉QtGui.QWidget,QtGui.QCloseEvent將會(huì)執(zhí)行。所以為了達(dá)到我們的目的,我們需要重新定制closeEvent()這個(gè)事件句柄(event handler)如下。
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
這里我們?cè)O(shè)定顯示一個(gè)有兩個(gè)選項(xiàng)(yes & no)的消息框(message box)。QtGui.QMessageBox.question()方法的第二個(gè)參數(shù)是出現(xiàn)在標(biāo)題欄的標(biāo)題,第三個(gè)參數(shù)是消息框顯示的對(duì)話內(nèi)容,第四個(gè)參數(shù)是出現(xiàn)在消息框的按鈕的組合【用或( | )連接】,最后一個(gè)參數(shù)是默認(rèn)按鈕,即消息框剛跳出來的時(shí)候按enter鍵就可以執(zhí)行的按鈕。這里我們將函數(shù)的返回值存儲(chǔ)在了reply這個(gè)變量中。
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
這里我們測(cè)試函數(shù)的返回值。如果我們點(diǎn)擊了Yes按鈕,close這個(gè)事件將會(huì)被接受(accept),部件關(guān)閉、應(yīng)用結(jié)束;否則close這個(gè)事件將會(huì)被忽視(ignore),程序繼續(xù)執(zhí)行。
運(yùn)行出來是這個(gè)樣子:
使窗口顯示在屏幕中間
下面這個(gè)腳本實(shí)現(xiàn)了讓窗口在屏幕的中央顯示。
# -*- coding: utf-8 -*-
"""
This program centers a window
on the screen.
"""
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.resize(250, 150)
self.center()
self.setWindowTitle('Center')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
- 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
- 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
其中QtGui.QDesktopWidget這個(gè)類提供了用戶桌面的信息,包括屏幕大小。
self.center()
我們調(diào)用一個(gè)自己寫的center()方法來實(shí)現(xiàn)窗口在屏幕中央顯示。
qr = self.frameGeometry()
這里我們用frameGeometry方法得到了主窗口的矩形框架qr。
cp = QtGui.QDesktopWidget().availableGeometry().center()
我們調(diào)用這些方法來得到屏幕分辨率,并最終得到屏幕中間點(diǎn)的坐標(biāo)cp。
qr.moveCenter(cp)
這里我們將矩形框架移至屏幕正中央,大小不變。
self.move(qr.topLeft())
最后我們將應(yīng)用窗口移至矩形框架的左上角點(diǎn),這樣應(yīng)用窗口就位于屏幕的中央了【注意部件的move都是左上角移動(dòng)到某點(diǎn)】。
好了,這就是本節(jié)全部的內(nèi)容了,我們已經(jīng)掌握了一些基本的方法!
|