zoukankan      html  css  js  c++  java
  • PyQt4自定义控件----指示灯控件

    程序中演示了PyQt中编程实现自定义圆形指示灯控件的方法,通过程序界面可改变其属性值并能实时看到指示灯的外观变化情况,同时,在定时器中也实现了一个类似跑马灯效果的功能。

    例子虽小,但涉及的编程点挺多,包括:自定义控件(圆形指示灯、颜色选择框等)、分割条、布局、辐射渐变画刷、定时器、自定义信号(pyqtSignal)、列表、setattr、hasattr、for...in、zip、map、十进制转二进制等等。

    代码如下:

      1 # -*- coding: utf-8 -*-#
      2 
      3 #-------------------------------------------------------------------------------
      4 # Name:         自定义圆形指示灯控件
      5 # Description:  
      6 # Author:       lgk
      7 # Date:         2018/7/05
      8 #-------------------------------------------------------------------------------
      9 
     10 import sys
     11 from PyQt4.QtGui import *
     12 from PyQt4.QtCore import *
     13 
     14 allAttributes =   [  'colorOnBegin', 'colorOnEnd', 'colorOffBegin', 'colorOffEnd', 'colorBorderIn', 'colorBorderOut',
     15                      'radiusBorderOut', 'radiusBorderIn', 'radiusCircle']
     16 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),
     17                     500, 450, 400]
     18 allLabelNames =   [ u'灯亮圆心颜色:', u'灯亮边缘颜色:', u'灯灭圆心颜色:', u'灯灭边缘颜色:', u'边框内测颜色:', u'边框外侧颜色:',
     19                     u'边框外侧半径:', u'边框内侧半径:', u'中间圆灯半径:']
     20 
     21 class MyLed(QAbstractButton):
     22     def __init__(self, parent=None):
     23         super(MyLed, self).__init__(parent)
     24         self.initUI()
     25 
     26     def initUI(self):
     27         self.setMinimumSize(24, 24)
     28         self.setCheckable(True)
     29         self.scaledSize = 1000.0    #为方便计算,将窗口短边值映射为1000
     30         self.setLedDefaultOption()
     31 
     32     def setLedDefaultOption(self):
     33         for attr, val in zip(allAttributes, allDefaultVal):
     34             setattr(self, attr, val)
     35         self.update()
     36 
     37     def setLedOption(self, opt='colorOnBegin', val=QColor(0,240,0)):
     38         if hasattr(self, opt):
     39             setattr(self, opt, val)
     40             self.update()
     41 
     42     def resizeEvent(self, evt):
     43         self.update()
     44 
     45     def paintEvent(self, evt):
     46         painter = QPainter(self)
     47         painter.setRenderHint(QPainter.Antialiasing, True)
     48         painter.setPen(QPen(Qt.black, 1))
     49 
     50         realSize = min(self.width(), self.height())                         #窗口的短边
     51         painter.translate(self.width()/2.0, self.height()/2.0)              #原点平移到窗口中心
     52         painter.scale(realSize/self.scaledSize, realSize/self.scaledSize)   #缩放,窗口的短边值映射为self.scaledSize
     53         gradient = QRadialGradient(QPointF(0, 0), self.scaledSize/2.0, QPointF(0, 0))   #辐射渐变
     54 
     55         #画边框外圈和内圈
     56         for color, radius in [(self.colorBorderOut, self.radiusBorderOut),  #边框外圈
     57                                (self.colorBorderIn, self.radiusBorderIn)]:   #边框内圈
     58             gradient.setColorAt(1, color)
     59             painter.setBrush(QBrush(gradient))
     60             painter.drawEllipse(QPointF(0, 0), radius, radius)
     61 
     62         # 画内圆
     63         gradient.setColorAt(0, self.colorOnBegin if self.isChecked() else self.colorOffBegin)
     64         gradient.setColorAt(1, self.colorOnEnd if self.isChecked() else self.colorOffEnd)
     65         painter.setBrush(QBrush(gradient))
     66         painter.drawEllipse(QPointF(0, 0), self.radiusCircle, self.radiusCircle)
     67 
     68 class MyColorBox(QFrame):
     69     sigColorChanged = pyqtSignal(QColor)
     70     def __init__(self, parent=None, height=20, color=QColor(0,240,0)):
     71         super(MyColorBox, self).__init__(parent)
     72         self.setFixedHeight(height)
     73         self.setAutoFillBackground(True)
     74         self.setPalette(QPalette(color))
     75         self.setFrameStyle(QFrame.Panel | QFrame.Sunken)
     76 
     77     def mousePressEvent(self, *args, **kwargs):
     78         color = QColorDialog.getColor(initial=self.palette().color(QPalette.Window))
     79         if color.isValid():
     80             self.setPalette(QPalette(color))
     81             self.sigColorChanged.emit(color)
     82 
     83     def setColor(self, color):
     84         self.setPalette(QPalette(color))
     85 
     86 class MyRadiusCtrl(QSpinBox):
     87     def __init__(self, parent=None, initVal=500):
     88         super(MyRadiusCtrl, self).__init__(parent)
     89         self.setRange(1, 500)
     90         self.setValue(initVal)
     91 
     92 class ConfigWnd(QFrame):
     93     def __init__(self, parent=None):
     94         super(ConfigWnd, self).__init__(parent)
     95         self.initUI()
     96 
     97     def initUI(self):
     98         self.setFrameStyle(QFrame.Box|QFrame.Sunken)
     99 
    100         mainLayout = QVBoxLayout(self)
    101         mainLayout.addWidget(self.createColorParaGroupBox(), 0)
    102         mainLayout.addSpacing(20)
    103         mainLayout.addWidget(self.createRadiusParaGroupBox(), 0)
    104         mainLayout.addStretch()
    105         mainLayout.addSpacing(20)
    106         self.restoreDefaultBtn = QPushButton(u'恢复默认设置')
    107         mainLayout.addWidget(self.restoreDefaultBtn, 0)
    108         mainLayout.addSpacing(10)
    109         self.animateBtn = QPushButton(u'开始动画')
    110         self.animateBtn.setCheckable(True)
    111         mainLayout.addWidget(self.animateBtn, 0)
    112 
    113     def createColorParaGroupBox(self):
    114         colorParaGroupBox = QGroupBox(u"颜色参数设置", self)
    115         layout = QGridLayout(colorParaGroupBox)
    116         layout.setSpacing(10)
    117 
    118         self.allColorBoxCtrls = []
    119         for name, color, row in zip(allLabelNames[:6], allDefaultVal[:6], range(6)):
    120             layout.addWidget(QLabel(name), row, 0)
    121             colorBox = MyColorBox(color=color)
    122             layout.addWidget(colorBox, row, 1)
    123             self.allColorBoxCtrls.append(colorBox)
    124 
    125         layout.setColumnStretch(0, 0)
    126         layout.setColumnStretch(1, 1)
    127         return colorParaGroupBox
    128 
    129     def createRadiusParaGroupBox(self):
    130         radiusParaGroupBox = QGroupBox(u"半径设置(1~500)", self)
    131         layout = QGridLayout(radiusParaGroupBox)
    132         layout.setSpacing(10)
    133 
    134         self.allRadiusCtrls = []
    135         for name, radius, row in zip(allLabelNames[6:], allDefaultVal[6:], range(3)):
    136             layout.addWidget(QLabel(name), row, 0)
    137             radiusCtrl = MyRadiusCtrl(initVal=radius)
    138             layout.addWidget(radiusCtrl, row, 1)
    139             self.allRadiusCtrls.append(radiusCtrl)
    140 
    141         layout.setColumnStretch(0, 0)
    142         layout.setColumnStretch(1, 1)
    143         return radiusParaGroupBox
    144 
    145 class MainWindow(QMainWindow):
    146     def __init__(self):
    147         super(MainWindow, self).__init__()
    148         self.initUI()
    149         self.initSlotFunc()
    150         self.cnt = 0
    151         self.show()
    152 
    153     def initUI(self):
    154         self.resize(580, 350)
    155         self.setWindowTitle(u'自定义圆形指示灯控件')
    156 
    157         mainSplitter = self.createSplitter(style=Qt.Horizontal, parent=self, width=4)
    158 
    159         self.configWnd = ConfigWnd(mainSplitter)
    160 
    161         rightSplitter = self.createSplitter(style=Qt.Vertical, parent=mainSplitter, width=4)
    162 
    163         rightTopWnd = self.createSubWnd(rightSplitter)
    164         rightTopLayout = QVBoxLayout(rightTopWnd)
    165         rightTopLayout.setContentsMargins(60, 60, 60, 60)
    166         self.ledSingle = MyLed()
    167         self.ledSingle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
    168         rightTopLayout.addWidget(self.ledSingle)
    169 
    170         rightBottomWnd = self.createSubWnd(rightSplitter)
    171         rightBottomLayout = QHBoxLayout(rightBottomWnd)
    172         rightBottomLayout.setContentsMargins(10, 10, 10, 10)
    173         self.ledGroup = []
    174         for i in range(8):
    175             led = MyLed()
    176             led.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
    177             self.ledGroup.append(led)
    178             rightBottomLayout.addWidget(led)
    179 
    180         self.setSplitterStrechFactor(rightSplitter, 1, 0)
    181         self.setSplitterStrechFactor(mainSplitter, 0, 1)
    182         self.setCentralWidget(mainSplitter)
    183 
    184     def createSplitter(self, style=Qt.Horizontal, parent=None, width=3):
    185         splitter = QSplitter(style, parent)
    186         splitter.setHandleWidth(width)
    187         return splitter
    188 
    189     def setSplitterStrechFactor(self, splitter=None, factor1=1, factor2=1): #设置分割条两部分的比例
    190         splitter.setStretchFactor(0, factor1)
    191         splitter.setStretchFactor(1, factor2)
    192 
    193     def createSubWnd(self, parent=None):
    194         wnd = QFrame(parent)
    195         wnd.setFrameStyle(QFrame.Box | QFrame.Sunken)
    196         return wnd
    197 
    198     def initSlotFunc(self):
    199         self.configWnd.restoreDefaultBtn.clicked.connect(self.slotRestoreDefault)
    200         map(lambda x: x.sigColorChanged.connect(self.slotattributeChanged), self.configWnd.allColorBoxCtrls)   #设定每个颜色控件的槽函数
    201         map(lambda x: x.valueChanged.connect(self.slotattributeChanged), self.configWnd.allRadiusCtrls)        #设定每个半径控件的槽函数
    202         self.configWnd.animateBtn.clicked.connect(self.slotAnimation)
    203         self.timer = QTimer()
    204         self.timer.timeout.connect(self.slotTimeout) #动画定时器
    205 
    206     def slotattributeChanged(self, val):
    207         allCtrls = self.configWnd.allColorBoxCtrls + self.configWnd.allRadiusCtrls
    208         idx = allCtrls.index(self.sender())
    209         self.ledSingle.setLedOption(allAttributes[idx], val)
    210 
    211     def slotRestoreDefault(self):
    212         for colorBox, val in zip(self.configWnd.allColorBoxCtrls, allDefaultVal[:6]):
    213             colorBox.setColor(val)
    214 
    215         for radiusCtrl, val in zip(self.configWnd.allRadiusCtrls, allDefaultVal[6:]):
    216             radiusCtrl.setValue(val)
    217 
    218         self.ledSingle.setLedDefaultOption()
    219 
    220     def slotAnimation(self):
    221         if self.configWnd.animateBtn.isChecked():
    222             self.cnt = 0
    223             self.configWnd.animateBtn.setText(u'停止动画')
    224             self.timer.start(300)
    225         else:
    226             self.configWnd.animateBtn.setText(u'开始动画')
    227             self.timer.stop()
    228 
    229     def slotTimeout(self):
    230         self.cnt = self.cnt % 256
    231         ledBits = QString('%1').arg(self.cnt, 8, 2, fillChar=QChar('0'))    #将数值转换为二进制字符串
    232         for ledBit, led in zip(ledBits, self.ledGroup):
    233             led.setChecked(ledBit=='1')
    234         self.cnt += 1
    235 
    236 def main():
    237     app = QApplication(sys.argv)
    238     mainWnd = MainWindow()
    239     sys.exit(app.exec_())
    240 
    241 if __name__ == '__main__':
    242     main()
     
  • 相关阅读:
    题解-FJOI2014 树的重心
    题解-CF1307G Cow and Exercise
    题解-SHOI2005 树的双中心

    【转载】SVN使用教程总结
    Fastcgi、CGI 是什么
    通过js或jq增加的代码,点击事件或其他一些事件不起作用时
    js闭包讲解
    PHP 程序员危机(转载)
    浏览器 User-Agent相关知识
  • 原文地址:https://www.cnblogs.com/luke0011/p/9271371.html
Copyright © 2011-2022 走看看