pyqt4 自定义圆形指示灯控件

37 篇文章 1 订阅
21 篇文章 0 订阅
# -*- coding: utf-8 -*-#

#-------------------------------------------------------------------------------
# Name:         自定义圆形指示灯控件
#-------------------------------------------------------------------------------

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

allAttributes =   [  'colorOnBegin', 'colorOnEnd', 'colorOffBegin', 'colorOffEnd', 'colorBorderIn', 'colorBorderOut',
                     'radiusBorderOut', 'radiusBorderIn', 'radiusCircle']
allDefaultVal =   [ QColor(0, 240, 0), QColor(0, 160, 0), QColor(0, 68, 0), QColor(0, 28, 0), QColor(140, 140, 140), QColor(100, 100, 100),
                    500, 450, 400]
allLabelNames =   [ u'灯亮圆心颜色:', u'灯亮边缘颜色:', u'灯灭圆心颜色:', u'灯灭边缘颜色:', u'边框内测颜色:', u'边框外侧颜色:',
                    u'边框外侧半径:', u'边框内侧半径:', u'中间圆灯半径:']


class MyLed(QAbstractButton):
    def __init__(self, parent=None):
        super(MyLed, self).__init__(parent)
        self.initUI()

    def initUI(self):
        self.setMinimumSize(24, 24)
        self.setCheckable(True)
        self.scaledSize = 1000.0    #为方便计算,将窗口短边值映射为1000
        self.setLedDefaultOption()

    def setLedDefaultOption(self):
        for attr, val in zip(allAttributes, allDefaultVal):
            setattr(self, attr, val)
        self.update()

    def setLedOption(self, opt='colorOnBegin', val=QColor(0,240,0)):
        if hasattr(self, opt):
            setattr(self, opt, val)
            self.update()

    def resizeEvent(self, evt):
        self.update()

    def paintEvent(self, evt):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setPen(QPen(Qt.black, 1))

        realSize = min(self.width(), self.height())                         #窗口的短边
        painter.translate(self.width()/2.0, self.height()/2.0)              #原点平移到窗口中心
        painter.scale(realSize/self.scaledSize, realSize/self.scaledSize)   #缩放,窗口的短边值映射为self.scaledSize
        gradient = QRadialGradient(QPointF(0, 0), self.scaledSize/2.0, QPointF(0, 0))   #辐射渐变

        #画边框外圈和内圈
        for color, radius in [(self.colorBorderOut, self.radiusBorderOut),  #边框外圈
                               (self.colorBorderIn, self.radiusBorderIn)]:   #边框内圈
            gradient.setColorAt(1, color)
            painter.setBrush(QBrush(gradient))
            painter.drawEllipse(QPointF(0, 0), radius, radius)

        # 画内圆
        gradient.setColorAt(0, self.colorOnBegin if self.isChecked() else self.colorOffBegin)
        gradient.setColorAt(1, self.colorOnEnd if self.isChecked() else self.colorOffEnd)
        painter.setBrush(QBrush(gradient))
        painter.drawEllipse(QPointF(0, 0), self.radiusCircle, self.radiusCircle)

class MyColorBox(QFrame):
    sigColorChanged = pyqtSignal(QColor)
    def __init__(self, parent=None, height=20, color=QColor(0,240,0)):
        super(MyColorBox, self).__init__(parent)
        self.setFixedHeight(height)
        self.setAutoFillBackground(True)
        self.setPalette(QPalette(color))
        self.setFrameStyle(QFrame.Panel | QFrame.Sunken)

    def mousePressEvent(self, *args, **kwargs):
        color = QColorDialog.getColor(initial=self.palette().color(QPalette.Window))
        if color.isValid():
            self.setPalette(QPalette(color))
            self.sigColorChanged.emit(color)

    def setColor(self, color):
        self.setPalette(QPalette(color))

class MyRadiusCtrl(QSpinBox):
    def __init__(self, parent=None, initVal=500):
        super(MyRadiusCtrl, self).__init__(parent)
        self.setRange(1, 500)
        self.setValue(initVal)

class ConfigWnd(QFrame):
    def __init__(self, parent=None):
        super(ConfigWnd, self).__init__(parent)
        self.initUI()

    def initUI(self):
        self.setFrameStyle(QFrame.Box|QFrame.Sunken)

        mainLayout = QVBoxLayout(self)
        mainLayout.addWidget(self.createColorParaGroupBox(), 0)
        mainLayout.addSpacing(20)
        mainLayout.addWidget(self.createRadiusParaGroupBox(), 0)
        mainLayout.addStretch()
        mainLayout.addSpacing(20)
        self.restoreDefaultBtn = QPushButton(u'恢复默认设置')
        mainLayout.addWidget(self.restoreDefaultBtn, 0)
        mainLayout.addSpacing(10)
        self.animateBtn = QPushButton(u'开始动画')
        self.animateBtn.setCheckable(True)
        mainLayout.addWidget(self.animateBtn, 0)

    def createColorParaGroupBox(self):
        colorParaGroupBox = QGroupBox(u"颜色参数设置", self)
        layout = QGridLayout(colorParaGroupBox)
        layout.setSpacing(10)

        self.allColorBoxCtrls = []
        for name, color, row in zip(allLabelNames[:6], allDefaultVal[:6], range(6)):
            layout.addWidget(QLabel(name), row, 0)
            colorBox = MyColorBox(color=color)
            layout.addWidget(colorBox, row, 1)
            self.allColorBoxCtrls.append(colorBox)

        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 1)
        return colorParaGroupBox

    def createRadiusParaGroupBox(self):
        radiusParaGroupBox = QGroupBox(u"半径设置(1~500)", self)
        layout = QGridLayout(radiusParaGroupBox)
        layout.setSpacing(10)

        self.allRadiusCtrls = []
        for name, radius, row in zip(allLabelNames[6:], allDefaultVal[6:], range(3)):
            layout.addWidget(QLabel(name), row, 0)
            radiusCtrl = MyRadiusCtrl(initVal=radius)
            layout.addWidget(radiusCtrl, row, 1)
            self.allRadiusCtrls.append(radiusCtrl)

        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 1)
        return radiusParaGroupBox

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()
        self.initSlotFunc()
        self.cnt = 0
        self.show()

    def initUI(self):
        self.resize(580, 350)
        self.setWindowTitle(u'自定义圆形指示灯控件')

        mainSplitter = self.createSplitter(style=Qt.Horizontal, parent=self, width=4)

        self.configWnd = ConfigWnd(mainSplitter)

        rightSplitter = self.createSplitter(style=Qt.Vertical, parent=mainSplitter, width=4)

        rightTopWnd = self.createSubWnd(rightSplitter)
        rightTopLayout = QVBoxLayout(rightTopWnd)
        rightTopLayout.setContentsMargins(60, 60, 60, 60)
        self.ledSingle = MyLed()
        self.ledSingle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        rightTopLayout.addWidget(self.ledSingle)

        rightBottomWnd = self.createSubWnd(rightSplitter)
        rightBottomLayout = QHBoxLayout(rightBottomWnd)
        rightBottomLayout.setContentsMargins(10, 10, 10, 10)
        self.ledGroup = []
        for i in range(8):
            led = MyLed()
            led.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.ledGroup.append(led)
            rightBottomLayout.addWidget(led)

        self.setSplitterStrechFactor(rightSplitter, 1, 0)
        self.setSplitterStrechFactor(mainSplitter, 0, 1)
        self.setCentralWidget(mainSplitter)

    def createSplitter(self, style=Qt.Horizontal, parent=None, width=3):
        splitter = QSplitter(style, parent)
        splitter.setHandleWidth(width)
        return splitter

    def setSplitterStrechFactor(self, splitter=None, factor1=1, factor2=1): #设置分割条两部分的比例
        splitter.setStretchFactor(0, factor1)
        splitter.setStretchFactor(1, factor2)

    def createSubWnd(self, parent=None):
        wnd = QFrame(parent)
        wnd.setFrameStyle(QFrame.Box | QFrame.Sunken)
        return wnd

    def initSlotFunc(self):
        self.configWnd.restoreDefaultBtn.clicked.connect(self.slotRestoreDefault)
        map(lambda x: x.sigColorChanged.connect(self.slotattributeChanged), self.configWnd.allColorBoxCtrls)   #设定每个颜色控件的槽函数
        map(lambda x: x.valueChanged.connect(self.slotattributeChanged), self.configWnd.allRadiusCtrls)        #设定每个半径控件的槽函数
        self.configWnd.animateBtn.clicked.connect(self.slotAnimation)
        self.timer = QTimer()
        self.timer.timeout.connect(self.slotTimeout) #动画定时器

    def slotattributeChanged(self, val):
        allCtrls = self.configWnd.allColorBoxCtrls + self.configWnd.allRadiusCtrls
        idx = allCtrls.index(self.sender())
        self.ledSingle.setLedOption(allAttributes[idx], val)

    def slotRestoreDefault(self):
        for colorBox, val in zip(self.configWnd.allColorBoxCtrls, allDefaultVal[:6]):
            colorBox.setColor(val)

        for radiusCtrl, val in zip(self.configWnd.allRadiusCtrls, allDefaultVal[6:]):
            radiusCtrl.setValue(val)

        self.ledSingle.setLedDefaultOption()

    def slotAnimation(self):
        if self.configWnd.animateBtn.isChecked():
            self.cnt = 0
            self.configWnd.animateBtn.setText(u'停止动画')
            self.timer.start(300)
        else:
            self.configWnd.animateBtn.setText(u'开始动画')
            self.timer.stop()

    def slotTimeout(self):
        self.cnt = self.cnt % 256
        ledBits = QString('%1').arg(self.cnt, 8, 2, fillChar=QChar('0'))    #将数值转换为二进制字符串
        for ledBit, led in zip(ledBits, self.ledGroup):
            led.setChecked(ledBit=='1')
        self.cnt += 1

def main():
    app = QApplication(sys.argv)
    mainWnd = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

佐倉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值