本篇以一个例子来介绍如何通过子类化QWidget或其它内置窗口部件来创建自定义的窗口部件。
程序的功能是用彩色的多个自定义Label来可视化一个二维数组。彩色Label与左边的行号Label、顶部的列号Label,以及右边自定义的colorbar一起,组成了一个相对复杂的自定义的复合控件。
示例代码如下:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QColor,QPainter,QBrush,QLinearGradient
from PyQt5.QtCore import Qt, pyqtSignal
import numpy as np
def x2RGB(x,LSL=0, USL=1.0):#颜色映射
r=(x-LSL)/(USL-LSL)
if r>1:
return (255, 255, 255)
elif r>=0.75:
return (255, int(255*(1-r)*4), 0)
elif r>=0.5:
return (int(255*(r-0.5)*4), 255, 0)
elif r>=0.25:
return (0, 255, int(255*(0.5-r)*4))
elif r>=0:
return (0, int(255*r*4), 255)
else:
return (0,0,0)
class MapItem(QLabel):
clicksignal = pyqtSignal(int, int, float)
def __init__(self,row,col, value, LSL =0 , USL = 1, text='', parent=None):
super().__init__(parent)
self.row = row
self.col = col
self.value = value
self.setText(text)
self.LSL = LSL
self.USL = USL
self.setBackgroundColor()
self.setFrameShape(QFrame.Box)
self.setLineWidth(0)
#self.setMinimumSize (10,6)
#self.setMaximumSize (20,12)
def getRGB(self):
return x2RGB(self.value, self.LSL,self.USL)
def setBackgroundColor(self):
self.setStyleSheet("QLabel{background:rgb(%d,%d,%d,250);}"% self.getRGB())
def enterEvent(self,event):
#self.setText("%3.3f" % self.value)
self.setLineWidth(1)
def leaveEvent(self,event):
#self.clear()
self.setLineWidth(0)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
#pos = event.pos() #QPoint
#self.cx , self.cy = pos.x(),pos.y()
self.clicksignal.emit(self.row,self.col,self.value)
class ColorBar(QWidget):#渐变色彩带
def __init__(self, parent = None):
super().__init__(parent)
self.setSize()
self.currentValue =None
def setSize(self, width=20, height=500):
self.width = width
self.height = height
self.update()
def paintEvent(self,QPaintEvent):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing);
painter.setRenderHint(QPainter.SmoothPixmapTransform)
painter.save()
linearGradient = QLinearGradient(0, 0, 0,self.height)
linearGradient.setColorAt(0.0,Qt.red)
linearGradient.setColorAt(0.25,Qt.yellow)
linearGradient.setColorAt(0.5,Qt.green)
linearGradient.setColorAt(0.75,Qt.cyan)
linearGradient.setColorAt(1.0,Qt.blue)
painter.setBrush(QBrush(linearGradient))
painter.drawRect(0,0,self.width,self.height)
class Map(QWidget):
def __init__(self, array =np.random.randn(40,25), parent = None):
super().__init__(parent)
self.array = array
self.rows, self.cols = self.array.shape
#self.setSL(self.array.min(), self.array.max())
self.setSL(-3.0, 3.0)
gl = QGridLayout()
gl.setSpacing(0)# 零间距
for i in range(self.rows):
rowLabel = QLabel(str(i+1))
rowLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
gl.addWidget(rowLabel,i+1,0)
for j in range(self.cols):
colLabel = QLabel(str(j+1))
colLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
gl.addWidget(colLabel, 0, j+1)
item = MapItem(i+1, j+1,self.array[i,j], self.LSL, self.USL)
item.clicksignal.connect(self.on_item_clicked)
gl.addWidget(item,i+1,j+1)
separator = QLabel()
separator.setFixedWidth(15)
gl.addWidget(separator, 1, self.cols+1, self.rows,1)
self.colorbar = ColorBar()
gl.addWidget(self.colorbar, 1, self.cols+2, self.rows,1)
USL_label =QLabel(str(round(self.USL,2)))
USL_label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
gl.addWidget(USL_label, 1, self.cols+3, 1,1)
LSL_label =QLabel(str(round(self.LSL,2)))
LSL_label.setAlignment(Qt.AlignBottom | Qt.AlignLeft)
gl.addWidget(LSL_label, self.rows, self.cols+3, 1,1)
target_label =QLabel(str(round((self.USL+self.LSL)/2.0, 2)))
target_label.setAlignment(Qt.AlignBottom | Qt.AlignLeft)
gl.addWidget(target_label, (self.rows+1)//2, self.cols+3, 1,1)
self.setLayout(gl)
self.setMinimumSize (600,500)
self.setWindowTitle("自定义控件示例")
def setSL(self, LSL =0, USL =1):
self.LSL = LSL
self.USL = USL
def on_item_clicked(self, row, col, value):
print(row, col, value)
self.colorbar.currentValue = value
self.colorbar.update()
def resizeEvent(self,event):
print(self.width(),self.height())
self.colorbar.setSize(20,self.height())
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = Map()
ui.show()
sys.exit(app.exec_())
本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!