文章目录
一、QAbstracrtButton 简介
前文10小节中,都是相关QWidget控件的特性,它继承自QObject等控件,是所有用户界面对象的基类。同样的QAbstracrtButton 是所有按钮控件的基类,即所有按钮都继承该类,所以学习该类也就学习了所有按钮的通用特性。
二、子类化抽象类:自定义按钮
由于这个类别是虚拟化类别,所以使用该类特性需要借助其子类(它不能被直接实例化)。如以下程序是无法通过编译的:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
# 错误的使用
btn = QAbstractButton()
if __name__ == '__main__':
sys.exit(app.exec_())
程勋运行如下所示:
如果我们想要创建一个QAbstractButton
类,需要创建一个继承它的类, 如下所示:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
class Btn(QAbstractButton):
def paintEvent(self, QPaintEvent):
pass
btn = Btn()
if __name__ == '__main__':
sys.exit(app.exec_())
这里还重定义了paintEvent()
函数,否则编译不通过并提示需要重载paintEvent()
函数。当然,程序运行以后不会有任何显示,如果我们需要自定义按键,则需要在paintEvent()
中实现绘图的代码。以下程序示例了一个简单的自定义按钮:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
#1.自定义一个类
class Btn(QAbstractButton):
#2.重定义绘图事件
def paintEvent(self, QPaintEvent):
#3.创建一个绘图对象
painter = QPainter(self)
#4.创建一个画笔(rgb颜色,宽度)
pen = QPen(QColor(111,100,50),3)
#5.设置画笔
painter.setPen(pen)
#6.绘制文本:自定义按键,在位置(20,20)
painter.drawText(20,20,"自定义按键")
#7.绘制一个按键边框
painter.drawEllipse(0,0,60,20)
btn = Btn(w)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
程序运行效果如下所示:
第14行:重写了paintEvent()
,当控件被绘制时,调用该函数
第16行:创建了一个QPainter()
对象,QWidget不知继承了QObject也继承QPaintDevice,QWidget及其子类都可以当做一个画纸,被QPainter()绘制
第18行:创建了画笔,QColor()
为rgb颜色,参数3
为画笔的宽度
第22行:设置了绘制文本位置及其内容
第24行:绘制一个椭圆,参数为(x坐标,y坐标,宽度,高度),它线条的宽度为Qpen决定。
这里只是简单的演示了一个按钮的绘制,它的大小,文本,样式都是无法改变的,实际应用中,我们会通过传参的方法,来让这个类变得更加灵活,由于它是按键的类,所以按键点击事件是可以被捕获的。当然,我们自定义按键也不一定继承该类,可视情况继承其子类。
三、功能(API)
接下来介绍该类一些常用的功能函数,设置文本,图标等。这里为方便不直接使用该类,而是借助pyQt已经实现的子类。
1. 设置文本
按键可以通过setText()
来设置按键显示的文本:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
btn = QPushButton(w)
btn.setText('一个按键')
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
2. 设置图标
按键可以设置一个图标,图标显示在按键的左测,通过setIcon()
来设置,还可以通过setIconSize()
和btn.iconSize()
来设置和获取大小,注意图标的大小会影响控件的大小,以下程序示例了一个按键图标的设置:(需要准备一个图标,并清楚其位置,一般放在工程文件中):
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
btn = QPushButton(w)
#1.文本操作
btn.setText('关闭电源')
#2.图标操作
icon = QIcon("powerBtn.ico") #图标的位置,由于本文件通目录,这里只写了名字即可
btn.setIcon(icon)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
程序运行如下:
3. 快捷键设置
3.1 快捷设置
可以通过&
来设置:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
btn = QPushButton(w)
#1.文本操作
btn.setText('&Power Down')
#2.图标操作
icon = QIcon("powerBtn.ico")
btn.setIcon(icon)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
程序可以通过按Alt + P
来实现和鼠标点击按键一样的效果:
可以发现,通过按Alt
以后,P字母下多了一个横线,这个功能在很多英文界面的软件都有体现,如果你改变了&
的位置,也就改变了快捷键。
3.2 函数设置
由于我们按键可能只有一个图标,或者显示文本非英文,如中文等,此时可以通过更灵活的函数setShortcut
,其参数为文本格式:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
btn = QPushButton(w)
#1.文本操作
btn.setText('关闭电源')
#2.图标操作
icon = QIcon("powerBtn.ico")
btn.setIcon(icon)
#3. 设置快捷:shift+F1
btn.setShortcut("Shift+F1")
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行程序以后,可以通过shift+F1
来按下按键
4. 自动重复
重复指的是当用户点击按钮时不松开,此时按键将不断被发送信号。
一些常用的API:
setAutoRepeat()
:是否自动重复
setAutoRepeatDelay()
:按下多久毫秒以后开始自动重复
setAutoRepeatInterval
:自动重复的间隔
以下程序演示了自动重复API的使用:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
btn = QPushButton(w)
#1.文本操作
btn.setText('关闭电源')
#2.图标操作
icon = QIcon("powerBtn.ico")
btn.setIcon(icon)
#3.设置快捷:shift+F1
btn.setShortcut("Shift+F1")
#4.自动重复
btn.setAutoRepeat(True) #自动重复
btn.setAutoRepeatDelay(2000) #两秒以后开始
btn.setAutoRepeatInterval(500) #间隔500ms,即1ms重复触发两次
#5. 打印按键点击事件
def press_slot():
print("按键点击")
#6.连接槽函数
btn.pressed.connect(press_slot)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
5. 状态设置
一个按键有多种状态,比如是否有效,是否被点击,是否被选中等等,都可以通过API来设置,也可以通API来获取某一个空间的状态:
函数 | 含义 |
---|---|
isDown() | 是否被按下 |
setDown(bool) | 设置按下状态 |
isChecked() | 是否被选中 |
isCheckable() | 是否能被选中 |
setChecked(bool) | 这是被选中 |
toggle | 切换选中状态 |
通常,按键被鼠标点击(但是没有松开)状态称为按下状态,类似单选框或者是复选框,它们还可以被选中,而普通的按键是默认是不能被选中的,但是它可以被设置。以下程序示例了这些接口函数的使:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
#1.创建一个普通按键
btn0 = QPushButton(w)
btn0.move(0,0)
btn0.setText('Push Button')
#2.创建一个单选按键
btn1 = QRadioButton(w)
btn1.move(0,30)
btn1.setText('RadioButton')
#3.创建一个复选复选按键
btn2 = QCheckBox(w)
btn2.move(0,60)
btn2.setText('CheckBox_1')
btn2.setChecked(True) #设置被选中状态
#3.创建一个复选复选按键
btn3 = QCheckBox(w)
btn3.move(0,90)
btn3.setText('CheckBox_2')
btn3.setEnabled(False) #失能按键
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
可以看到,程序创建了4个按键,其中2个是复选框,第一个复选框运行默认就别选中,第二个则是无效状态,显然的,复选框被选中的时候,方框内多了一个‘√’,在pyQt中,按钮别选中状态的样式,是可以通过样式表来设置的,以下程序示例将普通按钮的按下状态更改一个背景颜色:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
#1.创建一个普通按键
btn0 = QPushButton(w)
btn0.move(0,0)
btn0.setText('Push Button')
btn0.setStyleSheet("QPushButton:pressed {background-color:green}")
#2.创建一个单选按键
btn1 = QRadioButton(w)
btn1.move(0,30)
btn1.setText('RadioButton')
#3.创建一个复选复选按键
btn2 = QCheckBox(w)
btn2.move(0,60)
btn2.setText('CheckBox_1')
btn2.setChecked(True) #设置被选中状态
#3.创建一个复选复选按键
btn3 = QCheckBox(w)
btn3.move(0,90)
btn3.setText('CheckBox_2')
btn3.setEnabled(False) #失能按键
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行以后,当 Push Button 被按下以后,背景颜色将变成绿色。
这个只示例了一个最简单的修改背景功能,QSS样式表有跟多的功能。
6.排他性
6.1 按键排他性的设置
按钮的排他性指的是按键之间相互排查特性,比如一个性别表格中,会提供男性和女性供用户选择,但是用户只能选择其中一个,典型的应用是单选按钮。以下程序示例了排他性的使用,由于所用QPushButton控件默认无法被选中,所以通过set.Checkable(True)
来设置改变它的特性,这样,当我们点击按钮的时候,即便是松开,按钮的按时处于按下状态:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(300,300)
#1.使用for循环创建3个按键
for i in range(0,3):
btn = QPushButton(w)
btn.setCheckable(True) #失能选中状态:是按键能被选中
btn.setAutoExclusive(True) #设置排他性
btn.setText("btn_" + str(i))
btn.move(0,20*i)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
注:QPushButton默认没有排他性,而QRadioButton的是默认有排他性的。
6.2 按键排的范围
按键排他性设置为Ture
以后,就会和同父控件的其他同样设置为Ture
的按键形成互斥状态。所以,我们可以使用不同的父控件,来对按键排他性作一个分类:
from PyQt5.Qt import *
import sys
#创建一个APP
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(210,110)
sub_w1 = QWidget(w)
sub_w1.resize(100,100)
sub_w2 = QWidget(w)
sub_w2.resize(100,100)
sub_w2.move(105,0)
#1.使用for循环创建3个按键
for i in range(0,3):
btn = QPushButton(sub_w1)
btn.setCheckable(True) #失能选中状态:是按键能被选中
btn.setAutoExclusive(True) #设置排他性
btn.setText("btn_" + str(i))
btn.move(0,20*i)
#1.使用for循环创建3个按键
for i in range(0,3):
btn = QPushButton(sub_w2)
btn.setCheckable(True) #失能选中状态:是按键能被选中
btn.setAutoExclusive(True) #设置排他性
btn.setText("btn_" + str(i))
btn.move(0,20*i)
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
可以看到,两侧的按钮互相独立,但是同侧的按钮相互排斥,这就是因为所属父控件不同造成的。
7.设置有效区域
hitButton()
可以用来设置控件的有效区域,即使可以设定按钮控件内哪一部被按下,才算是点击了按钮。当控件被按下时候,hitButton()
默认返回True
,所以,可以通过重写该方法,来实现有效区域的自定义,以下程序示例了,一个按钮只有右半部分被点下时,才算有效点击:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("QAbstractButton")
w.resize(210,110)
class Btn(QPushButton):
def hitButton(self,point):
print(point) #打印point:point为光标点击坐标,相对于控件
if point.x() > self.width()/2: #判断x是否在右侧
return True
else :
return False
btn = Btn(w)
btn.setText("点击")
btn.pressed.connect(lambda: print("点击了这个按钮"))
w.show()
if __name__ == '__main__':
sys.exit(app.exec_())
运行:
这个控件宽度为75,所以只有当x值大于75/2时,“点击了这个按钮”才会被打印,也就是按键才被认为是按下了。
四、信号
QAbstractButton 类有是个基本的信号:
信号 | 含义 |
---|---|
pressed() | 按键被点击(不松开) |
released() | 按键松开 |
clicked() | 按键点击 |
toggled() | 按键选择状态翻转(一般用于单选框和复选框) |
这里,当鼠标在控件内按下不松开,然后离开控件,判定为:按键松开,但是不算一次点击,即发送released()信号,不发送clicked()信号。