用PyQt5寫的第一個程序
在這篇PyQt5教程中,我們可以學習一些PyQt5的基礎應用。
簡單的例子
這是一個顯示一個小窗口的簡單例子。我們可以做許多這樣的窗口。我們可以調整它的窗口尺寸,最大化或最小化這個窗口。這些需求需要碼很多代碼。但一些人已經寫好了這些功能實現。因為這些需求在很多應用中重復出現了,在這里我們不需要重新寫這些代碼。PyQt5是一個高級工具套件,為我們封裝了很多復雜功能的實現代碼,我們可以更加簡單的通過函數去實現這些功能。如果我們是在一個低級工具套件中寫代碼的話,下面例子的代碼很有可能需要數百行來實現。
1 #!/usr/bin/python3 2 # -*- coding: utf-8 -*- 3 4 """ 5 ZetCode PyQt5 教程 6 在這個例子中, 我們用PyQt5創建了一個簡單的窗口。 7 8 作者: Jan Bodnar 9 網站: zetcode.com 10 最后一次編輯: January 2015 11 """ 12 13 import sys 14 from PyQt5.QtWidgets import QApplication, QWidget 15 16 17 if __name__ == '__main__': 18 19 app = QApplication(sys.argv) 20 21 w = QWidget() 22 w.resize(250, 150) 23 w.move(300, 300) 24 w.setWindowTitle('Simple') 25 w.show() 26 27 sys.exit(app.exec_())
上面的代碼示例會在屏幕上顯示一個小窗口。
import sys from PyQt5.QtWidgets import QApplication, QWidget
這里我們進行了一些必要模塊的導入。最基礎的widget組件位於PyQt5.QtWidget模塊中
app = QApplication(sys.argv)
所有的PyQt5應用必須創建一個應用(Application)對象。sys.argv參數是一個來自命令行的參數列表。Python腳本可以在shell中運行。這是我們用來控制我們應用啟動的一種方法。
w = QWidget()
Qwidget組件是PyQt5中所有用戶界面類的基礎類。我們給QWidget提供了默認的構造方法。默認構造方法沒有父類。沒有父類的widget組件將被作為窗口使用。
w.resize(250, 150)
resize()方法調整了widget組件的大小。它現在是250px寬,150px高。
w.move(300, 300)
move()方法移動widget組件到一個位置,這個位置是屏幕上x=300,y=300的坐標。
w.setWindowTitle('Simple')
這里我們設置了我們窗口的標題。這個標題顯示在標題欄中。
w.show()
show()方法在屏幕上顯示出widget。一個widget對象在這里第一次被在內存中創建,並且之后在屏幕上顯示。
sys.exit(app.exec_())
最后,應用進入主循環。在這個地方,事件處理開始執行。主循環用於接收來自窗口觸發的事件,並且轉發他們到widget應用上處理。如果我們調用exit()方法或主widget組件被銷毀,主循環將退出。sys.exit()方法確保一個不留垃圾的退出。系統環境將會被通知應用是怎樣被結束的。
exec_()方法有一個下划線。因為exec是Python保留關鍵字。因此,用exec_()來代替。
Figure: Simple
一個簡單的應用圖標
應用圖標是一個常常顯示在標題欄左上方角落的小圖片。在下面的例子里,我們將展示我們如何在PyQt5中顯示應用圖標。我們也將介紹一些新方法的使用。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This example shows an icon
in the titlebar of the window.
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
上述的例子使用傳統的面向過程的代碼風格。Python編程語言提供面向過程和面向對象的代碼風格。PyQt5編程意味着就是面向對象的編程。
class Example(QWidget):
def __init__(self):
super().__init__()
...
在面向對象編程中有三個重要的東西,分別是類,數據和方法。這里我們創建了一個新類叫做Example。Example類繼承自QWidget類。這意味着我們調用了兩個構造方法:第一個是Example類的構造方法,第二個是被繼承類的構造方法。super()方法返回了Example類的父類對象,並且我們調用了父類的構造方法。__init__()方法是Python語言中的構造方法。
self.initUI()
GUI的創建授予initUI()方法完成。
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
三個方法都繼承自QWidgets類。setGeometry()做了兩件事:將窗口在屏幕上顯示,並設置了它的尺寸。setGeometry()方法的前兩個參數定位了窗口的x軸和y軸位置。第三個參數是定義窗口的寬度,第四個參數是定義窗口的高度。事實上,這是將resize()和move()方法融合在一個方法內。為了做好這個例子,我們創建了一個QIcon對象。QIcon對象接收一個我們要顯示的圖片路徑作為參數。
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
應用和example對象被創建。主循環被啟動。
Figure: Icon
顯示一個提示文本
我們可以給我們的任何widget組件提供氣泡幫助提示框。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This example shows a tooltip on
a window and a button.
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import (QWidget, QToolTip,
QPushButton, QApplication)
from PyQt5.QtGui import QFont
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(50, 50)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Tooltips')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在這個例子中,我們為兩個PyQt5組件顯示了提示框。
QToolTip.setFont(QFont('SansSerif', 10))
這個靜態方法設置了用於提示框的字體。我們使用10px大小的SansSerif字體。
self.setToolTip('This is a <b>QWidget</b> widget')
為了創建提示框,我們調用了setTooltip()方法。我們可以在提示框中使用富文本格式。
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
我們創建了一個按鈕組件並且為它設置一個提示框。
btn.resize(btn.sizeHint()) btn.move(50, 50)
這里改變了按鈕的大小,並移動了在窗口上的位置。setHint()方法給了按鈕一個推薦的大小。
Figure: Tooltips
關閉窗口
明顯的關閉窗口的方法是點擊標題欄的X標記。在下面的例子中,我們將展示怎么通過程序來關閉我們的窗口。我們將簡單的觸及信號和槽機制。
QPushButton(string text, QWidget parent = None)
text參數是將顯示在按鈕中的內容。parent參數是一個用來放置我們按鈕的組件。在我們的例子中將會是QWidget組件。一個應用的組件是分層結構的。在這個分層內,大多數組件都有父類。沒有父類的組件是頂級窗口。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This program creates a quit
button. When we press the button,
the application terminates.
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
qbtn = QPushButton('Quit', self)
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在這個例子中,我們創建一個退出按鈕,一旦按下按鈕,應用將會結束。
from PyQt5.QtCore import QCoreApplication
我們需要一個來自QtCore的對象模塊。
qbtn = QPushButton('Quit', self)
我們創建了一個按鈕。按鈕是一個QPushButton類的實例。構造方法的第一個參數是顯示在button上的標簽文本。第二個參數是父組件。父組件是Example組件,它繼承了QWiget類。
qbtn.clicked.connect(QCoreApplication.instance().quit)
在PyQt5中,事件處理系統由信號&槽機制建立。如果我們點擊了按鈕,信號clicked被發送。槽可以是Qt內置的槽或Python 的一個方法調用。QCoreApplication類包含了主事件循環;它處理和轉發所有事件。instance()方法給我們返回一個實例化對象。注意QCoreAppli類由QApplication創建。點擊信號連接到quit()方法,將結束應用。事件通信在兩個對象之間進行:發送者和接受者。發送者是按鈕,接受者是應用對象。
Figure: Quit button
Message Box
默認的,如果我們點擊了標題欄上的x按鈕,QWidget會被關閉。又是我們希望修改這個默認動作。舉個例子,如果我們有個文件在編輯器內打開,並且我們對這個文件做了一些修改。 我們顯示一個message box來確認這個動作。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This program shows a confirmation
message box when we click on the close
button of the application window.
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Message box')
self.show()
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
如果我們關閉一個QWidget,QCloseEvent類事件將被生成。要修改組件動作我們需要重新實現closeEvent()事件處理方法。
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
我們現實一個帶兩個按鈕的message box:YES和No按鈕。代碼中第一個字符串的內容被顯示在標題欄上。第二個字符串是對話框上顯示的文本。第三個參數指定了顯示在對話框上的按鈕集合。最后一個參數是默認選中的按鈕。這個按鈕一開始就獲得焦點。返回值被儲存在reply變量中。
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
在這里我們測試一下返回值。代碼邏輯是如果我們點擊Yes按鈕,我們接收到的事件關閉事件,這將導致了組件的關閉和應用的結束。否則不是點擊Yes按鈕的話我們將忽略將關閉事件。
Figure: Message box
屏幕上的居中窗口
下面的腳本展示我們如何把窗口居中顯示到桌面窗口。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This program centers a window
on the screen.
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(250, 150)
self.center()
self.setWindowTitle('Center')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
QtGui.QDesktopWidget類提供了我們桌面窗口的信息,包含了屏幕尺寸。
self.center()
將窗口居中放置的代碼在自定義的center()方法中。
qr = self.frameGeometry()
我們獲得主窗口的一個矩形特定幾何圖形。這包含了窗口的框架。
cp = QDesktopWidget().availableGeometry().center()
我們算出相對於顯示器的絕對值。並且從這個絕對值中,我們獲得了屏幕中心點。
qr.moveCenter(cp)
我們的矩形已經設置好了它的寬和高。現在我們把矩形的中心設置到屏幕的中間去。矩形的大小並不會改變。
self.move(qr.topLeft())
