用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())