pyside6自定义部件库和软件框架的建设记录

自定义的部件库原则上尽量做到前后端分离,接口方便,复制简单。

单选框部件

# encoding: utf-8
###################################################
#               自定义的单选框
###################################################

# 对外接口:
# stateNum = Signal(int)  状态号,从1开始,是几就几被选中
# customSetup():   # 定制的初始化程序


import PySide6
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QWidget, QGroupBox, QFrame


class PysideCustomRadiobutton(QFrame):
    stateNum = Signal(int)    # 状态号,从1开始,是几就几被选中

    def __init__(self, parent=None):
        super().__init__(parent)
        self.RadioButtons = []

    def customSetupUi(self):   # 定制的初始化程序
        self.RadioButtons = self.findChildren(PySide6.QtWidgets.QRadioButton)   # 部件中所有的单选按钮
        self.RadioButtons.sort(key=lambda child: child.objectName())    # 按名称排序

        for i in range(len(self.RadioButtons)):
            def callback(idx):
                return lambda: self.stateNum.emit(idx+1)
            self.RadioButtons[i].clicked.connect(callback(i))     # 单击按钮后发射信号

        self.stateNum.connect(self.changeState)                   # 状态号信号的连接

        self.stateNum.emit(1)                                     # 初始化状态下,状态1被选中

    def changeState(self, thisTurnOn):    # 改变状态
        self.RadioButtons[thisTurnOn-1].setChecked(True)




前端的范例: 

框架的建立和调用

# 阶段v1的调用
import sys
from time import strftime

from PySide6.QtCore import QObject, Signal, QTimer
from PySide6.QtWidgets import QWidget, QApplication, QMainWindow
import template_rc  # 导入需要显示的画面


# ############导入并需要显示的画面集中在这里定义#############################
# ############template.ui的显示#############################
class MainWindow(QMainWindow, template_rc.Ui_MainWindow):  # 定义需要显示的画面类
    def __int__(self):
        super().__init__()


# ########################部件初始化的通用函数###################################
def init_widgets(widget):  # 画面里的部件的初始化
    sons = widget.children()  # 儿辈部件

    def find_child(child):  # 查找子部件
        try:
            child.customSetupUi()  # 自定义的初始化
        except AttributeError:
            pass

        if child.children():
            for grandson in child.children():
                find_child(grandson)  # 递归查找

    for son in sons:
        find_child(son)


# #############################主程序###################################
if __name__ == '__main__':
    app = QApplication(sys.argv)

    # #######################本项目的定义###################################
    class UI(QObject):
        # ##########项目范围内的信号#############
        sysClock_1S = Signal()  # 秒时钟信号

        # ##########定时器#############
        timer_1s = QTimer()  # 定义全局0.1s的周期定时器
        timer_1s.start(1000)

        # ###########__init__###############
        def __init__(self):
            super().__init__()
            self.widgets = []  # 所有的视窗列表


    # ########################本项目的实例化###################################
    ui = UI()

    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    mainWindow = MainWindow()
    mainWindow.setupUi(mainWindow)  # 模板画面的本体初始化
    init_widgets(mainWindow)  # 模板画面的部件初始化
    mainWindow.show()
    ui.widgets.append(mainWindow)  # 将画面加入视窗列表,方便管理

    # ###########################信号的连接####################################
    # ###########################项目级别信号的连接###############################
    ui.timer_1s.timeout.connect(ui.sysClock_1S.emit)
    ui.sysClock_1S.connect(lambda: mainWindow.labelSystemClock.setText(strftime('%Y-%m-%d %H:%M:%S')))
    # ###########################mainWindow画面信号的连接######################
    mainWindow.RadioButtons_1.stateNum.connect(lambda x: mainWindow.label_1.setText(str(x)))
    mainWindow.pushButton_1.clicked.connect(lambda: mainWindow.RadioButtons_1.stateNum.emit(1))
    mainWindow.doubleSpinBox_1.valueChanged.connect(lambda x: mainWindow.label_22.setText(str(x)))

    # ###########################槽函数####################################

    sys.exit(app.exec())

运行截图:

本阶段的资源链接:(v1)https://download.csdn.net/download/xulibo5828/89120987?spm=1001.2101.3001.9499

自定义功能的仪表盘

        一个具有设定值输入、微调,实时值显示,历史曲线实时显示的仪表盘。

        在CAD软件中大致规划一下功能区的尺寸和排列:

         功能和分工规划:编程阶段可视的部件在QT designer中完成部署和设置,运行阶段可视的动态部件在程序中根据QT designer中的设置值自动计算和部署。

        对外接口:外部传入设定值和实时值。

        画面设计:在QT Designer里面完成画面的组态,布置和复制部件也仅在QT Designer中进行。部件的总容器和历史数据显示窗口用QFrame,进度条和历史曲线的显示在程序里用QPainter实现。历史曲线尝试过用专门的绘图库matplotlib,这个库在嵌入pyside6的部件时无法做到0边距无缝衔接,左右两边无法布满pyside6的部件。如下图:

所以,还是决定用QPainter的 drawline来实现。

在QT Designer里设计好部件的各个组件:

 为之配套编写代码,命名为PysideCustomDashboard.py,并将部件“提升为”这个自定义的类。

 部件的代码:

# encoding: utf-8
###################################################
#               自定义的仪表盘
###################################################

# 对外接口:
#   ActualValueInput = Signal(float)  # 从外部传入的实时值
#   customSetup():   # 定制的初始化程序


import PySide6
from PySide6.QtCore import Signal, Qt, QPoint
from PySide6.QtGui import QColor, QPen, QPainter
from PySide6.QtWidgets import QFrame


class PysideCustomDashboard(QFrame):
    ActualValueInput = Signal(float)  # 从外部传入的实时值
    PresetValueInput = Signal(float)  # 从外部传入的设定值
    PresetValueOutput = Signal(float)  # 向外部传出的设定值

    def __init__(self, parent=None):
        super().__init__(parent)
        # self.preset_value = 0.0            # 预设值的value
        self.processBar_preset_width = 0  # 预设值进度条的宽度
        self.processBar_preset_radius = 0  # 预设值进度条的半径
        self.processBar_actual_radius = 0  # 实时值进度条的半径
        self.processBar_y_start = 0  # 进度条的外轮廓距y方向边缘距离
        self.processBar_x_start = 0  # 进度条的外轮廓距x方向边缘距离
        self.center_point = QPoint(0, 0)  # 部件的中心坐标

        self.actual_text_color = QColor()  # 实时值窗口文字颜色
        self.spinBox_preset_text_color = QColor()  # 预设值窗口文字颜色
        self.progressBar_backColor = QColor('#515d80')  # 进度条背景色
        self.frame_history_Palette = None  # 历史曲线显示窗口的调色板
        self.frame_history_styleSheet = None  # 历史曲线显示窗口的样式表
        self.frame_history_geometry = None  # 历史曲线显示窗口的几何特征

        self.label_name = None  # 仪表盘名称文字框
        self.label_unit = None  # 显示单位文字框
        self.label_actual = None  # 实时值的显示文字框
        self.spinBox_preset = None  # 带微调的设置值输入部件
        self.frame_history = None  # 历史曲线显示窗口

        self.begin_degree = 225  # 进度条总的起始角度
        self.span_degree = -225  # 进度条总的跨度角度

        self.actual_begin_degree = 225  # 实时值的进度条起始角度
        self.actual_span_degree = 0  # 实时值的进度条跨度始角度

        self.preset_begin_degree = 225  # 设定值的进度条起始角度
        self.preset_span_degree = 0  # 设定值的进度条跨度始角度

        self.min_value = 0.0  # 最小值
        self.max_value = 100.0  # 最大值
        self.processBar_actual_width = 0  # 进度条的宽度
        self.processBar_center = QPoint(0, 0)  # 进度条的中心
        self.points = 10  # 显示的点数

    # #######################定制的初始化程序###########################
    def customSetupUi(self):  # 定制的初始化程序

        # ######################子部件的定义############################
        children = self.children()
        for child in children:
            # ##############历史曲线显示窗口#####################
            if 'frame_history' in child.objectName():
                self.frame_history_geometry = child.geometry()  # 几何数据
                self.frame_history_styleSheet = child.styleSheet()  # 样式表
                self.frame_history_Palette = child.palette()  # 颜色表
            # #################带微调的设置值输入部件################
            elif 'spinBox_preset' in child.objectName():
                self.spinBox_preset = child
                p = child.palette()  # 颜色表
                self.spinBox_preset_text_color = p.color(p.ColorRole.Text)  # 获取预设值窗口文字颜色
                self.min_value = child.minimum()  # 最小值
                self.max_value = child.maximum()  # 最大值
            # ###################实时值的显示文字框###################
            elif 'label_actual' in child.objectName():
                self.label_actual = child
                p = child.palette()  # 颜色表
                self.actual_text_color = p.color(p.ColorRole.Text)  # 获取实时值窗口文字颜色
            # #################显示单位文字#######################
            elif 'label_unit' in child.objectName():
                self.label_unit = child
            # ##############仪表盘名称文字####################
            elif 'label_name' in child.objectName():  #
                self.label_name = child

        # ##################本体几何参数########################
        self.center_point = QPoint(int(self.width() / 2), int((self.height() / 2)))  # 中心点坐标

        # ####################历史曲线显示窗口的定义###################
        self.frame_history = CustomLineChart(self.spinBox_preset_text_color, self.actual_text_color, self.min_value,
                                             self.max_value, self.points, self)  # 实体化历史曲线显示窗口
        self.frame_history.setGeometry(self.frame_history_geometry)  # 克隆几何尺寸
        self.frame_history.setStyleSheet(self.frame_history_styleSheet)  # 克隆样式表
        self.frame_history.setPalette(self.frame_history_Palette)  # 克隆颜色表
        self.frame_history.show()  # 显示
        # self.frame_history.customSetupUi()  # 历史曲线显示窗口初始化

        # ####################进度条的定义##############################
        self.processBar_actual_width = int((self.width() / 50))  # 实时值进度条的宽度
        # self.processBar_preset_width = self.processBar_actual_width  # 预设值进度条的宽度
        self.processBar_preset_width = int(self.processBar_actual_width * 0.66)  # 预设值进度条的宽度
        # self.processBar_preset_width = int(self.processBar_actual_width / 3)
        self.processBar_x_start = int(self.width() / 20)  # 进度条的外轮廓距x方向边缘距离
        self.processBar_y_start = int(self.width() / 20)  # 进度条的外轮廓距y方向边缘距离
        self.processBar_actual_radius = int(
            (self.width() / 2) - self.processBar_x_start - (self.processBar_actual_width / 2) * 0.9)  # 实时值进度条的半径
        self.processBar_preset_radius = int(
            self.processBar_actual_radius - self.processBar_actual_width)  # 预设值进度条的半径

        self.signal_handing([self.spinBox_preset.value(), 'preset'])  # 初始化一下预设值进度条的显示

        # ######################信号的连接############################
        self.ActualValueInput.connect(lambda x: self.signal_handing([x, 'actual']))  # 接收到外部传入实时数据后的信号处理
        self.PresetValueInput.connect(self.spinBox_preset.setValue)    # 接收到外部传入设置值后的信号处理
        self.spinBox_preset.valueChanged.connect(lambda x: self.signal_handing([x, 'preset']))  # 设置值发生改变后的信号处理

    # #######################发射信号的处理############################
    def signal_handing(self, args):
        if args[1] == 'actual':  # 如果是实时值发射的信号
            self.frame_history.PointValues.emit(self.spinBox_preset.value(), args[0])  # 将预设值和实际值打包发送到历史曲线的部件的输入信号
            self.label_actual.setText(str(args[0]))  # 实时显示实际值的数字

            self.actual_span_degree = int(
                (args[0] - self.min_value) / (self.max_value - self.min_value) * self.span_degree)  # 计算实时值进度条的角度
            self.update()  # 刷新画面

        else:  # 如果是设定值发射的信号
            self.frame_history.PointValues.emit(self.spinBox_preset.value(),
                                                float(self.label_actual.text()))  # 将预设值和实际值打包发送到历史曲线的部件的输入信号

            self.preset_span_degree = int(
                (args[0] - self.min_value) / (self.max_value - self.min_value) * self.span_degree)  # 计算设定值进度条的角度
            self.update()  # 刷新画面

    # ########################绘制进度条圆弧###########################
    def draw_arc(self, color, center, startAngle, spanAngle, width, radius):
        painter = QPainter(self)  # 设定画板
        painter.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
        painter.setPen(QPen(color, width, Qt.SolidLine))  # 设置画笔颜色、粗细和线型
        painter.drawArc(center[0] - radius, center[1] - radius, radius * 2, radius * 2, startAngle * 16, spanAngle * 16)

    # #########################重写paintEvent########################
    def paintEvent(self, event):
        # ##################绘制实时值背景进度条###############################
        self.draw_arc(self.progressBar_backColor, (self.center_point.x(), self.center_point.y()), self.begin_degree,
                      self.span_degree, self.processBar_actual_width, self.processBar_actual_radius)

        # ##################绘制设置值背景进度条###############################
        self.draw_arc(self.progressBar_backColor, (self.center_point.x(), self.center_point.y()), self.begin_degree,
                      self.span_degree, self.processBar_preset_width, self.processBar_preset_radius)

        # ##################绘制实时值的显示进度条###############################
        self.draw_arc(self.actual_text_color, (self.center_point.x(), self.center_point.y()), self.actual_begin_degree,
                      self.actual_span_degree, self.processBar_actual_width, self.processBar_actual_radius)

        # ##################绘制设置值的显示进度条###############################
        self.draw_arc(self.spinBox_preset_text_color, (self.center_point.x(), self.center_point.y()),
                      self.preset_begin_degree,
                      self.preset_span_degree, self.processBar_preset_width, self.processBar_preset_radius)


# #########################历史曲线显示窗口的class定义########################
class CustomLineChart(QFrame):  # 自定义的折线表
    PointValues = Signal(float, float)  # 点值,设置值在前,实时值在后

    def __init__(self, preset_color, actual_color, min_value, max_value, points, parent=None):
        super().__init__(parent)
        self.points = points  # 显示的点数
        self.preset_value_points = [0.0]  # 设置值的数据点集
        self.actual_value_points = [0.0]  # 实时值的数据点集
        self.overflow = False  # 数据超量程

        self.background_color = QColor()  # 背景色
        self.preset_color = preset_color  # 预置值颜色
        self.actual_color = actual_color  # 实时值颜色
        self.preset_pen = QPen()  # 预设值波形的画笔
        self.actual_pen = QPen()  # 实时值波形的画笔
        self.min_value = min_value  # 最小值
        self.max_value = max_value  # 最大值

        self.x_points = []  # X轴的分度
        self.x_step = 0  # X轴的步调节拍

    def customSetupUi(self):  # 定制的初始化程序
        # #####################建立x轴的分度表############################
        x = 0
        s = self.width() / (self.points - 1)
        for i in range(self.points):
            self.x_points.append(int(x))
            x += s

        # #####################初始化颜色特征############################
        p = self.palette()  # 获取调色板
        self.background_color = p.color(p.ColorRole.Window)  # 获取背景色
        self.preset_pen = QPen(self.preset_color, 1)  # 预置值的笔
        self.actual_pen = QPen(self.actual_color, 1)  # 实时值的笔

        # #####################信号的连接############################
        self.PointValues.connect(self.pretreat)  # 当传入值以后预处理数据
        self.PointValues.connect(self.update)  # 当传入值以后更新画面

    def pretreat(self, preset_value, actual_value):  # 数据的预处理
        # #####################预设值数据的预处理############################
        k = (preset_value - self.min_value) / (self.max_value - self.min_value)
        v = int(self.height() * (1 - k))
        self.preset_value_points.append(v)
        if len(self.preset_value_points) > self.points:
            del self.preset_value_points[0]

        # #####################实时值数据的预处理############################
        if actual_value < self.min_value:  # 输入值超出量程
            actual_value = self.min_value
            self.overflow = True
        elif actual_value > self.max_value:
            actual_value = self.max_value
            self.overflow = True
        else:
            self.overflow = False

        k = (actual_value - self.min_value) / (self.max_value - self.min_value)  # 显示比例转换
        v = int(self.height() * (1 - k))
        self.actual_value_points.append(v)
        if len(self.actual_value_points) > self.points:
            del self.actual_value_points[0]

    # ############################绘图事件####################################
    def paintEvent(self, event):  # 重新定义paintEvent
        painter = QPainter(self)  # 设定画板
        painter.setPen(Qt.NoPen)  # 设定画笔

        # #########################重画背景###################################
        if self.overflow:
            color = QColor('#363636')
        else:
            color = self.background_color
        painter.setBrush(color)  # 设置笔刷
        painter.drawRect(0, 0, self.width(), self.height())  # 重画背景

        # #########################绘制预设值的折线#############################
        pen = QPen(self.preset_color)
        pen.setWidth(1)
        painter.setPen(pen)
        if len(self.preset_value_points) > 1:
            i = 1
            while i < len(self.preset_value_points):
                painter.drawLine(self.x_points[i - 1], int(self.preset_value_points[i - 1]), self.x_points[i],
                                 int(self.preset_value_points[i]))
                i += 1

        # #########################绘制实时值的折线#############################
        pen = QPen(self.actual_color)
        pen.setWidth(1)
        painter.setPen(pen)
        if len(self.actual_value_points) > 1:
            i = 1
            while i < len(self.actual_value_points):                
                painter.drawLine(self.x_points[i - 1], int(self.actual_value_points[i - 1]),
                                 self.x_points[i], int(self.actual_value_points[i]))
                i += 1

 编写调用程序:基本的调用框架.py

# 阶段v1的调用
import random
import sys
from time import strftime

from PySide6.QtCore import QObject, Signal, QTimer
from PySide6.QtWidgets import QApplication, QMainWindow

import template_rc  # 导入需要显示的画面
import 按钮图标_rc


# ############导入并需要显示的画面集中在这里定义#############################
# ############template.ui的显示#############################
class MainWindow(QMainWindow, template_rc.Ui_MainWindow):  # 定义需要显示的画面类
    def __int__(self):
        super().__init__()


# ########################部件初始化的通用函数###################################
def init_widgets(widget):  # 画面里的部件的初始化
    sons = widget.children()  # 儿辈部件

    def find_child(child):  # 查找子部件
        try:
            child.customSetupUi()  # 自定义的初始化
        except AttributeError:
            pass

        if child.children():
            for grandson in child.children():
                find_child(grandson)  # 递归查找

    for son in sons:
        find_child(son)


def test():  # 测试程序
    n1 = random.randint(-300, 300)
    window1.dashboard_1.ActualValueInput.emit(float(n1 / 100.0 + 80))


# #############################主程序###################################
if __name__ == '__main__':
    app = QApplication(sys.argv)


    # #######################项目级别的定义###################################
    class UI(QObject):  # 将项目定义为QObject,用来管理项目级别的信号和变量
        # ##########项目范围内的信号#############
        sysClock_1S = Signal()  # 秒时钟信号

        # ##########定时器#############
        timer_1s = QTimer()  # 定义全局0.1s的周期定时器

        timer_1s.start(300)

        # ###########__init__###############
        def __init__(self):
            super().__init__()
            self.widgets = []  # 所有的视窗列表


    # ########################本项目的实例化###################################
    ui = UI()

    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    window1 = MainWindow()
    window1.setupUi(window1)  # 模板画面的本体初始化
    window1.show()  # 显示画面
    ui.widgets.append(window1)  # 将画面加入视窗列表,方便管理

    # ###########################信号的连接####################################

    # # ###########################项目级别信号的连接###############################
    ui.timer_1s.timeout.connect(ui.sysClock_1S.emit)
    ui.timer_1s.timeout.connect(test)
    ui.sysClock_1S.connect(lambda: window1.labelSystemClock.setText(strftime('%Y-%m-%d %H:%M:%S')))

    # ###########################Window1画面信号的连接######################
    # ###########################槽函数####################################

    init_widgets(window1)  # 画面的子部件初始化

    sys.exit(app.exec())

运行截图:

 

进一步的,在组态画面里按ctrl拖动复制一份 ,并改变一些几何和颜色特征,增加一个外部设定部件:

编写调用程序:仪表盘调用demo.py 

# 阶段v1的调用
import random
import sys
from time import strftime
from PySide6.QtCore import QObject, Signal, QTimer
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QDoubleSpinBox

import template_rc  # 导入需要显示的画面
import 按钮图标_rc


# ############导入并需要显示的画面集中在这里定义#############################
# ############template.ui的显示#############################
class MainWindow(QMainWindow, template_rc.Ui_MainWindow):  # 定义需要显示的画面类
    def __int__(self):
        super().__init__()


# ########################部件初始化的通用函数###################################
def init_widgets(widget):  # 画面里的部件的初始化
    sons = widget.children()  # 儿辈部件

    def find_child(child):  # 查找子部件
        try:
            child.customSetupUi()  # 自定义的初始化
        except AttributeError:
            pass

        if child.children():
            for grandson in child.children():
                find_child(grandson)  # 递归查找

    for son in sons:
        find_child(son)


def test():  # 测试程序
    n1 = random.randint(-300, 300)
    n2 = random.randint(-300, 300)
    window1.dashboard_1.ActualValueInput.emit(float(n1 / 100.0 + 80))
    window1.dashboard_2.ActualValueInput.emit(float(n2 / 100.0 + 150))


# #############################主程序###################################
if __name__ == '__main__':
    app = QApplication(sys.argv)


    # #######################项目级别的定义###################################
    class UI(QObject):  # 将项目定义为QObject,用来管理项目级别的信号和变量
        # ##########项目范围内的信号#############
        sysClock_1S = Signal()  # 秒时钟信号

        # ##########定时器#############
        timer_1s = QTimer()  # 定义全局0.1s的周期定时器

        timer_1s.start(1000)

        # ###########__init__###############
        def __init__(self):
            super().__init__()
            self.widgets = []  # 所有的视窗列表


    # ########################本项目的实例化###################################
    ui = UI()

    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    window1 = MainWindow()
    window1.setupUi(window1)  # 模板画面的本体初始化
    window1.show()  # 显示画面
    ui.widgets.append(window1)  # 将画面加入视窗列表,方便管理

    # ###########################信号的连接####################################

    # # ###########################项目级别信号的连接###############################
    ui.timer_1s.timeout.connect(ui.sysClock_1S.emit)
    ui.timer_1s.timeout.connect(test)
    ui.sysClock_1S.connect(lambda: window1.labelSystemClock.setText(strftime('%Y-%m-%d %H:%M:%S')))

    # ###########################Window1画面信号的连接######################
    window1.doubleSpinBox.valueChanged.connect(window1.dashboard_1.PresetValueInput.emit)

    # ###########################槽函数####################################

    init_widgets(window1)  # 画面的子部件初始化
    # QLabel
    # QDoubleSpinBox

    sys.exit(app.exec())

 运行截图:

基本实现了设计初衷 ,前后端图像和代码分离,接口和调用简单,复制部署方便。

 资源链接:(本阶段为v2)https://download.csdn.net/download/xulibo5828/89148225?spm=1001.2101.3001.9499 

20240501,增加了进度条的渐变色效果:

 改进后的仪表盘部件代码:

# encoding: utf-8
###################################################
#               自定义的仪表盘
###################################################

# 对外接口:
#   ActualValueInput = Signal(float)  # 从外部传入的实时值
#   customSetup():   # 定制的初始化程序


import PySide6
from PySide6.QtCore import Signal, Qt, QPoint, QPointF
from PySide6.QtGui import QColor, QPen, QPainter, QConicalGradient
from PySide6.QtWidgets import QFrame


class PysideCustomDashboard(QFrame):
    ActualValueInput = Signal(float)  # 从外部传入的实时值
    PresetValueInput = Signal(float)  # 从外部传入的设定值
    PresetValueOutput = Signal(float)  # 向外部传出的设定值

    def __init__(self, parent=None):
        super().__init__(parent)
        # self.preset_value = 0.0            # 预设值的value
        self.processBar_preset_width = 0  # 预设值进度条的宽度
        self.processBar_preset_radius = 0  # 预设值进度条的半径
        self.processBar_actual_radius = 0  # 实时值进度条的半径
        self.processBar_y_start = 0  # 进度条的外轮廓距y方向边缘距离
        self.processBar_x_start = 0  # 进度条的外轮廓距x方向边缘距离
        self.center_point = QPoint(0, 0)  # 部件的中心坐标

        self.actual_text_color = QColor()  # 实时值窗口文字颜色
        self.spinBox_preset_text_color = QColor()  # 预设值窗口文字颜色
        self.progressBar_backColor = QColor('#515d80')  # 进度条背景色
        self.frame_history_Palette = None  # 历史曲线显示窗口的调色板
        self.frame_history_styleSheet = None  # 历史曲线显示窗口的样式表
        self.frame_history_geometry = None  # 历史曲线显示窗口的几何特征

        self.label_name = None  # 仪表盘名称文字框
        self.label_unit = None  # 显示单位文字框
        self.label_actual = None  # 实时值的显示文字框
        self.spinBox_preset = None  # 带微调的设置值输入部件
        self.frame_history = None  # 历史曲线显示窗口

        self.begin_degree = 225  # 进度条总的起始角度
        self.span_degree = -225  # 进度条总的跨度角度

        self.actual_begin_degree = 225  # 实时值的进度条起始角度
        self.actual_span_degree = 0  # 实时值的进度条跨度始角度

        self.preset_begin_degree = 225  # 设定值的进度条起始角度
        self.preset_span_degree = 0  # 设定值的进度条跨度始角度

        self.min_value = 0.0  # 最小值
        self.max_value = 100.0  # 最大值
        self.processBar_actual_width = 0  # 进度条的宽度
        self.processBar_center = QPoint(0, 0)  # 进度条的中心
        self.points = 10  # 显示的点数

    # #######################定制的初始化程序###########################
    def customSetupUi(self):  # 定制的初始化程序

        # ######################子部件的定义############################
        children = self.children()
        for child in children:
            # ##############历史曲线显示窗口#####################
            if 'frame_history' in child.objectName():
                self.frame_history_geometry = child.geometry()  # 几何数据
                self.frame_history_styleSheet = child.styleSheet()  # 样式表
                self.frame_history_Palette = child.palette()  # 颜色表
            # #################带微调的设置值输入部件################
            elif 'spinBox_preset' in child.objectName():
                self.spinBox_preset = child
                p = child.palette()  # 颜色表
                self.spinBox_preset_text_color = p.color(p.ColorRole.Text)  # 获取预设值窗口文字颜色
                self.min_value = child.minimum()  # 最小值
                self.max_value = child.maximum()  # 最大值
            # ###################实时值的显示文字框###################
            elif 'label_actual' in child.objectName():
                self.label_actual = child
                p = child.palette()  # 颜色表
                self.actual_text_color = p.color(p.ColorRole.Text)  # 获取实时值窗口文字颜色
            # #################显示单位文字#######################
            elif 'label_unit' in child.objectName():
                self.label_unit = child
            # ##############仪表盘名称文字####################
            elif 'label_name' in child.objectName():  #
                self.label_name = child

        # ##################本体几何参数########################
        self.center_point = QPoint(int(self.width() / 2), int((self.height() / 2)))  # 中心点坐标

        # ####################历史曲线显示窗口的定义###################
        self.frame_history = CustomLineChart(self.spinBox_preset_text_color, self.actual_text_color, self.min_value,
                                             self.max_value, self.points, self)  # 实体化历史曲线显示窗口
        self.frame_history.setGeometry(self.frame_history_geometry)  # 克隆几何尺寸
        self.frame_history.setStyleSheet(self.frame_history_styleSheet)  # 克隆样式表
        self.frame_history.setPalette(self.frame_history_Palette)  # 克隆颜色表
        self.frame_history.show()  # 显示
        # self.frame_history.customSetupUi()  # 历史曲线显示窗口初始化

        # ####################进度条的定义##############################
        self.processBar_actual_width = int((self.width() / 50))  # 实时值进度条的宽度
        # self.processBar_preset_width = self.processBar_actual_width  # 预设值进度条的宽度
        self.processBar_preset_width = int(self.processBar_actual_width * 0.66)  # 预设值进度条的宽度
        # self.processBar_preset_width = int(self.processBar_actual_width / 3)
        self.processBar_x_start = int(self.width() / 20)  # 进度条的外轮廓距x方向边缘距离
        self.processBar_y_start = int(self.width() / 20)  # 进度条的外轮廓距y方向边缘距离
        self.processBar_actual_radius = int(
            (self.width() / 2) - self.processBar_x_start - (self.processBar_actual_width / 2) * 0.9)  # 实时值进度条的半径
        self.processBar_preset_radius = int(
            self.processBar_actual_radius - self.processBar_actual_width)  # 预设值进度条的半径

        self.signal_handing([self.spinBox_preset.value(), 'preset'])  # 初始化一下预设值进度条的显示

        # ######################信号的连接############################
        self.ActualValueInput.connect(lambda x: self.signal_handing([x, 'actual']))  # 接收到外部传入实时数据后的信号处理
        self.PresetValueInput.connect(self.spinBox_preset.setValue)    # 接收到外部传入设置值后的信号处理
        self.spinBox_preset.valueChanged.connect(lambda x: self.signal_handing([x, 'preset']))  # 设置值发生改变后的信号处理

    # #######################发射信号的处理############################
    def signal_handing(self, args):
        if args[1] == 'actual':  # 如果是实时值发射的信号
            self.frame_history.PointValues.emit(self.spinBox_preset.value(), args[0])  # 将预设值和实际值打包发送到历史曲线的部件的输入信号
            self.label_actual.setText(str(args[0]))  # 实时显示实际值的数字

            self.actual_span_degree = int(
                (args[0] - self.min_value) / (self.max_value - self.min_value) * self.span_degree)  # 计算实时值进度条的角度
            self.update()  # 刷新画面

        else:  # 如果是设定值发射的信号
            self.frame_history.PointValues.emit(self.spinBox_preset.value(),
                                                float(self.label_actual.text()))  # 将预设值和实际值打包发送到历史曲线的部件的输入信号

            self.preset_span_degree = int(
                (args[0] - self.min_value) / (self.max_value - self.min_value) * self.span_degree)  # 计算设定值进度条的角度
            self.update()  # 刷新画面

    # ########################绘制进度条圆弧###########################
    def draw_arc(self, color, center, startAngle, spanAngle, width, radius):
        painter = QPainter(self)  # 设定画板
        painter.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
        painter.setPen(QPen(color, width, Qt.SolidLine))  # 设置画笔颜色、粗细和线型
        painter.drawArc(center[0] - radius, center[1] - radius, radius * 2, radius * 2, startAngle * 16, spanAngle * 16)

    # #########################重写paintEvent########################
    def paintEvent(self, event):
        # ##################绘制实时值背景进度条###############################
        self.draw_arc(self.progressBar_backColor, (self.center_point.x(), self.center_point.y()), self.begin_degree,
                      self.span_degree, self.processBar_actual_width, self.processBar_actual_radius)
        # print(self.preset_begin_degree, self.preset_span_degree)

        # ##################绘制设置值背景进度条###############################
        self.draw_arc(self.progressBar_backColor, (self.center_point.x(), self.center_point.y()), self.begin_degree,
                      self.span_degree, self.processBar_preset_width, self.processBar_preset_radius)

        # ##################绘制实时值的显示进度条###############################
        # self.draw_arc(self.actual_text_color, (self.center_point.x(), self.center_point.y()), self.actual_begin_degree,
        #               self.actual_span_degree, self.processBar_actual_width, self.processBar_actual_radius)   # 选择1:画单色的圆弧

        gradient = QConicalGradient(self.center_point.x(), self.center_point.y(), self.actual_begin_degree + self.actual_span_degree)  # 创建锥形梯度
        color = self.actual_text_color        # 定义临时颜色
        gradient.setColorAt(0, color)         # 定义渐变色的起点颜色

        color.setAlpha(120)        # 定义渐变色的中点颜色
        k = abs(self.actual_span_degree) / 360
        gradient.setColorAt(0.2*k, color)

        color.setAlpha(10)  # 定义渐变色的终点颜色
        gradient.setColorAt(k, color)
        self.draw_arc(gradient, (self.center_point.x(), self.center_point.y()), self.actual_begin_degree,       # 选择2:画渐变色的圆弧
                      self.actual_span_degree, self.processBar_actual_width, self.processBar_actual_radius)
        color.setAlpha(255)       # 复位颜色

        # ##################绘制设置值的显示进度条###############################
        # self.draw_arc(self.spinBox_preset_text_color, (self.center_point.x(), self.center_point.y()),
        #               self.preset_begin_degree,
        #               self.preset_span_degree, self.processBar_preset_width, self.processBar_preset_radius)   # 选择1:画单色的圆弧

        gradient = QConicalGradient(self.center_point.x(), self.center_point.y(),
                                    self.preset_begin_degree + self.preset_span_degree)  # 创建锥形梯度
        color = self.spinBox_preset_text_color  # 定义临时颜色
        gradient.setColorAt(0, color)  # 定义渐变色的起点颜色

        color.setAlpha(120)  # 定义渐变色的中点颜色
        k = abs(self.preset_span_degree) / 360
        gradient.setColorAt(0.2 * k, color)

        color.setAlpha(10)
        k = abs(self.preset_span_degree) / 360
        gradient.setColorAt(k, color)  # 定义渐变色的终点颜色
        self.draw_arc(gradient, (self.center_point.x(), self.center_point.y()), self.preset_begin_degree,  # 选择2:画渐变色的圆弧
                      self.preset_span_degree, self.processBar_preset_width, self.processBar_preset_radius)
        color.setAlpha(255)  # 复位颜色


# #########################历史曲线显示窗口的class定义########################
class CustomLineChart(QFrame):  # 自定义的折线表
    PointValues = Signal(float, float)  # 点值,设置值在前,实时值在后

    def __init__(self, preset_color, actual_color, min_value, max_value, points, parent=None):
        super().__init__(parent)
        self.points = points  # 显示的点数
        self.preset_value_points = [0.0]  # 设置值的数据点集
        self.actual_value_points = [0.0]  # 实时值的数据点集
        self.overflow = False  # 数据超量程

        self.background_color = QColor()  # 背景色
        self.preset_color = preset_color  # 预置值颜色
        self.actual_color = actual_color  # 实时值颜色
        self.preset_pen = QPen()  # 预设值波形的画笔
        self.actual_pen = QPen()  # 实时值波形的画笔
        self.min_value = min_value  # 最小值
        self.max_value = max_value  # 最大值

        self.x_points = []  # X轴的分度
        self.x_step = 0  # X轴的步调节拍

    def customSetupUi(self):  # 定制的初始化程序
        # #####################建立x轴的分度表############################
        x = 0
        s = self.width() / (self.points - 1)
        for i in range(self.points):
            self.x_points.append(int(x))
            x += s

        # #####################初始化颜色特征############################
        p = self.palette()  # 获取调色板
        self.background_color = p.color(p.ColorRole.Window)  # 获取背景色
        self.preset_pen = QPen(self.preset_color, 1)  # 预置值的笔
        self.actual_pen = QPen(self.actual_color, 1)  # 实时值的笔

        # #####################信号的连接############################
        self.PointValues.connect(self.pretreat)  # 当传入值以后预处理数据
        self.PointValues.connect(self.update)  # 当传入值以后更新画面

    def pretreat(self, preset_value, actual_value):  # 数据的预处理
        # #####################预设值数据的预处理############################
        k = (preset_value - self.min_value) / (self.max_value - self.min_value)
        v = int(self.height() * (1 - k))
        self.preset_value_points.append(v)
        if len(self.preset_value_points) > self.points:
            del self.preset_value_points[0]

        # #####################实时值数据的预处理############################
        if actual_value < self.min_value:  # 输入值超出量程
            actual_value = self.min_value
            self.overflow = True
        elif actual_value > self.max_value:
            actual_value = self.max_value
            self.overflow = True
        else:
            self.overflow = False

        k = (actual_value - self.min_value) / (self.max_value - self.min_value)  # 显示比例转换
        v = int(self.height() * (1 - k))
        self.actual_value_points.append(v)
        if len(self.actual_value_points) > self.points:
            del self.actual_value_points[0]

    # ############################绘图事件####################################
    def paintEvent(self, event):  # 重新定义paintEvent
        painter = QPainter(self)  # 设定画板
        painter.setPen(Qt.NoPen)  # 设定画笔

        # #########################重画背景###################################
        if self.overflow:
            color = QColor('#666666')
        else:
            color = self.background_color
        painter.setBrush(color)  # 设置笔刷
        painter.drawRect(0, 0, self.width(), self.height())  # 重画背景

        # #########################绘制预设值的折线#############################
        pen = QPen(self.preset_color)
        pen.setWidth(1)
        painter.setPen(pen)
        if len(self.preset_value_points) > 1:
            i = 1
            while i < len(self.preset_value_points):
                painter.drawLine(self.x_points[i - 1], int(self.preset_value_points[i - 1]), self.x_points[i],
                                 int(self.preset_value_points[i]))
                i += 1

        # #########################绘制实时值的折线#############################
        pen = QPen(self.actual_color)
        pen.setWidth(1)
        painter.setPen(pen)
        if len(self.actual_value_points) > 1:
            i = 1
            while i < len(self.actual_value_points):
                painter.drawLine(self.x_points[i - 1], int(self.actual_value_points[i - 1]),
                                 self.x_points[i], int(self.actual_value_points[i]))
                i += 1

使用自定义属性的指示灯

使用自定义属性,并且用样式表操作其显示特性。

QT Desinger里新建mainwindow,放置一个40*40的QLabel,并设定样式表,将圆弧设置为长宽的一半,就可以得到一个圆:

QLabel {

/*normal样式*/

background-color: rgb(118, 118, 118); /*Turn OFF状态的颜色定义*/

border:2px solid rgb(70, 70, 70);

border-radius:20px;

}

QLabel[OnOff="true"] {

/*Turn ON状态的样式,用作ON状态指示*/

background-color: #007800; /*Turn ON状态的颜色定义*/

}

 显示如下:

 然后新建两个按钮:

 调用的脚本:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow

import lamp_demo_rc


class Window(QMainWindow, lamp_demo_rc.Ui_MainWindow):
    def __int__(self):
        super(Window, self).__init__()


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

    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    window1 = Window()   # 实例化画面
    window1.show()  # 显示画面
    window1.setupUi(window1)  # 模板画面的本体初始化

    # ###########################信号的连接####################################

    window1.pushButton.clicked.connect(lambda: window1.label.setProperty('OnOff', True))
    window1.pushButton_2.clicked.connect(lambda: window1.label.setProperty('OnOff', False))
    window1.pushButton.clicked.connect(lambda: window1.label.setStyleSheet(window1.label.styleSheet()))  # 加载一次样式表,刷新显示
    window1.pushButton_2.clicked.connect(lambda: window1.label.setStyleSheet(window1.label.styleSheet()))
    sys.exit(app.exec())

运行截图:

 知识点:

1、在样式表里自定义了一个特性:OnOff,并且在脚本里对这个特性进行赋值用以改变显示。

2、 自定义特性的条件需要写成“QLabel[OnOff="true"]{} ”这样,写成部件的默认特性那种,如“QLabel:OnOff {}”这种,设定不起作用。

3、window1.pushButton.clicked.connect(lambda:window1.label.setStyleSheet(window1.label.styleSheet()))这一句必不可少,作用是重新加载一次样式表,刷新显示。用updata()不能刷新显示。
   

还可以将部件封装成一个标准件,用“提升为” 来调用,主程序会更简洁一些。

PysideLamp.py:

# encoding: utf-8
###################################################
#               自定义的指示灯
###################################################

# 对外接口:
#   OnOff = Signal(bool)     # on/off的信号
#   Blink = Signal(bool)     # 闪烁的信号

from PySide6.QtCore import Signal
from PySide6.QtWidgets import QLabel


class PysideLamp(QLabel):
    OnOff = Signal(bool)  # on/off的信号
    Blink = Signal(bool)  # 闪烁的信号

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

        # #######################定制的初始化程序###########################

    def customSetupUi(self):  # 定制的初始化程序
        self.OnOff.connect(self.color_OnOff)

    def color_OnOff(self, bool_in):  # 由输入的bool来控制颜色的显示
        self.setProperty('OnOff', bool_in)      # 设置自定义的OnOff属性
        self.setStyleSheet(self.styleSheet())   # 重新加载样式表,刷新显示
lamp_demo_rc:使用pyuic从ui文件转换来的py脚本
# -*- coding: utf-8 -*-

################################################################################
## Form generated from reading UI file 'lamp_demo.ui'
##
## Created by: Qt User Interface Compiler version 6.6.3
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QMainWindow, QMenuBar, QPushButton,
    QSizePolicy, QStatusBar, QWidget)

from PysideLamp import PysideLamp

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(211, 300)
        MainWindow.setStyleSheet(u"")
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.label = PysideLamp(self.centralwidget)
        self.label.setObjectName(u"label")
        self.label.setGeometry(QRect(70, 20, 40, 40))
        self.label.setStyleSheet(u"QLabel {\n"
"	/*normal\u6837\u5f0f*/\n"
"	background-color: rgb(118, 118, 118);\n"
"	border:2px solid  rgb(70, 70, 70);\n"
"	border-radius:20px;\n"
"	}\n"
"QLabel[OnOff=\"true\"] {\n"
"	/*Turn ON\u72b6\u6001\u7684\u6837\u5f0f\uff0c\u7528\u4f5cON\u72b6\u6001\u6307\u793a*/\n"
"	background-color: #007800;   /*Turn ON\u72b6\u6001\u7684\u989c\u8272\u5b9a\u4e49*/ \n"
"	}\n"
"")
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setGeometry(QRect(30, 90, 111, 61))
        self.pushButton_2 = QPushButton(self.centralwidget)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.pushButton_2.setGeometry(QRect(30, 160, 111, 61))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 211, 21))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.label.setText("")
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
        self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
    # retranslateUi

调用的脚本

import sys
from PySide6.QtWidgets import QApplication, QMainWindow

import lamp_demo_rc


# ########################部件初始化的通用函数###################################
def init_widgets(widget):  # 画面里的部件的初始化
    sons = widget.children()  # 儿辈部件

    def find_child(child):  # 查找子部件
        try:
            child.customSetupUi()  # 自定义的初始化
        except AttributeError:
            pass

        if child.children():
            for grandson in child.children():
                find_child(grandson)  # 递归查找

    for son in sons:
        find_child(son)


class Window(QMainWindow, lamp_demo_rc.Ui_MainWindow):
    def __int__(self):
        super(Window, self).__init__()


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

    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    window1 = Window()   # 实例化画面
    window1.show()  # 显示画面
    window1.setupUi(window1)  # 模板画面的本体初始化
    init_widgets(window1)  # 画面的子部件初始化

    # ###########################信号的连接####################################

    window1.pushButton.clicked.connect(lambda: window1.label.OnOff.emit(True))   # 使用“提升为”以后的操作
    window1.pushButton_2.clicked.connect(lambda: window1.label.OnOff.emit(False))

    sys.exit(app.exec())

进一步的,加入闪烁的功能:

# encoding: utf-8
###################################################
#               自定义的指示灯
###################################################

# 对外接口:
#   OnOff = Signal(bool)     # on/off的信号
#   Blink = Signal(bool)     # 闪烁的信号

from PySide6.QtCore import Signal, QTimer
from PySide6.QtWidgets import QLabel


class PysideLamp(QLabel):
    OnOff = Signal(bool)  # on/off的信号
    Blink = Signal(bool)  # 闪烁的信号

    def __init__(self, parent=None):
        super().__init__(parent)
        self.timer = QTimer()   # 控制闪烁的定时器
        self.BlinkColor = 1      # 闪烁色编号

        # #######################定制的初始化程序###########################

    def customSetupUi(self):  # 定制的初始化程序
        self.OnOff.connect(self.color_OnOff)   # 信号的连接
        self.Blink.connect(self.color_blink)
        self.timer.timeout.connect(self.blink_nums)

    def color_OnOff(self, bool_in):  # 由输入的bool来控制颜色的显示
        self.setProperty('OnOff', bool_in)      # 设置自定义的OnOff属性
        self.setStyleSheet(self.styleSheet())   # 重新加载样式表,刷新显示

    def color_blink(self, bool_in):   # 由输入的bool来控制是否闪烁
        if not self.timer.isActive():
            if bool_in:
                self.timer.start(500)
            else:
                self.timer.stop()

        self.setProperty('Blink', bool_in)  # 设置自定义的Blink属性
        self.setStyleSheet(self.styleSheet())  # 重新加载样式表,刷新显示

    def blink_nums(self):   # 闪烁色的编号
        if self.BlinkColor == 1:
            self.BlinkColor = 2
        else:
            self.BlinkColor = 1
        self.setProperty('BlinkColor', self.BlinkColor)   # 设置闪烁色
        self.setStyleSheet(self.styleSheet())  # 重新加载样式表,刷新显示
import sys

from PySide6.QtCore import QObject, Signal, QTimer
from PySide6.QtWidgets import QApplication, QMainWindow
import lamp_demo_rc


# ########################部件初始化的通用函数###################################
def init_widgets(widget):  # 画面里的部件的初始化
    sons = widget.children()  # 儿辈部件

    def find_child(child):  # 查找子部件
        try:
            child.customSetupUi()  # 自定义的初始化
        except AttributeError:
            pass

        if child.children():
            for grandson in child.children():
                find_child(grandson)  # 递归查找

    for son in sons:
        find_child(son)


class Window(QMainWindow, lamp_demo_rc.Ui_MainWindow):
    def __int__(self):
        super(Window, self).__init__()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # #######################画面实例化和初始化#################################
    # ########################实例化模板画面#################################
    window1 = Window()
    window1.show()  # 显示画面
    window1.setupUi(window1)  # 模板画面的本体初始化
    init_widgets(window1)  # 画面的子部件初始化

    # ###########################信号的连接####################################
    window1.pushButton.clicked.connect(lambda: window1.label.OnOff.emit(True))     # turn on
    window1.pushButton_2.clicked.connect(lambda: window1.label.OnOff.emit(False))   # turn off
    window1.pushButton_3.clicked.connect(lambda: window1.label.Blink.emit(True))   # 闪烁
    window1.pushButton_4.clicked.connect(lambda: window1.label.Blink.emit(False))  # 停止闪烁

    sys.exit(app.exec())

 自锁按钮

方法1:使用自带函数setCheckable()将按钮设为自锁。

可以用toggle()来切换其状态

请注意:

toggled信号,是当按钮的状态发生切换时发出

clicked信号,是当按钮点击时发出

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Main Window with Buttons")

        # 创建按钮
        self.button1 = QPushButton('Button 1', self)
        self.button1.setGeometry(50, 50, 100, 50)  # 设置按钮1的位置和大小
        self.button1.setCheckable(True)

        # 连接按钮的点击事件到槽函数
        self.button1.toggled.connect(self.button1_toggled)
        self.button1.clicked.connect(self.button1_clicked)

    def button1_toggled(self):
        print('toggled')

    def button1_clicked(self):
        print('clicked')


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

    

在上面的范例中,当点击按钮,toggled信号和clicked信号都发射。

方法2:使用自定义特性和伪状态:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Main Window with Buttons")

        # 创建按钮
        self.button2 = QPushButton('Button 2', self)
        self.button2.setGeometry(50, 120, 100, 50)  # 设置按钮2的位置和大小
        self.button2.setProperty('activated', False)  # 设置自定义特性:'activated'
        self.button2.setStyleSheet('QPushButton[activated="true"]{background-color:#9db6f9;}')  # 设置伪状态的样式表

        # 连接按钮的点击事件到槽函数
        self.button2.clicked.connect(self.button2_checked)

    def button2_checked(self):
        act = self.button2.property('activated')
        self.button2.setProperty('activated', not act)
        self.button2.setStyleSheet(self.button2.styleSheet())   # 更新显示


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深蓝海拓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值