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()

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM