【PyQt学习篇 · ⑩】:QAbstractButton的使用

QAbstractButton简介

QAbstractButton 是一个抽象类,无法直接实例化,但它提供了很多在 PyQt 中使用按钮时常用的功能和特性。开发人员可以通过继承 QAbstractButton 类并实现自定义行为来创建自己的按钮类。

子类化抽象类

在 PyQt 中,可以通过子类化 QAbstractButton 的抽象类来创建自定义的按钮类。通过子类化,可以根据需要扩展和重写 QAbstractButton 的功能,并实现自定义的按钮行为。

如以下代码:

btu = QAbstractButton(window)
btu.setText('按钮')

结果:

在这里插入图片描述
当我们实例化一个QAbstractButton对象时发生错误,原因就是C++的抽象类无法直接被实例化,而应该去子类化一个类,也就是写一个继承自QAbstractButton的类才可以。

再看以下代码:

class Btu(QAbstractButton):
    pass
btu = Btu(window)
btu.setText('按钮')

结果:

在这里插入图片描述
当我们想子类化抽象类时,必须要实现抽象类里面的所有抽象方法,即根据以上报错信息,我们必须要实现绘制事件paintEvent这样一个方法。

示例代码:

from PyQt5.Qt import *
import sys


class Btu(QAbstractButton):
    def paintEvent(self, evt):
        # 1. 创建一个画家
        painter = QPainter(self)

        # 2. 创建一支笔 QColor(RGB, 笔的宽度)
        pen = QPen(QColor(111, 100, 50), 3)

        # 3. 设置笔
        painter.setPen(pen)

        # 4. 画家画
        painter.drawText(25, 50, self.text())

        # 画个圆形(长方体的内切圆)
        painter.drawEllipse(0, 0, 100, 100)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(300, 300)

    btu = Btu(window)
    btu.setText('按钮')
    btu.move(50, 50)
    btu.resize(100, 100)
    btu.pressed.connect(lambda: print('按钮被按下'))

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

运行结果:

在这里插入图片描述
在这里插入图片描述

图标设置

下面是关于 QAbstractButton 图标设置的一些重要 API 的说明:

  1. setIcon(QIcon("resource/h1.png"))

    • 这个方法用于设置按钮的图标。它接受一个 QIcon 参数,表示要在按钮上显示的图标。
  2. setIconSize(QSize(w, h))

    • 这个方法用于设置按钮图标的大小。它接受一个 QSize 参数,指定图标的宽度(w)和高度(h)。
  3. icon()

    • 这个方法用于获取当前按钮的图标。
  4. iconSize()

    • 这个方法用于获取按钮图标的大小。

以上API的使用示例代码:

from PyQt5.Qt import *
from PyQt5.QtGui import QIcon
import sys

class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setText('0')
        self.resize(50, 50)
        # 设置图标
        self.setIcon(QIcon('mouse.png'))
        # 设置图标大小
        self.setIconSize(QSize(50, 50))

        # 点击鼠标,数值+1
        self.pressed.connect(lambda: self.setText(str(int(self.text()) + 1)))

        print(self.icon())  # 获取当前按钮的图标并打印
        print(self.iconSize())  # 获取按钮图标的大小并打印


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(300, 300)
    window.setWindowTitle('图标设置')

    btu = Btu(window)

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

运行结果:

在这里插入图片描述
在这里插入图片描述

快捷键设置

可通过指定的快捷键,触发按钮的点击。

  • 方式一:有提示文本的。如果提示文本包含&符号的,则QAbstractButton会自动创建快捷键。
  • 方式二:没有提示文本的。setShortcut("Alt+G")

方式一的示例代码:

from PyQt5.Qt import *
from PyQt5.QtGui import QIcon
import sys


class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setText('a&bc')
        self.resize(80, 50)

        # 设置图标
        self.setIcon(QIcon('mouse.png'))
        # 设置图标大小
        self.setIconSize(QSize(50, 50))

        self.pressed.connect(lambda: print('按钮被按下'))

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(300, 300)
    window.setWindowTitle('快捷键设置')

    btu = Btu(window)

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

运行结果:

在这里插入图片描述
按下“Alt+b”后

在这里插入图片描述
方式二示例代码:

修改方式一中Btu类中的代码:

class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(80, 50)
        self.setShortcut("Alt+a")
        # 设置图标
        self.setIcon(QIcon('mouse.png'))
        # 设置图标大小
        self.setIconSize(QSize(50, 50))

        self.pressed.connect(lambda: print('按钮被按下'))

运行结果:

在这里插入图片描述
按下“Alt+b”后

在这里插入图片描述

自动重复

自动重复功能允许按钮在按下并保持按压状态时重复执行其操作。以下是关于 QAbstractButton 自动重复的一些重要 API 的说明:

  1. setAutoRepeat(bool)
    • 这个方法用于设置按钮的自动重复功能是否启用。它接受一个布尔值参数,如果为 True,表示启用自动重复;如果为 False,表示禁用自动重复。
  2. setAutoRepeatInterval(毫秒)
    • 这个方法用于设置按钮自动重复的时间间隔。它接受一个整数参数,表示按下按钮后的重复时间间隔,单位为毫秒。
    • 默认情况下,按钮的自动重复时间间隔为 1000 毫秒(即 1 秒)。
  3. setAutoRepeatDelay(毫秒)
    • 这个方法用于设置按钮自动重复的延迟时间。它接受一个整数参数,表示按下按钮后开始重复之前的延迟时间,单位为毫秒。
    • 默认情况下,按钮的自动重复延迟时间为 500 毫秒。
  4. autoRepeat()
    • 这个方法用于检查按钮的自动重复功能是否启用。如果按钮启用了自动重复,它将返回 True;否则返回 False。
  5. autoRepeatInterval()
    • 这个方法用于获取按钮的自动重复时间间隔,以毫秒为单位。
  6. autoRepeatDelay()
    • 这个方法用于获取按钮的自动重复延迟时间,以毫秒为单位。

示例代码:
当点击按钮不松时,按钮文本数字连续累增。

from PyQt5.Qt import *
from PyQt5.QtGui import QIcon
import sys


class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setText('0')
        self.resize(80, 50)

        # 设置图标
        self.setIcon(QIcon('mouse.png'))
        # 设置图标大小
        self.setIconSize(QSize(50, 50))

        self.pressed.connect(lambda: self.setText(str(int(self.text()) + 1)))


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(300, 300)
    window.setWindowTitle('自动回复')

    btu = Btu(window)

    # 设置自动回复
    btu.setAutoRepeat(True)
    # 设置自动重复的时间间隔
    btu.setAutoRepeatInterval(1000)     # 1000毫秒
    # 设置自动重复的延迟时间
    btu.setAutoRepeatDelay(3000)    # 3000毫秒

    print(btu.autoRepeat())
    print(btu.autoRepeatInterval())
    print(btu.autoRepeatDelay())

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

运行结果:

在这里插入图片描述
在这里插入图片描述
当鼠标一直按下按钮,过了三秒后,每隔一秒就会重复鼠标按下事件,于是数值每隔一秒后自增一。

状态设置

QAbstractButton 是 PyQt5 中的一个按钮类,它提供了一些方法用于设置按钮的状态。以下是关于 QAbstractButton 状态设置的一些重要 API 的说明:

  1. isDown()

    • 这个方法用于设置按钮是否处于按下状态(本质上,它是一种“按下”的效果,因为按钮通常是矩形区域,我们不能真的看到按钮被按下)。
    • 如果按钮被按下了,则返回 True;否则返回 False。
    • setDown(bool) 方法用于设置按钮是否处于按下状态,接受一个布尔值参数,如果为 True,表示按钮被按下了,否则表示按钮未被按下。
  2. isChecked()

    • 这个方法用于设置按钮是否处于选中状态。
    • 如果按钮被选中了,则返回 True;否则返回 False。
    • setCheckable(bool) 方法用于设置按钮是否可以被选中,接受一个布尔值参数,如果为 True,表示按钮可以被选中;否则表示按钮不可被选中。
    • toggle() 方法用于切换按钮的选中状态,如果按钮原来被选中,则调用 toggle() 后会取消选中;如果原来没被选中,则 toggle() 后会将其设置为被选中状态。
  3. isEnabled()setEnabled(bool)

    • isEnabled() 方法用于检查按钮是否处于可用状态。如果按钮可用,则返回 True;否则返回 False。
    • setEnabled(bool) 方法用于设置按钮的可用状态。如果将参数设置为 True,表示按钮可用,否则表示按钮不可用。

示例1代码:

from PyQt5.Qt import *
from PyQt5.QtGui import QIcon
import sys


class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.resize(50, 50)
        self.setIcon(QIcon('mouse.png'))
        self.setIconSize(QSize(50, 50))

if __name__ == '__main__':

    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle('状态设置')
    window.resize(300, 300)

    btu = Btu(window)

    # 创建三个按钮
    push_btu = QPushButton(window)
    push_btu.setText('这是一个按钮')
    push_btu.move(100, 50)

    radio_btu = QRadioButton(window)
    radio_btu.setText('这是一个radio')
    radio_btu.move(100, 100)

    checkbox_btu = QCheckBox(window)
    checkbox_btu.setText('这是一个checkbox')
    checkbox_btu.move(100, 150)

    # 把三个按钮,置为按下状态
    push_btu.setDown(True)
    radio_btu.setDown(True)
    checkbox_btu.setDown(True)


    print('是否被按下:')
    print(push_btu.isDown())
    print(radio_btu.isDown())
    print(checkbox_btu.isDown())

    print('是否处于选中状态:')
    print(push_btu.isChecked())
    print(radio_btu.isChecked())
    print(checkbox_btu.isChecked())

    print('是否可以被选中:')
    print(push_btu.isCheckable())
    print(radio_btu.isCheckable())
    print(checkbox_btu.isCheckable())

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

运行结果:

在这里插入图片描述
在这里插入图片描述
示例2代码:

from PyQt5.Qt import *
from PyQt5.QtGui import QIcon
import sys


class Btu(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.resize(50, 50)
        self.setIcon(QIcon('mouse.png'))
        self.setIconSize(QSize(50, 50))

def change_type():
    push_btu.toggle()
    radio_btu.toggle()
    checkbox_btu.toggle()

if __name__ == '__main__':

    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle('状态设置')
    window.resize(300, 300)

    btu = Btu(window)
    btu.pressed.connect(change_type)
    # 创建三个按钮
    push_btu = QPushButton(window)
    push_btu.setText('这是一个按钮')
    push_btu.move(100, 50)
    push_btu.setCheckable(True)     # 设置为可以被选中

    radio_btu = QRadioButton(window)
    radio_btu.setText('这是一个radio')
    radio_btu.move(100, 100)

    checkbox_btu = QCheckBox(window)
    checkbox_btu.setText('这是一个checkbox')
    checkbox_btu.move(100, 150)
    
    window.show()
    sys.exit(app.exec_())

运行结果:

在这里插入图片描述
示例3代码:
在示例2代码的基础上,设置三个按钮为不可用状态,观察其是否还可以切换状态。

    push_btu.setEnabled(False)
    radio_btu.setEnabled(False)
    checkbox_btu.setEnabled(False)

运行结果:
还是可以切换状态

在这里插入图片描述

排他性

以下是有关排他性的重要 API 的说明:

  1. autoExclusive()setAutoExclusive(bool)
    • autoExclusive() 方法用于检查按钮是否启用了排他性。如果按钮启用了排他性,则返回 True;否则返回 False。
    • setAutoExclusive(bool) 方法用于设置按钮是否启用排他性。如果参数设置为 True,表示启用按钮的排他性,即同一组中的按钮只能有一个处于选中状态;否则表示不启用排他性,即同一组中的按钮可以同时选中多个。

示例1代码:

from PyQt5.Qt import *
import sys


app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle('排他性')
window.resize(300, 300)

for i in range(3):
    btu = QPushButton(window)
    btu.setText('btu' + str(i))
    btu.move(50*i, 50*i)

print(btu.autoExclusive())  # 打印三个按钮的排他性
btu.setCheckable(True)  # 设置三个按钮为可选中

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

运行结果:
因为三个按钮排他性都为False,所以都可以被选中
在这里插入图片描述
在这里插入图片描述

示例2代码:

btu.setAutoExclusive(True)  # 设置排他性为True

运行结果:
设置三个按钮的排他性为True后,只能选择其中一个按钮。

在这里插入图片描述
在这里插入图片描述

点击

在 PyQt5 中,QAbstractButton 类提供了两个方法来处理按钮的点击事件。以下是有关点击事件的两个重要 API 的说明:

  1. click()
    • click() 方法用于手动触发按钮的点击事件。当程序调用该方法时,按钮将执行与点击事件相关的操作,就好像用户实际点击了按钮一样。
  2. animateClick(ms)
    • animateClick(ms) 方法用于模拟按钮的动画点击效果,即在一段时间内模拟按钮的按下和释放动作。该方法会触发按钮的点击事件,并在一定时间内呈现按钮按下和释放的效果。
    • 参数 ms 表示动画点击的持续时间(以毫秒为单位)。在这段时间内,按钮会呈现按下状态,然后逐渐恢复到正常状态。

示例代码:

from PyQt5.Qt import *
import sys


app = QApplication(sys.argv)

window = QWidget()
window.resize(300, 300)
window.setWindowTitle('点击')

btu = QPushButton(window)
btu.setText('按钮')
btu.move(100, 100)

def text():
    print('点击了这个按钮')
btu.pressed.connect(text)

btu.click()     # 模拟鼠标点击

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

运行结果:
窗口出现后,模拟点击,进入槽函数,打印结果。

在这里插入图片描述
在这里插入图片描述

将以上代码中的 btu.click() 换成 btu.animateClick(2000) 后运行,在窗口出现后按钮被模拟点击2s,相当于按下按钮2s后再松开,展现一个按钮被点击的动画。

运行结果:

在这里插入图片描述
在这里插入图片描述

设置点击有效区域

在 PyQt5 中,QAbstractButton 类提供了一个重写函数 hitButton(QPoint),用于实现按钮的模拟点击。以下是 hitButton(QPoint) 的说明:

  1. hitButton(QPoint) 函数:
    • hitButton(QPoint) 函数用于处理按钮的模拟点击事件。当用户在图形界面上模拟点击按钮时,该函数将被调用,并传入点击的坐标。
    • 点击有效返回True,否则返回False
    • 参数 QPoint 表示点击的坐标,是一个包含 x 和 y 坐标值的 QPoint 对象,其中以按钮的左上角为坐标原点。

示例1代码:

from PyQt5.Qt import *
import sys


class Btu(QPushButton):
    def hitButton(self, point):
        print(point)
        return False

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.resize(300, 300)
    window.setWindowTitle('设置有效区域')

    btu = Btu(window)
    btu.setText('点击')
    btu.move(100, 100)

    btu.pressed.connect(lambda: print('按钮被点击了'))

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

运行结果:
点击按钮后槽函数并没有被执行,因为在hitButton(self, point)函数中返回了False,判定为本次点击无效。

在这里插入图片描述
示例2代码:
设置点击按钮左半部分无效,点击右半部分有效。

class Btu(QPushButton):
    def hitButton(self, point):
        print(point)
        if point.x() > self.width() / 2:
            return True
        return False

运行结果:

在这里插入图片描述

可用信号

在 PyQt5 中,QAbstractButton 类提供了多个可用信号,用于处理按钮被按下、释放、单击和切换等事件。以下是有关信号的四个重要 API 的说明:

  1. pressed()
    • pressed() 信号在按钮被按下时发出。对于鼠标事件,指鼠标按下左键并保持键盘状态的情况。
  2. released()
    • released() 信号在按钮被释放时发出。对于鼠标事件,指放开左键。
  3. clicked(checked=false)
    • clicked(checked=false) 信号在按钮被单击时发出。如果按钮是可切换的,则 checked 参数表示按钮状态是否已切换。
    • 对于弹起事件,也会发出 clicked 信号。这意味着 clicked 信号发出时,不一定意味着按钮处于按下状态。
  4. toggled(bool checked)
    • toggled(bool checked) 信号在按钮的状态切换时发出。如果按钮未切换,则 checked 为 False;如果按钮已切换,则 checked 为 True。
    • 这个信号只对可切换的按钮有效。

示例1代码:

from PyQt5.Qt import *
import sys


app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle('可用信号')
window.resize(300, 300)

btu = QPushButton(window)
btu.move(100, 100)
btu.setText('点击')

btu.pressed.connect(lambda: print('按钮被按下了'))
btu.released.connect(lambda: print('按钮被释放了'))

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

运行结果:

在这里插入图片描述
示例2代码:

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)

window = QWidget()
window.setWindowTitle('可用信号')
window.resize(300, 300)

btu = QPushButton(window)
btu.move(100, 100)
btu.setText('点击')

btu.toggled.connect(lambda value: print('按钮选中状态发生了改变', value))

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

运行结果:
点击按钮后没有任何打印结果

在这里插入图片描述
在示例2中加入以下代码:
设置按钮为可选状态

btu.setCheckable(True)

运行结果:

在这里插入图片描述