pyQt5 学习笔记(11)QAbstractButton 虚拟按钮控件

mac2026-02-14  10

文章目录

一、QAbstracrtButton 简介二、子类化抽象类:自定义按钮三、功能(API)1. 设置文本2. 设置图标3. 快捷键设置3.1 快捷设置3.2 函数设置 4. 自动重复5. 状态设置6.排他性6.1 按键排他性的设置6.2 按键排的范围 7.设置有效区域 四、信号

一、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()信号。

最新回复(0)