8 按鈕類控件
《PyQt5快速開發(fā)與實戰(zhàn)》學(xué)習(xí)筆記。
8.1 QAbstractButton
在任何 GUI 設(shè)計中,按鈕都是最重要的和常用的觸發(fā)動作請求的方式,用來與用戶進行交互操作。在 PyQt5 中根據(jù)不同的使用場景將按鈕劃分為不同的表現(xiàn)形式。按鈕的基類是 QAbstractButton,提供了按鈕的通用性功能。QAbstractButton 類為抽象類,不能實例化,必須由其他的按鈕類繼承 QAbstractButton 類,來實現(xiàn)不同的功能、不同的表現(xiàn)形式。
常見的按鈕類包括:QPushButton、QToolButton、QRadioButton 和 QCheckBox。這些按鈕類均繼承自 QAbstractButton 類,根據(jù)各自的使用場景通過圖形展現(xiàn)出來。
QAbstractButton 提供的狀態(tài)如下所示:

QAbstractButton 提供的信號如下所示:

8.2 QPushButton
QPushButton 類繼承自 QAbstractButton 類,其形狀是長方形,文本標(biāo)題或圖標(biāo)可以顯示在其上。它也是一種命令按鈕,可以單擊該按鈕執(zhí)行一些命令,或者響應(yīng)一些事件。
命令按鈕通常通過文本來描述執(zhí)行的動作,有時候也會通過快捷鍵來執(zhí)行對應(yīng)按鈕的命令。
QPushButton 類中的常用方法:

通過按鈕名字能為 QPushButton 設(shè)置快捷鍵,比如名字為“&Download”的按鈕,它的快捷鍵是“Alt+D”。其規(guī)則是:如果想要實現(xiàn)快捷鍵為“Alt + D”,那么按鈕的名字里就要有這個字母 D,并且在字母 D 前面加上“&”。這個字母 D 一般是按鈕名稱的首字母,而且在按鈕顯示時,“&” 不會被顯示出來,但字母 D 會顯示一條下畫線。如果只想顯示 “&”,那么需要像轉(zhuǎn)義一樣使用 “&&”。更多的關(guān)于快捷鍵的使用,請參考 QShortcut 類。其核心代碼如下:
self.button=QPushButton("&Download")
self.button.setDefault(True)
一個例子:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
layout = QVBoxLayout()
self.btn1 = QPushButton("Button1")
self.btn1.setCheckable(True)
self.btn1.toggle() # 切換按鈕狀態(tài)
self.btn1.clicked.connect(lambda: self.whichbtn(self.btn1))
self.btn1.clicked.connect(self.btnstate)
layout.addWidget(self.btn1)
self.btn2 = QPushButton('image')
self.btn2.setIcon(QIcon(QPixmap("./images/python.png")))
self.btn2.clicked.connect(lambda: self.whichbtn(self.btn2))
layout.addWidget(self.btn2)
self.setLayout(layout)
self.btn3 = QPushButton("Disabled")
self.btn3.setEnabled(False) # 禁用
layout.addWidget(self.btn3)
self.btn4 = QPushButton("&Download")
self.btn4.setDefault(True)
self.btn4.clicked.connect(lambda: self.whichbtn(self.btn4))
layout.addWidget(self.btn4)
self.setWindowTitle("Button demo")
def btnstate(self):
if self.btn1.isChecked():
print("button pressed")
else:
print("button released")
def whichbtn(self, btn):
print("clicked button is " + btn.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
btnDemo = Form()
btnDemo.show()
sys.exit(app.exec_())
8.3 QRadioButton
QRadioButton 類繼承自 QAbstractButton 類,它提供了一組可供選擇的按鈕和文本標(biāo)簽,用戶可以選擇其中一個選項,標(biāo)簽用于顯示對應(yīng)的文本信息。單選鈕是一種開關(guān)按鈕,可以切換為 on 或者off,即 checked 或者 unchecked,主要是為用戶提供“多選一”的選擇。
QRadioButton 是單選鈕控件默認是獨占的(Exclusive)。對于繼承自同一個父類 Widget 的多個單選鈕,它們屬于同一個按鈕組合,在單選鈕組里,一次只能選擇一個單選鈕。如果需要多個獨占的按鈕組合,則需要將它們放在 QGroupBox 或 QButtonGroup 中。
當(dāng)將單選鈕切換到 on 或者 off 時,就會發(fā)送 toggled 信號,綁定這個信號,在按鈕狀態(tài)發(fā)生改變時,觸發(fā)相應(yīng)的行為。
QRadioButton類中的常用方法:

在 QRadioButton 中,toggled 信號是在切換單選鈕狀態(tài)(開、關(guān))時發(fā)射的,而 clicked 信號則在每次點擊單選鈕時都會發(fā)射。在實際中,一般只有狀態(tài)改變時才有必要去響應(yīng),因此 toggled 信號更適合用于狀態(tài)監(jiān)控。
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Radiodemo(QWidget):
def __init__(self, parent=None):
super(Radiodemo, self).__init__(parent)
layout = QHBoxLayout()
self.btn1 = QRadioButton("Button1")
self.btn1.setChecked(True)
self.btn1.toggled.connect(lambda: self.btnstate(self.btn1))
layout.addWidget(self.btn1)
self.btn2 = QRadioButton("Button2")
self.btn2.toggled.connect(lambda: self.btnstate(self.btn2))
layout.addWidget(self.btn2)
self.setLayout(layout)
self.setWindowTitle("RadioButton demo")
def btnstate(self, btn):
if btn.text() == "Button1":
if btn.isChecked() == True:
print(btn.text() + " is selected")
else:
print(btn.text() + " is deselected")
if btn.text() == "Button2":
if btn.isChecked() == True:
print(btn.text() + " is selected")
else:
print(btn.text() + " is deselected")
if __name__ == '__main__':
app = QApplication(sys.argv)
radioDemo = Radiodemo()
radioDemo.show()
sys.exit(app.exec_())
效果:

8.4 QCheckBox
QCheckBox 類繼承自 QAbstractButton 類,它提供了一組帶文本標(biāo)簽的復(fù)選框,用戶可以選擇多個選項。和 QPushButton 一樣,復(fù)選框可以顯示文本或者圖標(biāo),其中文本可以通過構(gòu)造函數(shù)或者 setText() 來設(shè)置;圖標(biāo)可以通過 setIcon() 來設(shè)置。在視覺上,QButtonGroup 可以把許多復(fù)選框組織在一起。
QCheckBox(復(fù)選框)和 QRadioButton(單選鈕)都是選項按鈕,因為它們都可以在開(選中)或者關(guān)(未選中)之間切換。它們的區(qū)別是對用戶選擇的限制:單選鈕提供了“多選一”的選擇;而復(fù)選框提供的是“多選多”的選擇。
QCheckBox 通常被應(yīng)用在需要用戶選擇一個或多個可用的選項的場景中。只要復(fù)選框被選中或者取消選中,都會發(fā)射一個 stateChanged 信號。如果想在復(fù)選框狀態(tài)改變時觸發(fā)相應(yīng)的行為,請連接這個信號,可以使用 isChecked() 來查詢復(fù)選框是否被選中。
除了常用的選中和未選中兩種狀態(tài),QCheckBox 還提供了第三種狀態(tài)(半選中)來表明“沒有變化”。當(dāng)需要為用戶提供一個選中或者未選中復(fù)選框的選擇時,這種狀態(tài)是很有用的。如果需要第三種狀態(tài),則可以通過 setTristate() 來使它生效,并使用 checkState() 來查詢當(dāng)前的切換狀態(tài)。
QCheckBox 類中的常用方法:

三態(tài)復(fù)選框有三種狀態(tài):

QCheckBox 按鈕的使用
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
class CheckBoxDemo(QWidget):
def __init__(self, parent=None):
super(CheckBoxDemo, self).__init__(parent)
groupBox = QGroupBox("Checkboxes")
groupBox.setFlat(False)
layout = QHBoxLayout()
self.checkBox1 = QCheckBox("&Checkbox1")
self.checkBox1.setChecked(True)
self.checkBox1.stateChanged.connect(lambda: self.btnstate(self.checkBox1))
layout.addWidget(self.checkBox1)
self.checkBox2 = QCheckBox("Checkbox2")
self.checkBox2.toggled.connect(lambda: self.btnstate(self.checkBox2))
layout.addWidget(self.checkBox2)
self.checkBox3 = QCheckBox("tristateBox")
self.checkBox3.setTristate(True)
self.checkBox3.setCheckState(Qt.PartiallyChecked)
self.checkBox3.stateChanged.connect(lambda: self.btnstate(self.checkBox3))
layout.addWidget(self.checkBox3)
groupBox.setLayout(layout)
mainLayout = QVBoxLayout()
mainLayout.addWidget(groupBox)
self.setLayout(mainLayout)
self.setWindowTitle("checkbox demo")
def btnstate(self, btn):
chk1Status = self.checkBox1.text()+", isChecked=" + str(self.checkBox1.isChecked()) + \
', chekState=' + str(self.checkBox1.checkState()) + "\n"
chk2Status = self.checkBox2.text()+", isChecked=" + str(self.checkBox2.isChecked()) + \
', checkState=' + str(self.checkBox2.checkState()) + "\n"
chk3Status = self.checkBox3.text()+", isChecked=" + str(self.checkBox3.isChecked()) + \
', checkState=' + str(self.checkBox3.checkState()) + "\n"
print(chk1Status + chk2Status + chk3Status)
if __name__ == '__main__':
app = QApplication(sys.argv)
checkboxDemo = CheckBoxDemo()
checkboxDemo.show()
sys.exit(app.exec_())
效果:
