9 - 具化的按钮子类

9 - 具化的按钮子类

(一)QPushButton

1、描述

用来给用户点击, 来完成某种动作的控件,一般是矩形

例如:登录按钮、注册按钮、关闭按钮、是、否…

2、继承

QObject——QWidget——QAbstractButton——QPushButton

3、功能作用
(1)构造函数
  • QPushButton():创建一个无父控件的按钮控件;
  • QPushButton(parent):创建控件的同时, 设置父控件
  • QPushButton(text, parent):创建控件的同时, 设置提示文本和父控件,相当于QPushButton+setText。
  • QPushButton(icon, text, parent):创建控件的同时, 设置图标, 提示文本和父控件
btn1 = QPushButton(window)
btn2 = QPushButton("按钮", window)
btn3 = QPushButton(QIcon("star.png"), "按钮", window)

btn2.move(0, 100)
btn3.move(0, 200)

image-20220217183149249

(2)快捷键
API

设置英文文本时使用&符号

QPushButton("&Sz", window)

setText("&Sz")

应用场景

想通过快捷键触发按钮点击事件的时候设置

案例

创建一个窗口, 上面有个子控件按钮,要求:点击后打印"Hello Sz",可通过快捷键Alt + H, 触发点击。

btn = QPushButton("&H", window)
btn.pressed.connect(lambda : print("Hello Sz"))
(3)菜单设置
API
  • setMenu(QMenu):设置菜单;
  • menu():获取菜单;
  • showMenu():展示菜单(菜单呈打开状态)。PS:必须在window.show()之后才能用
应用场景

可以设置点击按钮是弹出的菜单, 供用户选择。比如:

image-20220217184533153

对应上图,QMenu:

  • 添加子菜单:addMenu(QMenu) 比如,上图的【打开最近文件】这种不会执行的行为,而是打开子菜单。
  • 添加分割线:addSeparator() 比如,上图【新建窗口】下面的那条线。
  • 添加行为动作:addAction(QAction) 比如,上图的【新建】这种直接执行的行为。
  • QMenu控件设置:
    • setTitle(str);
    • setlcon(Qlcon)
  • QAction设置:
    • setText(str):设置标题;
    • setlcon(QIcon):设置图标;
    • 信号:triggAred
# *******************设置菜单*******************开始
menu = QMenu()

new_action = QAction()
new_action.setText("新建")
new_action.setIcon(QIcon("star.png"))
menu.addAction(new_action)

btn3.setMenu(menu)
# *******************设置菜单*******************结束

由构造函数可知:

class QAction(__PyQt5_QtCore.QObject):
    """
    QAction(parent: QObject = None)
    QAction(str, parent: QObject = None)
    QAction(QIcon, str, parent: QObject = None)
    """

创建QAction同时可设置标题、图标、父对象,即可以合并成一句:

注意:就算设置了父控件,也不会自动加到菜单里,还得手动add。

# *******************设置菜单*******************开始
menu = QMenu(window)

new_action = QAction(QIcon("star.png"), "新建", menu)
menu.addAction(new_action)

btn3.setMenu(menu)
# *******************设置菜单*******************结束
案例:

创建一个菜单,其中最近打开包含子菜单,新建、打开–分割线–退出不包含。

# *******************设置菜单*******************开始
menu = QMenu(window)
# new_action = QAction()
# new_action.setText("新建")
# new_action.setIcon(QIcon("star.png"))
new_action = QAction("新建", menu)
new_action.triggered.connect(lambda: print("新建文件"))

open_action = QAction("打开", menu)
open_action.triggered.connect(lambda: print("打开文件"))

exit_action = QAction("退出", menu)
exit_action.triggered.connect(lambda: print("退出程序"))

open_recent_menu = QMenu("最近打开", menu)
# open_recent_menu.setTitle("最近打开")
file_action = QAction("python-gui")
open_recent_menu.addAction(file_action)

menu.addAction(new_action)
menu.addAction(open_action)
menu.addMenu(open_recent_menu)
menu.addSeparator()
menu.addAction(exit_action)

btn3.setMenu(menu)
print(btn3.menu())
# *******************设置菜单*******************结束

image-20220217210103702

打印出的菜单对象:<PyQt5.QtWidgets.QMenu object at 0x00000149EB06D0D8>

(4)边框是否保持扁平
API
  • setFlat(bool):默认值为False。设置了此属性,则除非按下按钮,否则大多数样式都不会绘制按钮背景
  • isFlat():获取当前按钮边框是否扁平。
# *******************扁平化*******************开始
print(btn3.isFlat())
btn3.setStyleSheet("background-color:cyan;")
btn3.setFlat(True)
print(btn3.isFlat())
# *******************扁平化*******************结束

输出:False、True。

非扁平化:(看第三个按钮)

image-20220217211125714

扁平化:

image-20220217211109015

应用场景

设置按钮扁平化风格。

(5)默认处理
API
  • setAutoDefault(bool)
    • 用户点击后设置为自动默认按钮(不是一开始就默认!!)。
    • 在某些GUI样式中,默认按钮被绘制,其周围有一个额外的框架,最多3个像素或更多。
    • Qt会自动在自动默认按钮周围保留此空间,即自动默认按钮可能会有稍大的提示。
    • 对于具有QDialog父级的按钮,此属性的默认值为true ; 否则默认为false。
  • autoDefault()
  • setDefault(bool):一开始就设置为默认按钮。
  • isDefault()
# *******************自动默认按钮*******************开始
btn2.setAutoDefault(True)
btn1.setDefault(True)
print(btn1.isDefault())
print(btn2.isDefault())
print(btn3.isDefault())
print(btn1.autoDefault())
print(btn2.autoDefault())
print(btn3.autoDefault())
# *******************自动默认按钮*******************结束

image-20220217211903752

输出:True,False,False;False,True,False。

应用场景

一般是在对话框中使用。比如下图的自动默认按钮是【打开】,即点击==【Enter】==会选择的按钮。

image-20220217211259317

4、信号

都是继承下来的。

  • QAbstractButton:

    • pressed():鼠标按下信号;
    • released():鼠标释放(控件内松开鼠标 or 鼠标移出控件范围后松开);
    • clicked(checked = false):控件内按下+控件内释放;
    • toggled(bool checked):切换信号,选中状态是否改变(一般在单选框或者两态的复选框中使用)。
  • QWidget:

    • windowTitleChanged(QString):窗口标题改变信号;
    • windowIconChanged(QIcon):窗口图标改变信号;
    • customContextMenuRequested(QPoint):自定义上下文菜单请求信号。

    PS:设置上下文菜单的函数是setContextMenuPolicy(参数),其中参数有如下两种:

    • Qt.DefaultContextMenu:默认上下文菜单设置,调用对象方法contextMenuEvent()
    • Qt.CustomContextMenu:自定义上下文菜单设置,发射信号customContextMenuRequested(QPoint)
右键菜单(上下文菜单):有默认和自定义两种方法

默认:

class Window(QWidget):
    def contextMenuEvent(self, evt):
        # *******************设置菜单*******************开始
        menu = QMenu(self)
        new_action = QAction("新建", menu)
        new_action.triggered.connect(lambda: print("新建文件"))

        open_action = QAction("打开", menu)
        open_action.triggered.connect(lambda: print("打开文件"))

        exit_action = QAction("退出", menu)
        exit_action.triggered.connect(lambda: print("退出程序"))

        open_recent_menu = QMenu("最近打开", menu)
        # open_recent_menu.setTitle("最近打开")
        file_action = QAction("python-gui")
        open_recent_menu.addAction(file_action)

        menu.addAction(new_action)
        menu.addAction(open_action)
        menu.addMenu(open_recent_menu)
        menu.addSeparator()
        menu.addAction(exit_action)

        menu.exec_(evt.globalPos())
        # *******************设置菜单*******************结束

image-20220217214053744

自定义:

# *******************自定义上下文菜单*******************开始
def show_menu(point):
    # *******************设置菜单*******************开始
    menu = QMenu(window)
    new_action = QAction("新建", menu)
    new_action.triggered.connect(lambda: print("新建文件"))

    open_action = QAction("打开", menu)
    open_action.triggered.connect(lambda: print("打开文件"))

    exit_action = QAction("退出", menu)
    exit_action.triggered.connect(lambda: print("退出程序"))

    open_recent_menu = QMenu("最近打开", menu)
    # open_recent_menu.setTitle("最近打开")
    file_action = QAction("python-gui")
    open_recent_menu.addAction(file_action)

    menu.addAction(new_action)
    menu.addAction(open_action)
    menu.addMenu(open_recent_menu)
    menu.addSeparator()
    menu.addAction(exit_action)

    # 局部-->全局
    dest_point = window.mapToGlobal(point)
    menu.exec_(dest_point)
    # *******************设置菜单*******************结束


window.setContextMenuPolicy(Qt.CustomContextMenu)
window.customContextMenuRequested.connect(show_menu)

# *******************上下文菜单*******************结束

注意:menu.exec_(QPoint)获取的是相对于桌面的坐标,所以获取鼠标位置也应该是全局位置。在默认那里全局位置直接通过事件的globalPos()方法来获得,在自定义那里发射信号传出来的是局部坐标(可以通过槽函数接收参数并打印得知),需要映射方法window.mapToGlobal(point)。

(二)QCommandLinkButton(命令链接按钮)

1、描述

命令链接是Windows Vista引入的新控件;

它的用途类似于单选按钮的用途,因为它用于在一组互斥选项之间进行选择;

命令链接按钮不应单独使用,而应作为向导和对话框中单选按钮的替代选项;

外观通常类似于**平面按钮(扁平化)**的外观,但除了普通按钮文本之外,它还允许描述性文本。

2、继承

QObject——QWidget——QAbstractButton——QPushButton——QCommandLinkButton

3、功能作用
创建命令链接按钮(构造函数)
  • QCommandLinkButton(parent)
  • QCommandLinkButton(text, parent)
  • QCommandLinkButton(text, description ,parent)
btn = QCommandLinkButton("标题", "描述", window)

image-20220218121509274

设置标题、描述、图标
btn = QCommandLinkButton("标题", "描述", window)
btn.setText("新的标题就是")
btn.setDescription("这个链接按钮功能不多欸")
btn.setIcon(QIcon("star.png"))

image-20220218122308445

4、信号

同QPushButton

(三)QRadioButton

1、描述

一般用于给用户提供若干选项中的单选操作,比如:性别不是男就是女;判断题答案不是是就是否…当选中一个时, 会自动取消上一个。此按钮左侧会有一个圆圈图标,用于标识用户的选中状态。

2、继承

QObject——QWidget——QAbstractButton——QRadioButton

3、功能作用
创建单选按钮
  • QRadioButton(parent)

  • QRadioButton(text, parent)

    rb_man = QRadioButton("男", window)
    rb_man.move(100, 100)
    rb_woman = QRadioButton("女", window)
    rb_woman.move(100, 150)
    

image-20220219102534341

如果只有一个单选按钮,可选可不选;如果同组有两个及以上,至少得选一个。

常用继承父类操作
  • setIcon(QIcon):设置图标

    rb_man.setIcon(QIcon("star.png"))
    rb_man.setIconSize(QSize(60, 60))
    # 设置默认选中的按钮
    rb_woman.setChecked(True)
    
  • setShortcut():

    • 设置快捷键

      rb_man.setShortcut("Alt+M")
      
    • 借助&(必须是按钮标题里含有的字母)

      rb_man = QRadioButton("男-&Man", window)
      
4、信号

均继承自父类(pressed、released、clicked、toggled)

常用信号为:toggled(bool)切换信号

rb_woman.toggled.connect(lambda ischecked: print(ischecked))
5、多组互斥问题
# *******************多组互斥问题*******************开始
rb_man = QRadioButton("男", window)
rb_man.move(100, 100)
rb_woman = QRadioButton("女", window)
rb_woman.move(100, 150)

rb_yes = QRadioButton("yes", window)
rb_no = QRadioButton("no", window)
rb_yes.move(200, 100)
rb_no.move(200, 150)
# *******************多组互斥问题*******************结束

四个按钮都互斥:

image-20220219110629949

解决方法一:不要放在同一个父控件内

# *******************多组互斥问题*******************开始
red = QWidget(window)
red.resize(200, 200)
red.setStyleSheet("background-color:red")
red.move(50, 50)

green = QWidget(window)
green.resize(200, 200)
green.setStyleSheet("background-color:green")
green.move(270, 50)

rb_man = QRadioButton("男", red)
rb_man.move(10, 10)
rb_woman = QRadioButton("女", red)
rb_woman.move(10, 50)

rb_yes = QRadioButton("yes", green)
rb_no = QRadioButton("no", green)
rb_yes.move(10, 10)
rb_no.move(10, 50)
# *******************多组互斥问题*******************结束

image-20220219111210947

解决方法二:抽象按钮组QButtonGroup

(三.2)QButtonGroup 按钮组

1、描述

提供一个抽象的按钮容器,可以将多个按钮划分为一组。不具备可视化的效果,一般放的都是可以被检查的按钮。

2、继承

QObject——QButtonGroup

这也是为什么不可视化,QWidget是所有可视化控件的基类。

3、功能
(1)创建按钮组
  • QButtonGroup(parent)
(2)添加按钮
  • addButton(QAbstractButton, id = -1) ID相当于一个标识
    • 如果ID为-1,则将为该按钮分配一个,自动分配的ID保证为负数,从-2开始依次往下;
    • 如果要分配自己的ID,请使用正值以避免冲突。

应用场景:向按钮组中添加按钮, 并选择性设置ID。

# *******************按钮组*******************开始
r_male = QRadioButton("男", window)
r_female = QRadioButton("女", window)
r_male.move(100, 100)
r_female.move(100, 150)

r_yes = QRadioButton("是", window)
r_no = QRadioButton("否", window)
r_yes.move(300, 100)
r_no.move(300, 150)

sex_group = QButtonGroup(window)
sex_group.addButton(r_male)
sex_group.addButton(r_female)

yes_group = QButtonGroup(window)
yes_group.addButton(r_yes)
yes_group.addButton(r_no)
# *******************按钮组*******************结束

image-20220219114143669

(3)查看按钮
  • buttons():查看所有按钮组中的按钮;

    print(sex_group.buttons())
    

    输出:[<PyQt5.QtWidgets.QRadioButton object at 0x0000020812A0EEE8>, <PyQt5.QtWidgets.QRadioButton object at 0x0000020812A0EF78>]

  • button(ID):根据ID获取对应按钮, 没有则返回None;

    sex_group.addButton(r_male, 1)
    sex_group.addButton(r_female, 2)
    
    print(sex_group.button(2))
    

    输出:<PyQt5.QtWidgets.QRadioButton object at 0x0000020812A0EF78>

  • checkedButton():获取选中的那个按钮。

    r_male.setChecked(True)
    print(sex_group.checkedButton())
    

    输出:<PyQt5.QtWidgets.QRadioButton object at 0x0000020812A0EEE8>

应用场景:获取指定条件的按钮。

(4)移除按钮
  • removeButton(QAbstractButton)

应用场景:移除指定按钮组关系,不是从界面上移除,是从抽象关系上移除。

sex_group.removeButton(r_female)
print(sex_group.buttons())
print(sex_group.button(2))

输出:[<PyQt5.QtWidgets.QRadioButton object at 0x000001A8E72BEEE8>] ;None

image-20220219115614295

(5)绑定和获取ID
  • setId(QAbstractButton,int):适用于添加按钮时没有传递id值。
  • id(QAbstractButton):指定按钮对应的ID;如果不存在此按钮,则返回-1
  • checkedId():选中的ID;如果没有选中按钮则返回-1

应用场景:设置ID, 方便识别用户选项。

# *******************绑定和获取ID*******************开始
yes_group.setId(r_yes, 1)
yes_group.setId(r_no, 2)
print(yes_group.id(r_no))
print(yes_group.id(r_yes))
print(yes_group.id(r_male))
print(yes_group.checkedId())
r_yes.setChecked(True)
print(yes_group.checkedId())
# *******************绑定和获取ID*******************结束

输出:2、1、-1、-1、1

(6)独占设置
  • setExclusive(bool)
  • exclusive()

应用场景:统一设置按钮组中的按钮是否是独占(选择互斥)

sex_group.setExclusive(False)

sex_group:可都选,可选任一,可不选。

4、信号
  • buttonClicked(int/QAbstractButton):当按钮组中的按钮被点击时, 发射此信号;
  • buttonPressed(int/QAbstractButton):当按钮组中的按钮被按下时, 发射此信号;
  • buttonReleased(int/QAbstractButton):当按钮组中的按钮被释放时, 发射此信号;
  • buttonToggled(QAbstractButton/int, bool):当按钮组中的按钮被切换状态时, 发射此信号。(点击后会有两个信号,因为两个按钮的状态变化了)
# *******************信号*******************开始
def test(val):
    print(val)


sex_group.buttonClicked.connect(test)
# *******************信号*******************结束

输出的是这样的:<PyQt5.QtWidgets.QRadioButton object at 0x000001CD6C20AF78>

重点注意:

  1. 参数可以是整型也可以是按钮,整型代表ID。

  2. 如果一个对象向外界提供的信号名称一样,但参数不一样,可以使用如下格式进行选择:

    signal_name[type] 表示 信号名称[参数类型]

所以如果先要输出按钮ID,有两种方法:

方法一:直接接收int型

sex_group.buttonClicked[int].connect(test)

方法二:在槽函数中获取id

def test(val):
    print(sex_group.id(val))

(四)QCheckBox

1、描述

一般用于给用户提供若干选项中的多选操作,可以都选,也可以都不选,也可以选部分。左侧会有一个方框图标, 标识用户的选中状态。

2、继承

QObject——QWidget——QAbstractButton——QCheckBox

查看父类除了看定义,还可以直接打印print(QCheckBox.__bases__)

3、功能作用
(1)创建复选框按钮
  • QCheckBox(parent=None)
  • QCheckBox(str, parent=None)
(2)常用继承父类操作
  • 图标:setIcon(QIcon)
  • 快捷键:文本加& 或 setShortcut()
(3)设置是否三态
  • setTristate(bool=True)
  • isTristate()

应用场景:是否支持复选框展示三种状态(未选中、部分选中、选中)

(4)设置复选框状态
  • setCheckState(Qt.CheckState):因为是三态,不能简单地setChecked(bool)两种状态。
    • Qt.Unchecked——该项目未选中image-20220219125318905
    • Qt.PartiallyChecked——部分选中image-20220219125351137
    • Qt.Checked——真的被选中image-20220219125401046
  • checkState()

应用场景:想给用户多一种选择状态

4、信号

除了继承的,特有:

  • stateChanged(int state):选中或清除选中时, 发射此信号,作为toggled(bool checked)的替代,toggled只会区别选中和未选中,无法识别PartiallyChecked和Checked的切换。
cb = QCheckBox("python", window)
cb.setTristate(True)
cb.stateChanged.connect(lambda state: print(state))

(五)QToolButton

1、描述

提供了一个快速访问按钮,通常是在工具栏内部使用,工具按钮通常不显示文本标签,而是显示图标。

image-20220218171940905

2、继承

QObject——QWidget——QAbstractButton——QToolButton

3、功能作用
创建按钮

QToolButton(parent: QWidget = None)

(继承自QAbstractButton) 设置文本、图标、工具提示
  • setText(str)
  • setIcon(QIcon)
  • setIconSize(QSize)
  • setToolTip(str):提示图标作用。

注意:如果文本和图标同时设置, 则默认只展示图标。

btn = QToolButton(window)
btn.setText("工具栏")
btn.setIcon(QIcon("star.png"))
btn.setIconSize(QSize(60, 60))
btn.setToolTip("新建按钮")

image-20220218173654105

按钮样式风格(设置按钮的图标和文字组合)
  • setToolButtonStyle(Qt.ToolButtonStyle(可选如下)):风格取值

    • Qt.ToolButtonIconOnly:仅显示图标

      image-20220218174257981

    • Qt.ToolButtonTextOnly:仅显示文字

      image-20220218174319297

    • Qt.ToolButtonTextBesideIcon:文本显示在图标旁边

      image-20220218174439508

    • Qt.ToolButtonTextUnderIcon:文本显示在图标下方

      image-20220218174506611

    • Qt.ToolButtonFollowStyle:遵循风格(不管)

      image-20220218174529718

  • toolButtonStyle():获取样式,可手动打印。

设置箭头(比如浏览器的前进和后退)
  • setArrowType(Qt.ArrowType(同上,也是个枚举类型))

    • Qt.NoArrow:无箭头

      image-20220218174914758

    • Qt.UpArrow:向上箭头

      image-20220218174933773

    • Qt.DownArrow:向下箭头

      image-20220218175034246

    • Qt.LeftArrow:向左箭头

      image-20220218175057748

    • Qt.RightArrow:向右箭头

      image-20220218175115293

  • arrowType():获取箭头类型。

PS:箭头优先级高于图标。

自动提升(非扁平化、突起)
  • setAutoRaise(bool)
  • autoRaise()

应用场景:

在自动提升模式下,该按钮仅在鼠标指向时才会绘制3D帧(突起),在工具栏(QToolBar)中默认就是自动提升。

一般按钮(QPushButton):如果设置了扁平化,不管鼠标放不放上去,都是扁平;但如果不设置扁平化,鼠标不移过去也是突起状态,移过去发光。

工具按钮:没有扁平化这个设置。如果设置了自动提升,不易过去是扁平化,移过去是发光,更加美观;如果没有设置自动提升,同没有设置扁平化的一般按钮。

菜单
  • setMenu(QMenu)
  • menu()

应用场景:通过菜单展示更多选项

菜单弹出模式
  • setPopupMode(QToolButton.ToolButtonPopupMode)

    • QToolButton.DelayedPopup:默认,鼠标按住一会才显示。

      image-20220218201304279

      实际应用:类似于浏览器后退按钮,按住停一会后不会后退,而是显示如下

      image-20220218182337270

    • QToolButton.MenuButtonPopup:有一个专门的指示箭头,点击箭头才显示。

      image-20220218201355971

    • QToolButton.InstantPopup:点了按钮就显示。

      image-20220218201430117

    延迟弹出分割线发射单击信号
    QToolButton.DelayedPopup
    QToolButton.MenuButtonPopup
    QToolButton.InstantPopup

    有分割线时:点击右边的箭头是弹出菜单,点击左边是触发单击。

  • popupMode()

应用场景:设置菜单弹出的触发方式。

4、信号

除了继承的,只有一个是特有的,是原来的triggered信号重写得到的。

  • triggered(QAction *action):当点击某个action时触发,并会将action传递出来。

    QAction对象可以通过==setData(Any)==绑定数据,==data()==获取数据。

例1:

btn = QToolButton(window)
btn.setText("工具栏")

menu = QMenu(btn)
menu.setTitle("菜单")

sub_menu = QMenu(menu)
sub_menu.setTitle("子菜单")
sub_menu.setIcon(QIcon("star.png"))

action1 = QAction("打开1", menu)
action2 = QAction("打开2", menu)
# action1.triggered.connect(lambda: print("点击了行为菜单"))

menu.addMenu(sub_menu)
menu.addSeparator()
menu.addAction(action1)
menu.addAction(action2)

btn.setMenu(menu)
btn.setPopupMode(QToolButton.InstantPopup)


def do_action(action):
    print("点击了行为", action)


btn.triggered.connect(do_action)

点击了【打开1】和【打开2】后,输出

image-20220218214411792

如果想要不同的行为执行不同事件,除了每个action写一个槽函数还有什么方法?

例2:

action1.setData([1, 2, 3])
action2.setData({"心情": "抑郁"})

def do_action(action):
    print("点击了行为", action.data())

btn.triggered.connect(do_action)

输出:

image-20220218214441023

这就提示我们可以给不同的行为绑定不同的数据,通过不同的数据执行不同的操作,比给每个行为单独连接信号要方便很多。


侵权即删

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值