[TOC]python
注:原創不易,轉載請務必註明原做者和出處,感謝支持!web
本文的主要內容:PyQt中的窗口部件:QMainWindow,QWidget,QDialog。app
上述三種窗口部件都是用來建立窗口的,能夠直接使用,也能夠繼承後再使用。它們的異同以下:工具
三者之間的繼承關係以下圖:佈局
何爲頂層窗口?若是一個窗口包含一個或多個窗口,那麼這個窗口就是父窗口,被包含的窗口則是子窗口。沒有父窗口的窗口則是頂層窗口。QMainWindow就是一個頂層窗口,它能夠包含不少界面元素,如菜單欄、工具欄、狀態欄、子窗口等等。QMainWindow元素佈局以下圖(來自Qt文檔)。 測試
QMainWindow經常使用的方法有:字體
方法 | 描述 |
---|---|
addToolBar() | 添加工具欄 |
centralWidget() | 返回窗口中心的控件,未設置時返回NULL |
menuBar() | 返回主窗口的菜單欄 |
setCentralWidget() | 設置窗口中心的控件 |
setStatusBar() | 設置狀態欄 |
statusBar() | 得到狀態欄對象後,調用狀態欄對象的showMessage()方法顯示狀態欄信息 |
什麼也不設置的「空白」QMainWindow,代碼及效果圖以下所示。ui
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QApplication, QMainWindow if __name__ == '__main__': app = QApplication(sys.argv) w = QMainWindow() w.show() sys.exit(app.exec_())
咱們經過一個仿照Windows系統的中記事本程序的小實例來了解QMainWindow的使用。url
# text-editor.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import webbrowser from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication, \ QMessageBox, QFileDialog, QDesktopWidget class TextEditor(QMainWindow): ''' TextEditor : 一個簡單的記事本程序 ''' def __init__(self): super().__init__() self.copiedText = '' self.initUI() # 初始化窗口界面 def initUI(self): # 設置中心窗口部件爲QTextEdit self.textEdit = QTextEdit() self.setCentralWidget(self.textEdit) self.textEdit.setText('') # 定義一系列的Action # 退出 exitAction = QAction(QIcon('./images/exit.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) # 新建 newAction = QAction(QIcon('./images/new.png'), 'New', self) newAction.setShortcut('Ctrl+N') newAction.setStatusTip('New application') newAction.triggered.connect(self.__init__) # 打開 openAction = QAction(QIcon('./images/open.png'), 'Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open Application') openAction.triggered.connect(self.open) # 保存 saveAction = QAction(QIcon('./images/save.png'), 'Save', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('Save Application') saveAction.triggered.connect(self.save) # 撤銷 undoAction = QAction(QIcon('./images/undo.png'), 'Undo', self) undoAction.setShortcut('Ctrl+Z') undoAction.setStatusTip('Undo') undoAction.triggered.connect(self.textEdit.undo) # 重作 redoAction = QAction(QIcon('./images/redo.png'), 'Redo', self) redoAction.setShortcut('Ctrl+Y') redoAction.setStatusTip('Redo') redoAction.triggered.connect(self.textEdit.redo) # 拷貝 copyAction = QAction(QIcon('./images/copy.png'), 'Copy', self) copyAction.setShortcut('Ctrl+C') copyAction.setStatusTip('Copy') copyAction.triggered.connect(self.copy) # 粘貼 pasteAction = QAction(QIcon('./images/paste.png'), 'Paste', self) pasteAction.setShortcut('Ctrl+V') pasteAction.setStatusTip('Paste') pasteAction.triggered.connect(self.paste) # 剪切 cutAction = QAction(QIcon('./images/cut.png'), 'Cut', self) cutAction.setShortcut('Ctrl+X') cutAction.setStatusTip('Cut') cutAction.triggered.connect(self.cut) # 關於 aboutAction = QAction(QIcon('./images/about.png'), 'About', self) aboutAction.setStatusTip('About') aboutAction.triggered.connect(self.about) # 添加菜單 # 對於菜單欄,注意menuBar,menu和action三者之間的關係 # 首先取得QMainWindow自帶的menuBar:menubar = self.menuBar() # 而後在menuBar裏添加Menu:fileMenu = menubar.addMenu('&File') # 最後在Menu裏添加Action:fileMenu.addAction(newAction) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(saveAction) fileMenu.addAction(exitAction) editMenu = menubar.addMenu('&Edit') editMenu.addAction(undoAction) editMenu.addAction(redoAction) editMenu.addAction(cutAction) editMenu.addAction(copyAction) editMenu.addAction(pasteAction) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(aboutAction) # 添加工具欄 # 對於工具欄,一樣注意ToolBar和Action之間的關係 # 首先在QMainWindow中添加ToolBar:tb1 = self.addToolBar('File') # 而後在ToolBar中添加Action:tb1.addAction(newAction) tb1 = self.addToolBar('File') tb1.addAction(newAction) tb1.addAction(openAction) tb1.addAction(saveAction) tb2 = self.addToolBar('Edit') tb2.addAction(undoAction) tb2.addAction(redoAction) tb2.addAction(cutAction) tb2.addAction(copyAction) tb2.addAction(pasteAction) tb3 = self.addToolBar('Exit') tb3.addAction(exitAction) # 添加狀態欄,以顯示每一個Action的StatusTip信息 self.statusBar() self.setGeometry(0, 0, 600, 600) self.setWindowTitle('Text Editor') self.setWindowIcon(QIcon('./images/text.png')) self.center() self.show() # 主窗口居中顯示 def center(self): screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) # 定義Action對應的觸發事件,在觸發事件中調用self.statusBar()顯示提示信息 # 重寫closeEvent def closeEvent(self, event): reply = QMessageBox.question(self, 'Confirm', \ 'Are you sure to quit without saving ?', \ QMessageBox.Yes | QMessageBox.No, \ QMessageBox.No) if reply == QMessageBox.Yes: self.statusBar().showMessage('Quiting...') event.accept() else: event.ignore() self.save() event.accept() # open def open(self): self.statusBar().showMessage('Open Text Files') fname = QFileDialog.getOpenFileName(self, 'Open file', '/home') self.statusBar().showMessage('Open File') if fname[0]: f = open(fname[0], 'r') with f: data = f.read() self.textEdit.setText(data) # save def save(self): self.statusBar().showMessage('Add extension to file name') fname = QFileDialog.getSaveFileName(self, 'Save File') if (fname[0]): data = self.textEdit.toPlainText() f = open(fname[0], 'w') f.write(data) f.close() # copy def copy(self): cursor = self.textEdit.textCursor() textSelected = cursor.selectedText() self.copiedText = textSelected # paste def paste(self): self.textEdit.append(self.copiedText) # cut def cut(self): cursor = self.textEdit.textCursor() textSelected = cursor.selectedText() self.copiedText = textSelected self.textEdit.cut() # about def about(self): url = 'https://en.wikipedia.org/wiki/Text_editor' self.statusBar().showMessage('Loading url...') webbrowser.open(url) if __name__ == '__main__': app = QApplication(sys.argv) w = TextEditor() sys.exit(app.exec_())
QWidget類是全部用戶界面對象的基類,全部的窗口和控件都直接或間接繼承自QWidget類。QWidget類相關的方法。spa
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QToolTip from PyQt5.QtGui import QIcon, QFont if __name__ == '__main__': app = QApplication(sys.argv) w = QWidget() btn = QPushButton(w) btn.setText('Button') btn.move(20, 20) w.resize(300, 200) w.move(250, 200) w.setWindowTitle('QWidget') # setWindowIcon()用於設置應用程序圖標 w.setWindowIcon(QIcon('./icon.png')) # setFont()爲QToolTip設定字體 QToolTip.setFont(QFont('Monospace Regular', 20)) w.setToolTip('這是一個<b>氣泡提示!</b>') w.show() print('QWidget:') print('w.x() = %d' % w.x()) print('w.y() = %d' % w.y()) print('w.width() = %d' % w.width()) print('w.height() = %d' % w.height()) print('QWidget.geometry') print('w.geometry().x() = %d' % w.geometry().x()) print('w.geometry().y() = %d' % w.geometry().y()) print('w.geometry().width() = %d' % w.geometry().width()) print('w.geometry().height() = %d' % w.geometry().height()) sys.exit(app.exec_())
腳本輸出爲:
QWidget: w.x() = 250 w.y() = 200 w.width() = 300 w.height() = 200 QWidget.geometry w.geometry().x() = 250 w.geometry().y() = 200 w.geometry().width() = 300 w.geometry().height() = 200
QDialog的各類子類提供了各類標準對話框,好比QMessageBox, QFileDialog, QInputDialog, QFontDialog等等。它們之間的繼承關係以下圖所示。
QDialog類中經常使用方法:
方法 | 描述 |
---|---|
setWindowTitle() | 設置對話框標題 |
setWindowModality() | 設置窗口模態。取值以下: Qt.NonModal - 非模態 Qt.WindowModal - 窗口模態 Qt.ApplicationModal - 應用程序模態 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog from PyQt5.QtCore import Qt class DialogWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('Dialog') self.resize(350, 300) self.btn = QPushButton(self) self.btn.setText('彈出對話框') self.btn.move(50, 50) self.btn.clicked.connect(self.showDialog) self.show() def showDialog(self): dialog = QDialog() btn = QPushButton('ok', dialog) btn.move(50, 50) dialog.setWindowTitle('Dialog') dialog.setWindowModality(Qt.ApplicationModal) dialog.exec_() if __name__ == '__main__': app = QApplication(sys.argv) w = DialogWindow() sys.exit(app.exec_())
QMessageBox是一種通用的彈出式對話框,用於顯示消息,容許用戶經過單擊不一樣的標準按鈕對消息進行反饋。每一個標準按鈕都有一個預約義的文本、角色和十六進制數。QMessageBox類提供了許多經常使用的彈出式對話框,好比提示、警告、錯誤、詢問、關於等對話框。這些不一樣類型的QMessageBox對話框只是顯示時得圖標不一樣,其餘功能是同樣的。QMessageBox類中經常使用的方法有:
方法 | 描述 |
---|---|
information(QWidget parent, title, text, buttons, defaultButton) | parent:父窗口 title:對話框標題 text:對話框文本 buttons:多個標準按鈕 defaultButton:默認選中的標準按鈕 |
question(QWidget parent, title, text, buttons, defaultButton) | 問答對話框 |
warning(QWidget parent, title, text, buttons, defaultButton) | 警告對話框 |
critical(QWidget parent, title, text, buttons, defaultButton) | 嚴重錯誤對話框 |
about(QWidget parent, title, text) | 關於對話框 |
setTitle() | 設置標題 |
setText() | 設置消息正文 |
setIcon() | 設置對話框的圖片 |
QMessageBox中的標準按鈕類型有:
類型 | 描述 |
---|---|
QMessageBox.Ok | 肯定 |
QMessageBox.Cancel | 取消 |
QMessageBox.Yes | 是 |
QMessageBox.No | 否 |
QMessageBox.Abort | 終止 |
QMessageBox.Retry | 重試 |
QMessageBox.Ignore | 忽略 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QApplication, QMessageBox, QWidget, QVBoxLayout, \ QPushButton class MessageBoxWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): vbox = QVBoxLayout() btn = QPushButton('點擊彈出消息框') btn.clicked.connect(self.showMessageBox) vbox.addWidget(btn) self.setLayout(vbox) self.setWindowTitle('QMessageBox') self.resize(300, 200) self.show() def showMessageBox(self): QMessageBox.question(self, '標題', '正文內容', QMessageBox.Yes | \ QMessageBox.No, QMessageBox.Yes) QMessageBox.warning(self, '標題', '正文內容', QMessageBox.Yes | \ QMessageBox.No, QMessageBox.Yes) QMessageBox.critical(self, '標題', '正文內容', QMessageBox.Yes | \ QMessageBox.No, QMessageBox.Yes) QMessageBox.about(self, '標題', '正文內容') if __name__ == '__main__': app = QApplication(sys.argv) w = MessageBoxWindow() sys.exit(app.exec_())
QInputDialog控件是一個標準對話框,由一個文本框和兩個按鈕(OK和Cancel)組成。當用戶單擊OK按鈕後,在父窗口能夠接受經過QInputDialog控件輸入的信息。在QInputDialog控件中能夠輸入數字、字符串或者列表中的選擇。標籤用於提示必要的信息。QInputDialog類經常使用的方法有:
方法 | 描述 |
---|---|
getInt() | 從控件中獲取標準整型輸入 |
getDouble() | 從控件中獲取標準浮點數輸入 |
getText() | 從控件中獲取標準字符串輸入 |
getItem() | 從控件中獲取列表裏的選項輸入 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QWidget, QFormLayout, QPushButton, QLineEdit, \ QInputDialog, QApplication class InputDialogWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): layout = QFormLayout() self.btn1 = QPushButton('得到列表裏的選項') self.btn1.clicked.connect(self.getItem) self.le1 = QLineEdit() layout.addRow(self.btn1, self.le1) self.btn2 = QPushButton('得到字符串') self.btn2.clicked.connect(self.getText) self.le2 = QLineEdit() layout.addRow(self.btn2, self.le2) self.btn3 = QPushButton('得到整數') self.btn3.clicked.connect(self.getInt) self.le3 = QLineEdit() layout.addRow(self.btn3, self.le3) self.setLayout(layout) self.setWindowTitle('QInputDialog') self.show() def getItem(self): items = ('C', 'C++', 'Java', 'Python') item, ok = QInputDialog.getItem(self, 'Select Input Dialog', \ '語言列表', items, 0, False) if ok and item: self.le1.setText(item) def getText(self): text, ok = QInputDialog.getText(self, 'Text Input Dialog', \ '輸入姓名:') if ok: self.le2.setText(str(text)) def getInt(self): num, ok = QInputDialog.getInt(self, 'Integer Input Dialog', \ '輸入數字:') if ok: self.le3.setText(str(num)) if __name__ == '__main__': app = QApplication(sys.argv) w = InputDialogWindow() sys.exit(app.exec_())
QFontDialog控件是一個經常使用的字體選擇對話框,可讓用戶選擇顯示文本的字體樣式、字號大小和格式。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QWidget, QVBoxLayout, QFontDialog, QApplication, \ QPushButton, QLabel class FontDialogWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): layout = QVBoxLayout() self.btn = QPushButton('選擇字體') self.btn.clicked.connect(self.chooseFont) self.lb = QLabel('Hello, 測試字體例子') layout.addWidget(self.btn) layout.addWidget(self.lb) self.setLayout(layout) self.setWindowTitle('FontDialog') self.show() def chooseFont(self): font, ok = QFontDialog.getFont() if ok: self.lb.setFont(font) if __name__ == '__main__': app = QApplication(sys.argv) w = FontDialogWindow() sys.exit(app.exec_())
QFileDialog是用於打開和保存文件的標準對話框。QFileDialog在打開文件時使用了文件過濾器,用於顯示指定擴展名的文件。也能夠設置使用QFileDialog打開文件時的起始目錄和指定擴展名的文件。QFileDialog類的經常使用方法有:
方法 | 描述 |
---|---|
getOpenFileName() | 返回用戶所選擇文件的名稱,並打開該文件 |
getSaveFileName() | 使用用戶選擇的文件名並保存文件 |
setFileMode() | 能夠選擇的文件類型,可選枚舉常量有: QFileDialog.AnyFile:任何文件 QFileDialog.ExistingFile:已存在的文件 QFileDialog.Directory:文件目錄 QFileDialog.ExistingFiles:已存在的多個文件 |
setFilter() | 設置過濾器,只顯示過濾器容許的文件類型 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, \ QLabel, QTextEdit, QFileDialog from PyQt5.QtCore import QDir from PyQt5.QtGui import QPixmap class FileDialogWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): layout = QVBoxLayout() self.btn1 = QPushButton('加載圖片') self.btn1.clicked.connect(self.chooseImage) self.lb = QLabel() layout.addWidget(self.btn1) layout.addWidget(self.lb) self.btn2 = QPushButton('加載文本文件') self.btn2.clicked.connect(self.chooseTextFile) self.content = QTextEdit() layout.addWidget(self.btn2) layout.addWidget(self.content) self.setLayout(layout) self.setWindowTitle('FileDialg') self.show() def chooseImage(self): fname, _ = QFileDialog.getOpenFileName(self, 'Open file', '/home', \ "Image files (*.jpg *.png *.gif)") self.lb.setPixmap(QPixmap(fname)) def chooseTextFile(self): dlg = QFileDialog() dlg.setFileMode(QFileDialog.AnyFile) dlg.setFilter(QDir.Files) if dlg.exec_(): fname = dlg.selectedFiles() f = open(fname[0], 'r') with f: data = f.read() self.content.setText(data) if __name__ == '__main__': app = QApplication(sys.argv) w = FileDialogWindow() sys.exit(app.exec_())