iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0

QMessageBox 是 PyQt5 裡的對話視窗元件,通常會搭配按鈕或選單,開啟對話視窗與使用者互動,這篇教學會介紹如何在 PyQt5 視窗裡加入 QMessageBox 對話視窗,並透過對話視窗進行開啟檔案或關閉視窗等基本互動應用。

原文參考:QMessageBox 對話視窗

因為 Google Colab 不支援 PyQt5,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。

Python 教學 - QMessageBox 對話視窗

加入 QMessageBox 對話視窗

建立 PyQt5 視窗物件後,先透過 QtWidgets.QPushButton(widget) 方法加入按鈕,使用 clicked.connect() 綁定點擊按鈕時的函式,點擊按鈕時使用 QtWidgets.QMessageBox() 方法建立對話視窗,接著使用 information() 方法,就能開啟資訊通知的對話視窗

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 300)

def show():
    mbox = QtWidgets.QMessageBox(Form)       # 加入對話視窗
    mbox.information(Form, 'info', 'hello')  # 開啟資訊通知的對話視窗,標題 info,內容 hello

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('彈出視窗')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

QMessageBox 的類型

QMessageBox 預設提供下列幾種預設類型 ( 四種方法都包含第四個參數 ButtonRole,通常不會設定,直接使用預設值 ):

方法 參數 說明
information() parent, title, text 資訊通知對話視窗。
question() parent, title, text 二選一問題對話視窗。
warning() parent, title, text 警告視窗。
critical() parent, title, text 關鍵警告視窗

下方的程式碼執行後,畫面中會有四顆按鈕,點擊後分別會出現不同的對話視窗。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show(n):
    mbox = QtWidgets.QMessageBox(Form)
    if n==1:
      mbox.information(Form, 'information', 'information...')
    elif n == 2:
      mbox.question(Form, 'question', 'question?')
    elif n == 3:
      mbox.warning(Form, 'warning', 'warning!!!')
    elif n == 4:
      mbox.critical(Form, 'critical', 'critical!!!')

btn1 = QtWidgets.QPushButton(Form)
btn1.move(10, 10)
btn1.setText('information')
btn1.clicked.connect(lambda: show(1))

btn2 = QtWidgets.QPushButton(Form)
btn2.move(10, 40)
btn2.setText('question')
btn2.clicked.connect(lambda: show(2))

btn3 = QtWidgets.QPushButton(Form)
btn3.move(10, 70)
btn3.setText('waring')
btn3.clicked.connect(lambda: show(3))

btn4 = QtWidgets.QPushButton(Form)
btn4.move(10, 100)
btn4.setText('critical')
btn4.clicked.connect(lambda: show(4))

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

自訂 QMessageBox 對話視窗

除了四種預設類型,QMessageBox 也提供「自訂對話視窗」的功能,自訂視窗的基本寫法先透過 setText() 方法設定通知的文字,接著使用 exec() 方法執行,下方的程式碼執行後,點擊按鈕會出現一個沒有 icon 的單純通知視窗。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')   # 通知文字
    mbox.exec()             # 執行

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

自訂對話視窗預設沒有 icon 圖示,使用 setIcon() 方法可以添加 icon 圖示,QMessageBox 提供四種預設 icon 圖示,直接輸入代號就會出現對應的 icon 圖示。

圖示 代號 說明
QMessageBox.Information 1 資訊。
QMessageBox.Warning 2 警告。
QMessageBox.Critical 3 重要警告。
QMessageBox.Question 4 問題。

下方的程式碼執行後,點擊按鈕就會出現帶有問號 icon 圖示的對話視窗。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello?')
    mbox.setIcon(4)          # 加入問號 icon
    # mbox.setIcon(QtWidgets.QMessageBox.Question)  # 效果等同這一段
    mbox.exec()

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

自訂 QMessageBox 按鈕

使用 addButton() 方法可以在自訂對話視窗中增加按鈕,QMessageBox 預設提供下列幾種常用的按鈕,預設按鈕有其固定位置,無法指定位置。

按鈕 呈現文字 對應 ButtonRole
QMessageBox.Ok Ok AcceptRole
QMessageBox.Open Open AcceptRole
QMessageBox.Save Save AcceptRole
QMessageBox.Cancel Save RejectRole
QMessageBox.Close Close RejectRole
QMessageBox.Discard Don't Save DestructiveRole
QMessageBox.Apply Apply AcceptRole
QMessageBox.Reset Reset ResetRole
QMessageBox.RestoreDefaults Restore Defaults ResetRole
QMessageBox.Help Help HelpRole
QMessageBox.SaveAll Save All AcceptRole
QMessageBox.Yes Yes YesRole
QMessageBox.YesToAll Yes to All YesRole
QMessageBox.No No NoRole
QMessageBox.NoToAll No to All NoRole
QMessageBox.Abort Abort RejectRole
QMessageBox.Retry Retry AcceptRole
QMessageBox.Ignore Ignore AcceptRole
QMessageBox.NoButton 停用 Button

下方的程式碼執行後,點擊按鈕會出現帶有四個按鈕的對話視窗。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    mbox.addButton(QtWidgets.QMessageBox.Ok)
    mbox.addButton(QtWidgets.QMessageBox.Open)
    mbox.addButton(QtWidgets.QMessageBox.Save)
    mbox.addButton(QtWidgets.QMessageBox.Cancel)
    mbox.exec()

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

如果是預設的按鈕,也可以使用 setStandardButtons() 方法添加按鈕,添加的寫法如下方程式碼所示 ( 同時使用 setDefaultButton() 方法設定預設按鈕 ):

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    # 添加三顆按鈕
    mbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Cancel)
    # 設定預設按鈕
    mbox.setDefaultButton(QtWidgets.QMessageBox.Yes)
    mbox.exec()

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

如果不想用預設按鈕文字,也可以直接輸入按鈕文字,但如果要自訂文字,需要包含第二個參數 ButtonRole,常用的 ButtonRole 如下:

ButtonRole 代碼 說明
QMessageBox.ButtonRole.InvalidRole -1 按鈕無效。
QMessageBox.ButtonRole.AcceptRole 0 接受。
QMessageBox.ButtonRole.RejectRole 1 拒絕。
QMessageBox.ButtonRole.DestructiveRole 2 破壞性更改。
QMessageBox.ButtonRole.ActionRole 3 發生行為。
QMessageBox.ButtonRole.HelpRole 4 請求幫助。
QMessageBox.ButtonRole.YesRole 5 等同「是」。
QMessageBox.ButtonRole.NoRole 6 等同「否」。
QMessageBox.ButtonRole.ApplyRole 7 同意。
QMessageBox.ButtonRole.ResetRole 8 設為預設值。

下方的程式碼執行後,點擊按鈕會出現一個帶有三顆自訂文字按鈕的對話視窗。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    mbox.addButton('Apple', 3)
    mbox.addButton('Banana', 3)
    mbox.addButton('Orange', 3)
    mbox.exec()

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

透過 setDefaultButton() 方法,可以指定那一顆按鈕預先選取 ( 開啟對話視窗時預先變色 ),下方的程式碼執行後,會預先選取 Banana 的按鈕。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    a = mbox.addButton('Apple',3)   # 前方多了變數 a
    b = mbox.addButton('Banana',3)  # 前方多了變數 b
    c = mbox.addButton('Orange',3)  # 前方多了變數 c
    mbox.setDefaultButton(b)        # 預先選取 b
    mbox.exec()

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

Python 教學 - QMessageBox 對話視窗

QMessageBox 點擊事件

如果要取得 QMessageBox 點擊事件,可以將最後 exec() 執行方法宣告為變數,該變數為一組數字,如果是預設按鈕,可以直接透過 if 判斷式進行判斷,就可以知道點擊了哪個按鈕。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    mbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Cancel)
    mbox.setDefaultButton(QtWidgets.QMessageBox.Yes)
    ret = mbox.exec()                      # 取得點擊的按鈕數字
    if ret == QtWidgets.QMessageBox.Yes:
        print(1)
    elif ret == QtWidgets.QMessageBox.No:
        print(2)
    elif ret == QtWidgets.QMessageBox.Cancel:
        print(3)

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

如果是自訂按鈕,則 ret 可以採用「順序」的方式,最先添加的按鈕順序為 0,接著依序增加,只要知道順序,就能知道點擊了哪顆按鈕。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    a = mbox.addButton('Apple',3)   # 前方多了變數 a,順序 0
    b = mbox.addButton('Banana',3)  # 前方多了變數 b,順序 1
    c = mbox.addButton('Orange',3)  # 前方多了變數 c,順序 2
    mbox.setDefaultButton(b)        # 預先選取 b
    ret = mbox.exec()
    print(ret)
    if ret == 0:
        print('Apple')
    if ret == 1:
        print('Banana')
    if ret == 2:
        print('Orange')

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

如果不想要使用「順序」作為判斷依據,也可以使用 mbox.clickedButton().text() 方法取得點擊按鈕的文字,再透過 if 判斷式就能知道點擊了哪顆按鈕。

from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)

def show():
    mbox = QtWidgets.QMessageBox(Form)
    mbox.setText('hello')
    a = mbox.addButton('Apple',3)   # 前方多了變數 a
    b = mbox.addButton('Banana',3)  # 前方多了變數 b
    c = mbox.addButton('Orange',3)  # 前方多了變數 c
    mbox.setDefaultButton(b)        # 預先選取 b
    mbox.exec()
    text = mbox.clickedButton().text()   # 取得點擊的按鈕文字
    if text == 'Apple':
        print('Apple')
    if text == 'Banana':
        print('Banana')
    if text == 'Orange':
        print('Orange')

btn = QtWidgets.QPushButton(Form)
btn.move(10, 10)
btn.setText('open')
btn.clicked.connect(show)

Form.show()
sys.exit(app.exec_())

更多 Python 教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 18 ) QFileDialog 選擇檔案對話視窗
下一篇
( Day 20 ) QInputDialog 輸入視窗
系列文
實戰 Python x PyQt5 軟體介面設計35
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言