def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen)
def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen)
def initialize(self) -> None: """ Method to initialize the display of this item :return: None """ op = self.sceneBoundingRect().center() self.setTransformOriginPoint(op) self.setRotation(self.angle) cx, cy = self.center r1, r2 = self.height / 2, self.width / 2 # Draw major axis major_axis = QGraphicsLineItem(-r2, 0, r2, 0) major_axis.setPos(cx, cy) major_axis.setParentItem(self) # Draw minor axis minor_axis = QGraphicsLineItem(-r1, 0, r1, 0) minor_axis.setPos(cx, cy) minor_axis.setParentItem(self) minor_axis.setRotation(90) rect = EditingRectangle(self.x, self.y, self.center[0], self.center[1], self.width, self.height) rect.setTransformOriginPoint(rect.sceneBoundingRect().center()) rect.setRotation(self.angle) self.indicators.extend([ major_axis, minor_axis, ]) self.edit_rect = rect self.rect = self.boundingRect() self.edit_rect.activate(False) self.setEnabled(False)
def on_actItem_Line_triggered(self): # 添加直线 item = QGraphicsLineItem(-100, 0, 100, 0) # x,y 为左上角的图元局部坐标,图元中心点为0,0 item.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable) pen = QPen(Qt.red) pen.setWidth(3) item.setPen(pen) self.view.frontZ = self.view.frontZ + 1 item.setZValue(self.view.frontZ) item.setPos(-50 + (QtCore.qrand() % 100), -50 + (QtCore.qrand() % 100)) self.view.seqNum = self.view.seqNum + 1 item.setData(self.view.ItemId, self.view.seqNum) # //自定义数据,ItemId键 item.setData(self.view.ItemDesciption, "直线") self.scene.addItem(item) self.scene.clearSelection() item.setSelected(True)
class painter(QGraphicsView): pixelSize = int(15 / narrowRatio) width = int(480 / narrowRatio) height = int(360 / narrowRatio) fontSize = int(15 / narrowRatio) anchorLineSize = int(100 / narrowRatio) ellipseRadius = int(8 / narrowRatio) textInterval = int(90 / narrowRatio) col = width / pixelSize line = height / pixelSize centerIndex = int(round(((line / 2 - 1) * col) + col / 2)) frameCount = 0 failedCount = 0 baseZValue = 0 mode = 1 body = 1 open_status = 0 textLineHeight = fontSize + 10 blurRaduis = 50 # Smoother improvement def __init__(self, dataThread): super(painter, self).__init__() self.dataThread = dataThread self.setFixedSize(self.width + 200, self.height + self.textLineHeight) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() self.setScene(self.scene) # center het text item self.centerTextItem = QGraphicsTextItem() self.centerTextItem.setPos((self.width + 200) / 2 - self.fontSize, 0) self.centerTextItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.centerTextItem) # version text item self.versionTextItem = QGraphicsTextItem() self.versionTextItem.setPos(self.width * 0.8 - self.fontSize, self.height * 0.8 - self.fontSize) self.versionTextItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.versionTextItem) self.userCom = None # center anchor item centerX = self.width / 2 centerY = self.height / 2 self.ellipseItem = QGraphicsEllipseItem(0, 0, self.ellipseRadius * 2, self.ellipseRadius * 2) self.horLineItem = QGraphicsLineItem(0, 0, self.anchorLineSize, 0) self.verLineItem = QGraphicsLineItem(0, 0, 0, self.anchorLineSize) self.ellipseItem.setPos(centerX - self.ellipseRadius, centerY - self.ellipseRadius) self.horLineItem.setPos(centerX - self.anchorLineSize / 2, centerY) self.verLineItem.setPos(centerX, centerY - self.anchorLineSize / 2) self.ellipseItem.setPen(QColor(Qt.white)) self.horLineItem.setPen(QColor(Qt.white)) self.verLineItem.setPen(QColor(Qt.white)) self.ellipseItem.setZValue(self.baseZValue + 1) self.horLineItem.setZValue(self.baseZValue + 1) self.verLineItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.ellipseItem) self.scene.addItem(self.horLineItem) self.scene.addItem(self.verLineItem) # camera item self.cameraBuffer = QPixmap(self.width, self.height + self.textLineHeight) self.cameraItem = QGraphicsPixmapItem() if useBlur: self.gusBlurEffect = QGraphicsBlurEffect() self.gusBlurEffect.setBlurRadius(self.blurRaduis) self.cameraItem.setGraphicsEffect(self.gusBlurEffect) self.cameraItem.setPos(100, 0) self.cameraItem.setZValue(self.baseZValue) self.scene.addItem(self.cameraItem) # het text item self.hetTextBuffer = QPixmap(self.width + 200, self.textLineHeight) self.hetTextItem = QGraphicsPixmapItem() self.hetTextItem.setPos(0, self.height) self.hetTextItem.setZValue(self.baseZValue) self.scene.addItem(self.hetTextItem) # button item self.ctrlOpenButton = QPushButton('Open', self) self.ctrlOpenButton.clicked.connect(self.ctrlOpen) self.ctrlOpenButton.setGeometry(10, 30, 100, 40) self.EvaluateButton = QPushButton('None', self) self.EvaluateButton.clicked.connect(self.evaluate) self.EvaluateButton.setGeometry(10, 80, 100, 40) self.getOnePicButton = QPushButton('Get a frame', self) self.getOnePicButton.clicked.connect(self.ctrlSendone) self.getOnePicButton.setGeometry(10, 130, 100, 40) self.getOnePicButton.setEnabled(False) self.modeManualButton = QPushButton('Auto', self) self.modeManualButton.clicked.connect(self.modeManual) self.modeManualButton.setGeometry(10, 180, 100, 40) self.modeObjButton = QPushButton('Body', self) self.modeObjButton.clicked.connect(self.objBody) self.modeObjButton.setGeometry(10, 230, 100, 40) self.modeFpsButton = QPushButton('4FPS', self) self.modeFpsButton.clicked.connect(self.rate) self.modeFpsButton.setGeometry(10, 280, 100, 40) self.modeAutoButton = QPushButton('Get offset', self) self.modeAutoButton.clicked.connect(self.commonOffset) self.modeAutoButton.setGeometry(570, 30, 100, 40) self.modeAutoButton = QPushButton('Get version', self) self.modeAutoButton.clicked.connect(self.sysVer) self.modeAutoButton.setGeometry(570, 80, 100, 40) self.evaluate = 1 self.evaluateButton = QPushButton('Evaluate', self) self.evaluateButton.clicked.connect(self.setEvaluate) self.evaluateButton.setGeometry(570, 120, 100, 40) self.serial_l = QLabel(self) self.serial_l.move(580, 250) self.serial_l.resize(60, 30) self.serial_l.setStyleSheet( "QLabel{color:rgb(0,0,0,255);background-color: rgb(255,255,255);font-size:16px;font-weight:normal;font-family:Arial;}" ) self.serial_l.setText("Serial:") self.serialList = SerialComboBox(self) self.serialList.setCurrentIndex(0) self.serialList.setStyleSheet( "border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);" ) self.serialList.currentIndexChanged.connect(self.serialChange) # self.evaluateButton.setGeometry(570,140,100,40) self.serialList.move(580, 280) self.serialList.resize(120, 30) self.serialList.addItem("Please select serial device") def checkSerial(self): reply = QMessageBox.information(self, 'No serial', "Please select serial device", QMessageBox.Yes) # portlist = SerialComboBox().get_port_list(self) # self.userCom = None # if portlist is not None: # for port in portlist: # print("port ",port) # self.userCom = port # if self.userCom is not None : # self.dataThread.openSerial(self.userCom) # else: # reply = QMessageBox.information(self, '没有设置串口', "请选择串口" , QMessageBox.Yes) def serialChange(self, i): print("serialChange", i, self.serialList.currentText()) if i > 0: self.userCom = self.serialList.currentText() self.dataThread.initSerialPort(self.userCom) def ctrlOpen(self): print("self.userCom", self.userCom) if self.userCom is None: self.checkSerial() return if self.open_status == 1: print('start send C command 0') self.open_status = 0 self.ctrlOpenButton.setText("Open") self.dataThread.sendData('CMDC\0') else: print('start send C command 1') self.open_status = 1 self.ctrlOpenButton.setText("Close") self.dataThread.sendData('CMDC\1') def evaluate(self): if self.userCom is None: self.checkSerial() return global evaluate_mode if evaluate_mode == "operate": print('start send E command 0') evaluate_mode = "evaluate" self.EvaluateButton.setText("Evaluate") self.dataThread.sendData('CMDE\1') else: print('start send E command 1') evaluate_mode = "operate" self.EvaluateButton.setText("Operate") self.dataThread.sendData('CMDE\0') def ctrlSendone(self): if self.userCom is None: self.checkSerial() return print('send a frame') self.dataThread.sendData('CMDC\2') def modeManual(self): if self.userCom is None: self.checkSerial() return if self.mode == 1: self.getOnePicButton.setEnabled(True) self.modeManualButton.setText("Manual") self.dataThread.sendData('CMDM\0') self.mode = 0 print('mode: manual') else: self.getOnePicButton.setEnabled(False) self.modeManualButton.setText("Auto") self.dataThread.sendData('CMDM\1') print('mode: auto') self.mode = 1 def modeAuto(self): if self.userCom is None: self.checkSerial() return print('mode: auto') self.dataThread.sendData('CMDM\1') def rate(self): if self.userCom is None: self.checkSerial() return global btn_index btn_index = (btn_index + 1) % 5 print('FPS:', strButton[btn_index]) self.modeFpsButton.setText(strButton[btn_index]) self.dataThread.sendData(strFpsCmd[btn_index]) #'CMDF\0') def objBody(self): if self.userCom is None: self.checkSerial() return if self.body == 1: self.body = 0 print('obj: Object') self.modeObjButton.setText("Object") self.dataThread.sendData('CMDO\0') else: self.body = 1 print('obj: Human Body') self.modeObjButton.setText("Body") self.dataThread.sendData('CMDO\1') def uiUpdate(self): global evaluate_mode print("update UI ", evaluate_mode) if evaluate_mode == "operate": self.EvaluateButton.setText("Operate") elif evaluate_mode == "evaluate": self.EvaluateButton.setText("Evaluate") else: self.EvaluateButton.setText("None") def cmdUpdate(self): if self.userCom is None: self.checkSerial() return print("get evaluate status and version\n") time.sleep(0.1) self.dataThread.sendData('CMDE\2') time.sleep(0.1) self.dataThread.sendData('CMDV\0') time.sleep(0.1) self.dataThread.sendData('CMDT\1') def commonOffset(self): if self.userCom is None: self.checkSerial() return self.dataThread.sendData('CMDT\1') print("Get commonOffset") def sysVer(self): if self.userCom is None: self.checkSerial() return self.dataThread.sendData('CMDV\1') print("Get firmware version and calibration version.") def setEvaluate(self): if self.userCom is None: self.checkSerial() return if self.evaluate == 1: self.evaluate = 0 self.evaluateButton.setText("Operate") self.dataThread.sendData('CMDE\0') else: self.evaluate = 1 self.evaluateButton.setText("Evaluate") self.dataThread.sendData('CMDE\1') def draw(self): global minHue global maxHue global maxHet global minHet global device_commonOffset global evaluate_mode if len(displayData) == 0: return font = QFont() color = QColor() font.setPointSize(self.fontSize) #font.setFamily("Microsoft YaHei") font.setLetterSpacing(QFont.AbsoluteSpacing, 0) index = 0 lock.acquire() frame = displayData.pop(0) lock.release() p = QPainter(self.cameraBuffer) p.fillRect(0, 0, self.width, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) # draw camera color = QColor() cneter = 0.0 if chip == "90640": if self.centerIndex == 0: centerIndex = 12 * 32 + 16 for yIndex in range(int(self.height / self.pixelSize)): for xIndex in range(int(self.width / self.pixelSize)): color.setHsvF(frame[index] / 360, 1.0, 1.0) p.fillRect(xIndex * self.pixelSize, yIndex * self.pixelSize, self.pixelSize, self.pixelSize, QBrush(color)) index = index + 1 cneter = round( mapValue(frame[self.centerIndex], minHue, maxHue, minHet, maxHet), 1) elif chip == "90621": if self.centerIndex == 0 or self.centerIndex >= 64: self.centerIndex = 2 * 16 + 8 cneter = round( mapValue(frame[self.centerIndex], minHue, maxHue, minHet, maxHet), 1) for yIndex in range(int(self.height / self.pixelSize / 6)): for xIndex in range(int(self.width / self.pixelSize / 2)): color.setHsvF(frame[index] / 360, 1.0, 1.0) p.fillRect(xIndex * self.pixelSize * 2, yIndex * self.pixelSize * 2 + 160, self.pixelSize * 2, self.pixelSize * 2, QBrush(color)) index = index + 1 elif chip == "90641": if self.centerIndex == 0 or self.centerIndex >= 192: self.centerIndex = 6 * 16 + 8 cneter = round( mapValue(frame[self.centerIndex], minHue, maxHue, minHet, maxHet), 1) for yIndex in range(int(self.height / self.pixelSize / 2)): for xIndex in range(int(self.width / self.pixelSize / 2)): color.setHsvF(frame[index] / 360, 1.0, 1.0) p.fillRect(xIndex * self.pixelSize * 2, yIndex * self.pixelSize * 2, self.pixelSize * 2, self.pixelSize * 2, QBrush(color)) index = index + 1 else: print("Dsiplay Error: can't detect any chip type!") self.cameraItem.setPixmap(self.cameraBuffer) self.frameCount = self.frameCount + 1 # draw text p = QPainter(self.hetTextBuffer) p.fillRect(0, 0, self.width + 200, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) version = self.dataThread.getID() p.setPen(QColor(Qt.white)) p.setFont(font) p.drawText(0, self.fontSize, " max:" + '{:.2f}'.format(maxHet)) p.drawText(self.textInterval, self.fontSize, " min:" + '{:.2f}'.format(minHet)) p.drawText(self.textInterval * 2, self.fontSize, "offset:" + '{:.2f}'.format(device_commonOffset)) p.drawText(self.textInterval * 3, self.fontSize, "mode:" + detect_status) p.drawText(self.textInterval * 4, self.fontSize, evaluate_mode) p.drawText(self.textInterval * 5, self.fontSize, "ID:" + str(version[0])) p.drawText(self.textInterval * 6, self.fontSize, "ver:" + str(version[1] & 0xff)) p.drawText(self.textInterval * 7, self.fontSize, chip) self.hetTextItem.setPixmap(self.hetTextBuffer) cneter = round( mapValue(frame[self.centerIndex], minHue, maxHue, minHet, maxHet), 1) centerText = "<font color=white>%s</font>" self.centerTextItem.setFont(font) self.centerTextItem.setHtml(centerText % (str(cneter) + "°")) # draw version text self.versionTextItem.setFont(font)
class RecordsetWindow(QWidget): dataDisplayRequest = pyqtSignal(str, int) dataUpdateRequest = pyqtSignal(str, Base) def __init__(self, manager, recordset: list, parent=None): super().__init__(parent=parent) self.UI = Ui_frmRecordsets() self.UI.setupUi(self) # Internal lists self.sensors = {} # List of sensors objects self.sensors_items = {} # List of QAction corresponding to each sensors self.sensors_graphs = {} # List of graph corresponding to each sensor graph self.sensors_location = [] # List of sensors location in this recordset self.sensors_blocks = {} # Sensor blocks - each block of data for each sensor # Variables self.time_pixmap = False # Flag used to check if we need to repaint the timeline or not self.zoom_level = 1 # Current timeview zoom level # Manually created UI objects self.time_bar = QGraphicsLineItem() # Currently selected timestamp bar self.selection_rec = QGraphicsRectItem() # Section rectangle self.sensors_menu = QMenu(self.UI.btnNewGraph) self.UI.btnNewGraph.setMenu(self.sensors_menu) # Data access informations self.dbMan = manager self.recordsets = recordset # Init temporal browser self.timeScene = QGraphicsScene() self.UI.graphTimeline.setScene(self.timeScene) self.UI.graphTimeline.fitInView(self.timeScene.sceneRect()) self.UI.graphTimeline.time_clicked.connect(self.timeview_clicked) self.UI.graphTimeline.time_selected.connect(self.timeview_selected) self.UI.scrollTimeline.valueChanged.connect(self.timeview_scroll) # Init temporal sensor list self.timeSensorsScene = QGraphicsScene() self.UI.graphSensorsTimeline.setScene(self.timeSensorsScene) self.UI.graphSensorsTimeline.fitInView(self.timeSensorsScene.sceneRect(), Qt.KeepAspectRatio) # Update general informations about recordsets self.update_recordset_infos() # Load sensors for that recordset self.load_sensors() # Connect signals to slots self.UI.btnClearSelection.clicked.connect(self.on_timeview_clear_selection_requested) self.UI.btnTimeZoomSelection.clicked.connect(self.on_timeview_zoom_selection_requested) self.UI.btnZoomReset.clicked.connect(self.on_timeview_zoom_reset_requested) self.UI.btnDisplayTimeline.clicked.connect(self.on_timeview_show_hide_requested) self.UI.btnTileHorizontal.clicked.connect(self.tile_graphs_horizontally) self.UI.btnTileVertical.clicked.connect(self.tile_graphs_vertically) self.UI.btnTileAuto.clicked.connect(self.tile_graphs_auto) self.sensors_menu.triggered.connect(self.sensor_graph_selected) # Initial UI state self.UI.btnZoomReset.setEnabled(False) self.UI.btnTimeZoomSelection.setEnabled(False) self.UI.btnClearSelection.setEnabled(False) self.update_tile_buttons_state() def paintEvent(self, paint_event): if not self.time_pixmap: self.refresh_timeview() self.time_pixmap = True def resizeEvent(self, resize_event): if self.time_pixmap: self.refresh_timeview() def refresh_timeview(self): QGuiApplication.setOverrideCursor(Qt.BusyCursor) # Computes required timescene size min_width = self.UI.graphTimeline.width() - 5 if len(self.recordsets) > 0: num_days = (self.get_recordset_end_day_date() - self.get_recordset_start_day_date()).days # Minimum size for days if num_days * 75 > min_width: min_width = num_days * 75 - 5 # Resize timeScene correctly self.timeScene.clear() self.timeScene.setSceneRect(self.timeScene.itemsBoundingRect()) self.timeScene.addLine(0, 80, min_width, 80, QPen(Qt.transparent)) # Set background color back_brush = QBrush(Qt.lightGray) self.timeScene.setBackgroundBrush(back_brush) self.timeSensorsScene.setBackgroundBrush(back_brush) # Update display self.draw_dates() self.draw_sensors_names() self.draw_recordsets() self.draw_sensors() self.draw_grid() self.draw_timebar() # Adjust splitter sizes self.adjust_timeview_size() # self.UI.frmSensors.hide() QGuiApplication.restoreOverrideCursor() def adjust_timeview_size(self): self.UI.frameScrollSpacer.setFixedWidth(self.UI.graphTimeline.pos().x()) if self.timeScene.itemsBoundingRect().width() * self.zoom_level > self.UI.graphTimeline.width(): self.UI.scrollTimeline.setVisible(True) # self.UI.scrollTimeline.setMinimum(self.UI.graphTimeline.width()/2) self.UI.scrollTimeline.setMinimum(0) self.UI.scrollTimeline.setMaximum(self.timeScene.itemsBoundingRect().width() * self.zoom_level) self.UI.scrollTimeline.setPageStep(self.UI.graphTimeline.width()/2) self.UI.scrollTimeline.setSingleStep(self.UI.graphTimeline.width()/5) else: self.UI.scrollTimeline.setVisible(False) def load_sensors(self): # self.UI.lstSensors.clear() self.sensors = {} self.sensors_items = {} self.sensors_location = [] self.sensors_menu.clear() if len(self.recordsets) > 0: for recordset in self.recordsets: for sensor in self.dbMan.get_sensors(recordset): if sensor.location not in self.sensors_location: self.sensors_location.append(sensor.location) self.sensors_menu.addSection(sensor.location) if sensor.id_sensor not in self.sensors: self.sensors[sensor.id_sensor] = sensor sensor_item = QAction(sensor.name) sensor_item.setCheckable(True) sensor_item.setProperty("sensor_id", sensor.id_sensor) self.sensors_items[sensor.id_sensor] = sensor_item self.sensors_menu.addAction(sensor_item) # Create sensors blocks for display self.load_sensors_blocks() else: self.UI.btnNewGraph.setEnabled(False) def update_recordset_infos(self): if len(self.recordsets) == 0: self.UI.lblTotalValue.setText("Aucune donnée.") self.UI.lblDurationValue.setText("Aucune donnée.") return start_time = self.recordsets[0].start_timestamp end_time = self.recordsets[len(self.recordsets) - 1].end_timestamp # Coverage self.UI.lblTotalValue.setText(start_time.strftime('%d-%m-%Y %H:%M:%S') + " @ " + end_time.strftime( '%d-%m-%Y %H:%M:%S')) # Duration # TODO: format better self.UI.lblDurationValue.setText(str(end_time - start_time)) self.UI.lblCursorTime.setText(start_time.strftime('%d-%m-%Y %H:%M:%S')) def get_recordset_start_day_date(self): if len(self.recordsets) == 0: return None start_time = self.recordsets[0].start_timestamp start_time = (datetime(start_time.year, start_time.month, start_time.day, 0, 0, 0)) return start_time def get_recordset_end_day_date(self): if len(self.recordsets) == 0: return None end_time = self.recordsets[len(self.recordsets) - 1].end_timestamp end_time = (datetime(end_time.year, end_time.month, end_time.day, 0, 0, 0) + timedelta(days=1)) return end_time def get_relative_timeview_pos(self, current_time): # start_time = self.recordsets[0].start_timestamp.timestamp() start_time = self.get_recordset_start_day_date().timestamp() # end_time = self.recordsets[len(self.recordsets) - 1].end_timestamp.timestamp() end_time = self.get_recordset_end_day_date().timestamp() time_span = (end_time - start_time) # Total number of seconds in recordsets # if type(current_time) is datetime: if isinstance(current_time, datetime): current_time = current_time.timestamp() if time_span > 0: # return ((current_time - start_time) / time_span) * self.UI.graphTimeline.width() return ((current_time - start_time) / time_span) * self.timeScene.width() else: return 0 def get_time_from_timeview_pos(self, pos): if len(self.recordsets) == 0: return None; start_time = self.get_recordset_start_day_date().timestamp() end_time = self.get_recordset_end_day_date().timestamp() current_time = (pos / self.timeScene.width()) * (end_time - start_time) + start_time current_time = datetime.fromtimestamp(current_time) return current_time def draw_dates(self): if len(self.recordsets) == 0: return # Computations start_time = self.recordsets[0].start_timestamp end_time = self.recordsets[len(self.recordsets) - 1].end_timestamp # time_span = (end_time - start_time).total_seconds() # Total number of seconds in recordsets current_time = (datetime(start_time.year, start_time.month, start_time.day, 0, 0, 0) + timedelta(days=1)) # Drawing tools black_pen = QPen(Qt.black) blue_brush = QBrush(Qt.darkBlue) # Date background self.timeScene.addRect(0, 0, self.timeScene.width(), 20, black_pen, blue_brush) self.timeSensorsScene.addRect(0, 0, self.timeSensorsScene.width(), 20, black_pen, blue_brush) # First date date_text = self.timeScene.addText(start_time.strftime("%d-%m-%Y")) date_text.setPos(0, 0) # -5 date_text.setDefaultTextColor(Qt.white) date_text.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) # Date separators while current_time <= end_time: pos = self.get_relative_timeview_pos(current_time) date_text = self.timeScene.addText(current_time.strftime("%d-%m-%Y")) date_text.setPos(pos, 0) # -5 date_text.setDefaultTextColor(Qt.white) date_text.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) current_time += timedelta(days=1) # self.UI.graphTimeline.fitInView(self.timeScene.sceneRect(), Qt.KeepAspectRatio) def draw_grid(self): if len(self.recordsets) == 0: return # Computations start_time = self.recordsets[0].start_timestamp end_time = self.recordsets[len(self.recordsets) - 1].end_timestamp # time_span = (end_time - start_time).total_seconds() # Total number of seconds in recordsets current_time = (datetime(start_time.year, start_time.month, start_time.day, 0, 0, 0) + timedelta(days=1)) vgrid_pen = QPen(Qt.gray) hgrid_pen = QPen(Qt.black) vgrid_pen.setCosmetic(True) # Horizontal lines pos = 20 # last_location = "" sensor_location_brush = QBrush(Qt.black) sensor_location_pen = QPen(Qt.transparent) for location in self.sensors_location: # Must create a new location line self.timeScene.addRect(0, pos, self.timeScene.width() - 1, 15, sensor_location_pen, sensor_location_brush) pos += 15 sensors = self.get_sensors_for_location(location) for _ in sensors: self.timeScene.addLine(0, pos, self.timeScene.width() - 1, pos, hgrid_pen) self.timeSensorsScene.addLine(0, pos, self.timeSensorsScene.width(), pos, hgrid_pen) pos += 20 # Final line self.timeScene.addLine(0, pos, self.timeScene.width() - 1, pos, hgrid_pen) self.timeSensorsScene.addLine(0, pos, self.timeSensorsScene.width() - 1, pos, hgrid_pen) # Date separators self.timeScene.addLine(0, 0, 0, self.timeScene.height(), vgrid_pen) # Other dates while current_time <= end_time: pos = self.get_relative_timeview_pos(current_time) self.timeScene.addLine(pos, 0, pos, self.timeScene.height(), vgrid_pen) current_time += timedelta(days=1) def draw_recordsets(self): recordset_brush = QBrush(QColor(212, 247, 192)) # Green recordset_pen = QPen(Qt.transparent) # Recording length for record in self.recordsets: start_pos = self.get_relative_timeview_pos(record.start_timestamp) end_pos = self.get_relative_timeview_pos(record.end_timestamp) span = end_pos - start_pos # print (str(span)) self.timeScene.addRect(start_pos, 21, span, self.timeSensorsScene.height()-21, recordset_pen, recordset_brush) # self.UI.graphTimeline.update() return def draw_sensors_names(self): if len(self.sensors) == 0: return sensor_location_brush = QBrush(Qt.black) sensor_location_pen = QPen(Qt.transparent) # Sensor names pos = 20 for location in self.sensors_location: # Must create a new location space for later pos += 15 sensors = self.get_sensors_for_location(location) for sensor_id in sensors: sensor = self.sensors[sensor_id] # Sensor names label = self.timeSensorsScene.addText(sensor.name) label.setPos(0, pos) label.setDefaultTextColor(Qt.black) # label.setFont(QFont("Times", 10, QFont.Bold)) pos += 20 # Adjust size appropriately self.timeSensorsScene.setSceneRect(self.timeSensorsScene.itemsBoundingRect()) self.UI.graphSensorsTimeline.setMaximumWidth(self.timeSensorsScene.itemsBoundingRect().width()) # Sensor location background pos = 20 for location in self.sensors_location: # Must create a new location line self.timeSensorsScene.addRect(0, pos, self.timeSensorsScene.width(), 15, sensor_location_pen, sensor_location_brush) label = self.timeSensorsScene.addText(location) label.setPos(0, pos) label.setDefaultTextColor(Qt.white) label.setFont(QFont("Times", 7)) pos += 15 sensors = self.get_sensors_for_location(location) for sensor_id in sensors: pos += 20 def draw_sensors(self): if len(self.sensors) == 0: return sensor_brush = QBrush(Qt.darkGreen) sensor_pen = QPen(Qt.transparent) sensors_rects = self.create_sensors_rects() for _, rect in enumerate(sensors_rects): self.timeScene.addRect(rect, sensor_pen, sensor_brush) # Adjust size appropriately self.timeSensorsScene.setSceneRect(self.timeSensorsScene.itemsBoundingRect()) self.UI.graphSensorsTimeline.setMaximumWidth(self.timeSensorsScene.itemsBoundingRect().width()) # self.UI.graphSensorsTimeline.setMaximumHeight(self.timeSensorsScene.itemsBoundingRect().height()) def load_sensors_blocks(self): # Create request tasks tasks = [] for location in self.sensors_location: sensors = self.get_sensors_for_location(location) for sensor_id in sensors: for record in self.recordsets: tasks.append(DBSensorTimesTask(title="Chargement des données temporelles", db_manager=self.dbMan, sensor_id=sensor_id, recordset=record)) QGuiApplication.setOverrideCursor(Qt.BusyCursor) process = BackgroundProcess(tasks) dialog = ProgressDialog(process, "Chargement") process.start() dialog.exec() QGuiApplication.restoreOverrideCursor() # Combine tasks results self.sensors_blocks = {} for task in tasks: for result in task.results: if result['sensor_id'] not in self.sensors_blocks: self.sensors_blocks[result['sensor_id']] = [] start_time = result['start_time'] end_time = result['end_time'] data = {"start_time": start_time, "end_time": end_time} self.sensors_blocks[result['sensor_id']].append(data) def create_sensors_rects(self): rects = [] pos = 20 for location in self.sensors_location: # Must create a new location space for later pos += 15 sensors = self.get_sensors_for_location(location) for sensor_id in sensors: # sensor = self.sensors[sensor_id] # for record in self.recordsets: # datas = self.dbMan.get_all_sensor_data(sensor=sensor, recordset=record, channel=sensor.channels[0]) # for data in datas: # start_pos = self.get_relative_timeview_pos(data.timestamps.start_timestamp) # end_pos = self.get_relative_timeview_pos(data.timestamps.end_timestamp) # span = max(end_pos - start_pos, 1) # rects.append(QRectF(start_pos, pos + 3, span, 14)) if sensor_id in self.sensors_blocks: for block in self.sensors_blocks[sensor_id]: start_pos = self.get_relative_timeview_pos(block['start_time']) end_pos = self.get_relative_timeview_pos(block['end_time']) span = max(end_pos - start_pos, 1) rects.append(QRectF(start_pos, pos + 3, span, 14)) pos += 20 return rects def draw_timebar(self): line_pen = QPen(Qt.cyan) line_pen.setWidth(2) self.time_bar = self.timeScene.addLine(1, 21, 1, self.timeScene.height()-1, line_pen) # self.time_bar = self.timeScene.addLine(0, 1, 0, self.timeScene.height() - 1, line_pen) self.time_bar.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) def get_sensors_for_location(self, location): sensors_id = [] for sensor in self.sensors.values(): if sensor.location == location: sensors_id.append(sensor.id_sensor) return sensors_id @staticmethod def get_sensor_graph_type(sensor): if sensor.id_sensor_type == SensorType.ACCELEROMETER \ or sensor.id_sensor_type == SensorType.GYROMETER \ or sensor.id_sensor_type == SensorType.BATTERY \ or sensor.id_sensor_type == SensorType.LUX \ or sensor.id_sensor_type == SensorType.CURRENT \ or sensor.id_sensor_type == SensorType.BAROMETER \ or sensor.id_sensor_type == SensorType.MAGNETOMETER \ or sensor.id_sensor_type == SensorType.TEMPERATURE \ or sensor.id_sensor_type == SensorType.HEARTRATE \ or sensor.id_sensor_type == SensorType.ORIENTATION \ or sensor.id_sensor_type == SensorType.FSR: return GraphType.LINECHART if sensor.id_sensor_type == SensorType.GPS: return GraphType.MAP return GraphType.UNKNOWN @pyqtSlot(Sensor, datetime, datetime) def query_sensor_data(self, sensor: Sensor, start_time: datetime, end_time: datetime): timeseries = self.get_sensor_data(sensor, start_time, end_time)[0] if self.sensors_graphs[sensor.id_sensor]: graph_type = self.get_sensor_graph_type(sensor) graph_window = self.sensors_graphs[sensor.id_sensor] if graph_type == GraphType.LINECHART: series_id = 0 for series in timeseries: # Filter times that don't fit in the range y_range = series['y'] x_range = series['x'] y_range = y_range[x_range >= start_time.timestamp()] x_range = x_range[x_range >= start_time.timestamp()] y_range = y_range[x_range <= end_time.timestamp()] x_range = x_range[x_range <= end_time.timestamp()] if len(x_range)>0 and len(y_range)>0: graph_window.graph.update_data(x_range, y_range, series_id) series_id += 1 return @pyqtSlot(QAction) # @timing def sensor_graph_selected(self, sensor_item): sensor_id = sensor_item.property("sensor_id") sensor = self.sensors[sensor_id] sensor_label = sensor.name + " (" + sensor.location + ")" if sensor_item.isChecked(): # Choose the correct display for each sensor graph_window = None timeseries, channel_data = self.get_sensor_data(sensor) # Fetch all sensor data # Color map for curves colors = [Qt.blue, Qt.green, Qt.yellow, Qt.red] graph_type = self.get_sensor_graph_type(sensor) graph_window = GraphWindow(graph_type, sensor, self.UI.mdiArea) graph_window.setStyleSheet(self.styleSheet() + graph_window.styleSheet()) if graph_type == GraphType.LINECHART: # Add series for series in timeseries: graph_window.graph.add_data(series['x'], series['y'], color=colors.pop(), legend_text=series['label']) graph_window.graph.set_title(sensor_label) if graph_type == GraphType.MAP: for data in channel_data: gps = GPSGeodetic() gps.from_bytes(data.data) if gps.latitude != 0 and gps.longitude != 0: graph_window.graph.addPosition(data.timestamps.start_timestamp, gps.latitude / 1e7, gps.longitude / 1e7) graph_window.setCursorPositionFromTime(data.timestamps.start_timestamp) if graph_window is not None: self.UI.mdiArea.addSubWindow(graph_window).setWindowTitle(sensor_label) self.sensors_graphs[sensor.id_sensor] = graph_window # self.UI.displayContents.layout().insertWidget(0,graph) graph_window.show() QApplication.instance().processEvents() graph_window.aboutToClose.connect(self.graph_was_closed) graph_window.requestData.connect(self.query_sensor_data) graph_window.graph.cursorMoved.connect(self.graph_cursor_changed) graph_window.graph.selectedAreaChanged.connect(self.graph_selected_area_changed) graph_window.graph.clearedSelectionArea.connect(self.on_timeview_clear_selection_requested) graph_window.zoomAreaRequested.connect(self.graph_zoom_area) graph_window.zoomResetRequested.connect(self.graph_zoom_reset) self.UI.mdiArea.tileSubWindows() else: # Remove from display try: if self.sensors_graphs[sensor.id_sensor] is not None: self.UI.mdiArea.removeSubWindow(self.sensors_graphs[sensor.id_sensor].parent()) self.sensors_graphs[sensor.id_sensor].hide() del self.sensors_graphs[sensor.id_sensor] self.UI.mdiArea.tileSubWindows() except KeyError: pass self.update_tile_buttons_state() # @timing def get_sensor_data(self, sensor, start_time=None, end_time=None): QGuiApplication.setOverrideCursor(Qt.BusyCursor) task = DBSensorAllDataTask("Chargement des données...", self.dbMan, sensor, start_time, end_time, self.recordsets) process = BackgroundProcess([task]) dialog = ProgressDialog(process, "Traitement") process.start() dialog.exec() QGuiApplication.restoreOverrideCursor() return task.results['timeseries'], task.results['channel_data'] def update_tile_buttons_state(self): if self.sensors_graphs.keys().__len__() > 1: self.UI.btnTileAuto.setEnabled(True) self.UI.btnTileHorizontal.setEnabled(True) self.UI.btnTileVertical.setEnabled(True) else: self.UI.btnTileAuto.setEnabled(False) self.UI.btnTileHorizontal.setEnabled(False) self.UI.btnTileVertical.setEnabled(False) @pyqtSlot(QObject) def graph_was_closed(self, graph): for sensor_id, sensor_graph in self.sensors_graphs.items(): if sensor_graph == graph: # self.sensors_graphs[sensor_id] = None del self.sensors_graphs[sensor_id] self.sensors_items[sensor_id].setChecked(False) break self.UI.mdiArea.tileSubWindows() self.update_tile_buttons_state() @pyqtSlot(float) def graph_cursor_changed(self, timestamp): current_time = timestamp / 1000 for graph in self.sensors_graphs.values(): if graph is not None: graph.setCursorPositionFromTime(current_time, False) pos = self.get_relative_timeview_pos(current_time) self.time_bar.setPos(pos,0) # Ensure time bar is visible if scrollable self.ensure_time_bar_visible(pos) self.UI.lblCursorTime.setText(datetime.fromtimestamp(current_time).strftime('%d-%m-%Y %H:%M:%S')) def ensure_time_bar_visible(self, pos): if self.UI.scrollTimeline.isVisible(): max_visible_x = self.UI.graphTimeline.mapToScene(self.UI.graphTimeline.rect()).boundingRect().x() \ + self.UI.graphTimeline.mapToScene(self.UI.graphTimeline.rect()).boundingRect().width() min_visible_x = self.UI.graphTimeline.mapToScene(self.UI.graphTimeline.rect()).boundingRect().x() if pos < min_visible_x or pos > max_visible_x: self.UI.scrollTimeline.setValue(pos) @pyqtSlot(datetime, datetime) def graph_zoom_area(self, start_time, end_time): for graph in self.sensors_graphs.values(): if graph is not None: graph.zoomAreaRequestTime(start_time, end_time) @pyqtSlot() def graph_zoom_reset(self): for graph in self.sensors_graphs.values(): if graph is not None: graph.zoomResetRequest(False) @pyqtSlot(float, float) def graph_selected_area_changed(self, start_timestamp, end_timestamp): # Update timeview selection area start_pos = self.get_relative_timeview_pos(start_timestamp / 1000) end_pos = self.get_relative_timeview_pos(end_timestamp / 1000) self.timeview_selected(start_pos, end_pos) # Ensure time bar is visible if scrollable self.ensure_time_bar_visible(start_pos) # Update selection for each graph for graph in self.sensors_graphs.values(): if graph is not None: graph.setSelectionAreaFromTime(start_timestamp, end_timestamp) @pyqtSlot(int) def timeview_scroll(self, pos): self.UI.graphTimeline.centerOn(pos / self.zoom_level, 0) @pyqtSlot(float) def timeview_clicked(self, x): self.time_bar.setPos(x, 0) if len(self.recordsets)==0: return # Find time corresponding to that position timestamp = self.get_time_from_timeview_pos(x) self.UI.lblCursorTime.setText(timestamp.strftime('%d-%m-%Y %H:%M:%S')) for graph in self.sensors_graphs.values(): if graph is not None: # try: graph.setCursorPositionFromTime(timestamp, False) # except AttributeError: # continue @pyqtSlot(float, float) def timeview_selected(self, start_x, end_x): selection_brush = QBrush(QColor(153, 204, 255, 128)) selection_pen = QPen(Qt.transparent) self.timeScene.removeItem(self.selection_rec) self.selection_rec = self.timeScene.addRect(start_x, 20, end_x-start_x, self.timeScene.height()-20, selection_pen, selection_brush) self.UI.btnClearSelection.setEnabled(True) self.UI.btnTimeZoomSelection.setEnabled(True) # Update selection for each graph for graph in self.sensors_graphs.values(): if graph is not None: graph.setSelectionAreaFromTime(self.get_time_from_timeview_pos(start_x), self.get_time_from_timeview_pos(end_x)) @pyqtSlot() def on_timeview_clear_selection_requested(self): self.timeScene.removeItem(self.selection_rec) self.UI.btnClearSelection.setEnabled(False) self.UI.btnTimeZoomSelection.setEnabled(False) # Clear all selected areas in graphs for graph in self.sensors_graphs.values(): graph.clearSelectionArea() @pyqtSlot() def on_timeview_zoom_selection_requested(self): self.UI.graphTimeline.scale(1 / self.zoom_level, 1) # zoom_value = (self.timeScene.width() / (self.selection_rec.rect().width())) zoom_value = (self.UI.graphTimeline.width() / (self.selection_rec.rect().width())) self.zoom_level = zoom_value self.UI.graphTimeline.scale(zoom_value, 1) self.UI.btnZoomReset.setEnabled(True) self.adjust_timeview_size() # self.UI.graphTimeline.ensureVisible(self.selection_rec.rect(), 0, 0) # self.UI.graphTimeline.centerOn(self.selection_rec.rect().x() + self.selection_rec.rect().width() / 2, 0) self.UI.scrollTimeline.setValue((self.selection_rec.rect().x() + self.selection_rec.rect().width() / 2) * self.zoom_level) self.on_timeview_clear_selection_requested() @pyqtSlot() def on_timeview_zoom_reset_requested(self): self.UI.graphTimeline.scale(1 / self.zoom_level, 1) self.zoom_level = 1 self.UI.btnZoomReset.setEnabled(False) self.adjust_timeview_size() self.UI.scrollTimeline.setValue(0) @pyqtSlot() def on_timeview_show_hide_requested(self): visible = not self.UI.frameTimeline.isVisible() self.UI.frameTimeline.setVisible(visible) self.UI.frameTimelineControls.setVisible(visible) # self.UI.lblCursorTime.setVisible(visible) @pyqtSlot() def on_process_recordset(self): # Display Process Window window = ProcessSelectWindow(self.dbMan, self.recordsets) window.setStyleSheet(self.styleSheet()) if window.exec() == QDialog.Accepted: self.dataUpdateRequest.emit("result", window.processed_data) self.dataDisplayRequest.emit("result", window.processed_data.id_processed_data) @pyqtSlot() def tile_graphs_horizontally(self): self.tile_graphs(True) @pyqtSlot() def tile_graphs_vertically(self): self.tile_graphs(False) def tile_graphs(self, horizontal: bool): if self.UI.mdiArea.subWindowList() is None: return position = QPoint(0, 0) for window in self.UI.mdiArea.subWindowList(): if horizontal: rect = QRect(0, 0, self.UI.mdiArea.width() / len(self.UI.mdiArea.subWindowList()), self.UI.mdiArea.height()) else: rect = QRect(0, 0, self.UI.mdiArea.width(), self.UI.mdiArea.height() / len(self.UI.mdiArea.subWindowList())) window.setGeometry(rect) window.move(position) if horizontal: position.setX(position.x() + window.width()) else: position.setY(position.y() + window.height()) @pyqtSlot() def tile_graphs_auto(self): self.UI.mdiArea.tileSubWindows()
class painter(QGraphicsView): narrowRatio = int(sys.argv[4]) if len(sys.argv) >= 5 else 1 useBlur = sys.argv[5] != "False" if len(sys.argv) >= 6 else True pixelSize = int(15 / narrowRatio) width = int(480 / narrowRatio) height = int(360 / narrowRatio) fontSize = int(30 / narrowRatio) anchorLineSize = int(100 / narrowRatio) ellipseRadius = int(8 / narrowRatio) textInterval = int(90 / narrowRatio) col = width / pixelSize line = height / pixelSize centerIndex = int(round(((line / 2 - 1) * col) + col / 2)) frameCount = 0 baseZValue = 0 textLineHeight = fontSize + 10 blurRaduis = 50 # Smoother improvement def __init__(self): super(painter, self).__init__() self.setFixedSize(self.width, self.height + self.textLineHeight) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() self.setScene(self.scene) # center het text item self.centerTextItem = QGraphicsTextItem() self.centerTextItem.setPos(self.width / 2 - self.fontSize, 0) self.centerTextItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.centerTextItem) # center anchor item centerX = self.width / 2 centerY = self.height / 2 self.ellipseItem = QGraphicsEllipseItem(0, 0, self.ellipseRadius * 2, self.ellipseRadius * 2) self.horLineItem = QGraphicsLineItem(0, 0, self.anchorLineSize, 0) self.verLineItem = QGraphicsLineItem(0, 0, 0, self.anchorLineSize) self.ellipseItem.setPos(centerX - self.ellipseRadius, centerY - self.ellipseRadius) self.horLineItem.setPos(centerX - self.anchorLineSize / 2, centerY) self.verLineItem.setPos(centerX, centerY - self.anchorLineSize / 2) self.ellipseItem.setPen(QColor(Qt.white)) self.horLineItem.setPen(QColor(Qt.white)) self.verLineItem.setPen(QColor(Qt.white)) self.ellipseItem.setZValue(self.baseZValue + 1) self.horLineItem.setZValue(self.baseZValue + 1) self.verLineItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.ellipseItem) self.scene.addItem(self.horLineItem) self.scene.addItem(self.verLineItem) # camera item self.cameraBuffer = QPixmap(self.width, self.height + self.textLineHeight) self.cameraItem = QGraphicsPixmapItem() if self.useBlur: self.gusBlurEffect = QGraphicsBlurEffect() self.gusBlurEffect.setBlurRadius(self.blurRaduis) self.cameraItem.setGraphicsEffect(self.gusBlurEffect) self.cameraItem.setPos(0, 0) self.cameraItem.setZValue(self.baseZValue) self.scene.addItem(self.cameraItem) # het text item self.hetTextBuffer = QPixmap(self.width, self.textLineHeight) self.hetTextItem = QGraphicsPixmapItem() self.hetTextItem.setPos(0, self.height) self.hetTextItem.setZValue(self.baseZValue) self.scene.addItem(self.hetTextItem) def draw(self): if len(hetaData) == 0: return font = QFont() color = QColor() font.setPointSize(self.fontSize) font.setFamily("Microsoft YaHei") font.setLetterSpacing(QFont.AbsoluteSpacing, 0) index = 0 lock.acquire() frame = hetaData.pop(0) lock.release() maxHet = frame["maxHet"] minHet = frame["minHet"] frame = frame["frame"] p = QPainter(self.cameraBuffer) p.fillRect(0, 0, self.width, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) # draw camera color = QColor() for yIndex in range(int(self.height / self.pixelSize)): for xIndex in range(int(self.width / self.pixelSize)): tempData = constrain( mapValue(frame[index], minHet, maxHet, minHue, maxHue), minHue, maxHue) color.setHsvF(tempData / 360, 1.0, 1.0) p.fillRect(xIndex * self.pixelSize, yIndex * self.pixelSize, self.pixelSize, self.pixelSize, QBrush(color)) index = index + 1 self.cameraItem.setPixmap(self.cameraBuffer) # draw text p = QPainter(self.hetTextBuffer) p.fillRect(0, 0, self.width, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) hetDiff = maxHet - minHet bastNum = round(minHet) interval = round(hetDiff / 5) for i in range(5): hue = constrain( mapValue((bastNum + (i * interval)), minHet, maxHet, minHue, maxHue), minHue, maxHue) color.setHsvF(hue / 360, 1.0, 1.0) p.setPen(color) p.setFont(font) p.drawText(i * self.textInterval, self.fontSize + 3, str(bastNum + (i * interval)) + "°") self.hetTextItem.setPixmap(self.hetTextBuffer) # draw center het text cneter = round(frame[self.centerIndex], 1) centerText = "<font color=white>%s</font>" self.centerTextItem.setFont(font) self.centerTextItem.setHtml(centerText % (str(cneter) + "°")) self.frameCount = self.frameCount + 1 print("picture->" + str(self.frameCount))
class RotaryDialHoverRegion(QGraphicsEllipseItem): def __init__(self, rect, parent=None): # setup DNA line super(QGraphicsEllipseItem, self).__init__(rect, parent) self._parent = parent self.setPen(QPen(Qt.NoPen)) self.setBrush(_HOVER_BRUSH) self.setAcceptHoverEvents(True) # hover marker self._hoverLine = QGraphicsLineItem(-_ROTARY_DELTA_WIDTH/2, 0, _ROTARY_DELTA_WIDTH/2, 0, self) self._hoverLine.setPen(QPen(QColor(204, 0, 0), .5)) self._hoverLine.hide() self._startPos = None self._startAngle = None # save selection start self._clockwise = None self.dummy = RotaryDialDeltaItem(0, 0, parent) self.dummy.hide() def updateRect(self, rect): self.setRect(rect) def hoverEnterEvent(self, event): self.updateHoverLine(event) self._hoverLine.show() # end def def hoverMoveEvent(self, event): self.updateHoverLine(event) # end def def hoverLeaveEvent(self, event): self._hoverLine.hide() # end def def mousePressEvent(self, event): r = _RADIUS self.updateHoverLine(event) pos = self._hoverLine.pos() aX, aY, angle = self.snapPosToCircle(pos, r) if angle != None: self._startPos = QPointF(aX, aY) self._startAngle = self.updateHoverLine(event) self.dummy.updateAngle(self._startAngle, 0) self.dummy.show() # mark the start # f = QGraphicsEllipseItem(pX, pY, 2, 2, self) # f.setPen(QPen(Qt.NoPen)) # f.setBrush(QBrush(QColor(204, 0, 0))) # end def def mouseMoveEvent(self, event): eventAngle = self.updateHoverLine(event) # Record initial direction before calling getSpanAngle if self._clockwise is None: self._clockwise = False if eventAngle > self._startAngle else True spanAngle = self.getSpanAngle(eventAngle) self.dummy.updateAngle(self._startAngle, spanAngle) # end def def mouseReleaseEvent(self, event): self.dummy.hide() endAngle = self.updateHoverLine(event) spanAngle = self.getSpanAngle(endAngle) old_angle = self._parent.virtualHelix().getProperty('eulerZ') new_angle = round((old_angle - spanAngle) % 360,0) self._parent.virtualHelix().setProperty('eulerZ', new_angle) # mark the end # x = self._hoverLine.x() # y = self._hoverLine.y() # f = QGraphicsEllipseItem(x, y, 6, 6, self) # f.setPen(QPen(Qt.NoPen)) # f.setBrush(QBrush(QColor(204, 0, 0, 128))) # end def def updateHoverLine(self, event): """ Moves red line to point (aX,aY) on RotaryDialLine closest to event.pos. Returns the angle of aX, aY, using the Qt arc coordinate system (0 = east, 90 = north, 180 = west, 270 = south). """ r = _RADIUS aX, aY, angle = self.snapPosToCircle(event.pos(), r) if angle != None: self._hoverLine.setPos(aX, aY) self._hoverLine.setRotation(-angle) return angle # end def def snapPosToCircle(self, pos, radius): """Given x, y and radius, return x,y of nearest point on circle, and its angle""" pX = pos.x() pY = pos.y() cX = cY = radius vX = pX - cX vY = pY - cY magV = sqrt(vX*vX + vY*vY) if magV == 0: return (None, None, None) aX = cX + vX / magV * radius aY = cY + vY / magV * radius angle = (atan2(aY-cY, aX-cX)) deg = -degrees(angle) if angle < 0 else 180+(180-degrees(angle)) return (aX, aY, deg) # end def def getSpanAngle(self, angle): """ Return the spanAngle angle by checking the initial direction of the selection. Selections that cross 0° must be handed as an edge case. """ if self._clockwise: # spanAngle is negative if angle < self._startAngle: spanAngle = angle - self._startAngle else: spanAngle = -(self._startAngle + (360-angle)) else: # counterclockwise, spanAngle is positive if angle > self._startAngle: spanAngle = angle - self._startAngle else: spanAngle = (360-self._startAngle) + angle return spanAngle
class painter(QGraphicsView): pixelSize = int(15 / narrowRatio) width = int(480 / narrowRatio) height = int(360 / narrowRatio) fontSize = int(30 / narrowRatio) anchorLineSize = int(100 / narrowRatio) ellipseRadius = int(8 / narrowRatio) textInterval = int(90 / narrowRatio) col = width / pixelSize line = height / pixelSize centerIndex = int(round(((line / 2 - 1) * col) + col / 2)) frameCount = 0 baseZValue = 0 mode = 1 body = 1 open_status = 0 textLineHeight = fontSize + 10 blurRaduis = 50 # Smoother improvement def __init__(self, dataThread): super(painter, self).__init__() self.dataThread = dataThread self.setFixedSize(self.width, self.height + self.textLineHeight) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() self.setScene(self.scene) # center het text item self.centerTextItem = QGraphicsTextItem() self.centerTextItem.setPos(self.width / 2 - self.fontSize, 0) self.centerTextItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.centerTextItem) # center anchor item centerX = self.width / 2 centerY = self.height / 2 self.ellipseItem = QGraphicsEllipseItem(0, 0, self.ellipseRadius * 2, self.ellipseRadius * 2) self.horLineItem = QGraphicsLineItem(0, 0, self.anchorLineSize, 0) self.verLineItem = QGraphicsLineItem(0, 0, 0, self.anchorLineSize) self.ellipseItem.setPos(centerX - self.ellipseRadius, centerY - self.ellipseRadius) self.horLineItem.setPos(centerX - self.anchorLineSize / 2, centerY) self.verLineItem.setPos(centerX, centerY - self.anchorLineSize / 2) self.ellipseItem.setPen(QColor(Qt.white)) self.horLineItem.setPen(QColor(Qt.white)) self.verLineItem.setPen(QColor(Qt.white)) self.ellipseItem.setZValue(self.baseZValue + 1) self.horLineItem.setZValue(self.baseZValue + 1) self.verLineItem.setZValue(self.baseZValue + 1) self.scene.addItem(self.ellipseItem) self.scene.addItem(self.horLineItem) self.scene.addItem(self.verLineItem) # camera item self.cameraBuffer = QPixmap(self.width, self.height + self.textLineHeight) self.cameraItem = QGraphicsPixmapItem() if useBlur: self.gusBlurEffect = QGraphicsBlurEffect() self.gusBlurEffect.setBlurRadius(self.blurRaduis) self.cameraItem.setGraphicsEffect(self.gusBlurEffect) self.cameraItem.setPos(0, 0) self.cameraItem.setZValue(self.baseZValue) self.scene.addItem(self.cameraItem) # het text item self.hetTextBuffer = QPixmap(self.width, self.textLineHeight) self.hetTextItem = QGraphicsPixmapItem() self.hetTextItem.setPos(0, self.height) self.hetTextItem.setZValue(self.baseZValue) self.scene.addItem(self.hetTextItem) # button item self.ctrlOpenButton = QPushButton('Open', self) self.ctrlOpenButton.clicked.connect(self.ctrl_open) self.ctrlOpenButton.setGeometry(10, 30, 100, 40) ''' self.ctrlCloseButton = QPushButton('stop send',self) self.ctrlCloseButton.clicked.connect(self.ctrl_close) self.ctrlCloseButton.setGeometry(10,80,100,40) ''' self.getOnePicButton = QPushButton('send a frame', self) self.getOnePicButton.clicked.connect(self.ctrl_sendone) self.getOnePicButton.setGeometry(10, 130, 100, 40) self.getOnePicButton.setEnabled(False) self.modeManualButton = QPushButton('Auto', self) self.modeManualButton.clicked.connect(self.mode_manual) self.modeManualButton.setGeometry(10, 180, 100, 40) self.modeObjButton = QPushButton('Body', self) self.modeObjButton.clicked.connect(self.obj_body) self.modeObjButton.setGeometry(10, 230, 100, 40) ''' self.modeAutoButton = QPushButton('mode: auto',self) self.modeAutoButton.clicked.connect(self.mode_auto) self.modeAutoButton.setGeometry(10,230,100,40) ''' self.modeFpsButton = QPushButton('3fps', self) self.modeFpsButton.clicked.connect(self.rate_0) self.modeFpsButton.setGeometry(10, 280, 100, 40) self.blackbodyEdit = QLineEdit() self.blackbodyEdit.setGeometry(270, 200, 100, 40) self.blackbodyEdit.setText('37') self.calibrateButton = QPushButton(calibrateStr[0], self) self.calibrateButton.clicked.connect(self.calibrate_handle) self.calibrateButton.setGeometry(370, 280, 100, 40) ''' self.modeAutoButton = QPushButton('1fps',self) self.modeAutoButton.clicked.connect(self.rate_1) self.modeAutoButton.setGeometry(35,280,50,40) self.modeAutoButton = QPushButton('2fps',self) self.modeAutoButton.clicked.connect(self.rate_2) self.modeAutoButton.setGeometry(60,280,50,40) self.modeAutoButton = QPushButton('3fps',self) self.modeAutoButton.clicked.connect(self.rate_3) self.modeAutoButton.setGeometry(85,280,50,40) ''' ''' self.modeAutoButton = QPushButton('obj: common',self) self.modeAutoButton.clicked.connect(self.obj_common) self.modeAutoButton.setGeometry(370,80,100,40) ''' # self.modeAutoButton = QPushButton('version',self) # self.modeAutoButton.clicked.connect(self.sys_ver) # self.modeAutoButton.setGeometry(370,230,100,40) def ctrl_open(self): if self.open_status == 1: print('start send C command 0') self.open_status = 0 self.ctrlOpenButton.setText("Open") self.dataThread.send_data('CMDC\0') else: print('start send C command 1') self.open_status = 1 self.ctrlOpenButton.setText("Close") self.dataThread.send_data('CMDC\1') ''' def ctrl_close(self): print('stop send') self.dataThread.send_data('CMDC\0') ''' def ctrl_sendone(self): print('send a frame') self.dataThread.send_data('CMDC\2') def mode_manual(self): if self.mode == 1: self.getOnePicButton.setEnabled(True) self.modeManualButton.setText("Manual") self.dataThread.send_data('CMDM\0') self.mode = 0 print('mode: manual') else: self.getOnePicButton.setEnabled(False) self.modeManualButton.setText("Auto") self.dataThread.send_data('CMDM\1') print('mode: auto') self.mode = 1 def mode_auto(self): print('mode: auto') self.dataThread.send_data('CMDM\1') def stop_calibration(self): global calibration_offset calibration_start = False self.calibrateButton.setText(calibrateStr[0]) if (calibration_frame_count): reply = QMessageBox.information(self, '信息', '校准很久都不行,模组是否没有预热20分钟呢?', QMessageBox.Yes) else: reply = QMessageBox.information(self, '信息', '校准已完成', QMessageBox.Yes) def calibrate_handle(self): global calibration_start global calibration_max_list global blackbody_temperature if calibration_start: calibration_start = False self.calibrateButton.setText(calibrateStr[0]) else: calibration_max_list.clear() blackbody_temperature = float(self.blackbodyEdit.text()) calibration_start = True print(" blackbody_temperature ", blackbody_temperature) self.calibrateButton.setText(calibrateStr[1]) def rate_0(self): global btn_index btn_index = (btn_index + 1) % 4 print('FPS:', strButton[btn_index]) self.modeFpsButton.setText(strButton[btn_index]) self.dataThread.send_data(strFpsCmd[btn_index]) #'CMDF\0') ''' def rate_1(self): print('FPS:1') self.dataThread.send_data('CMDF\1') def rate_2(self): print('FPS:2') self.dataThread.send_data('CMDF\2') def rate_3(self): print('FPS:3') self.dataThread.send_data('CMDF\3') ''' def obj_body(self): if self.body == 1: self.body = 0 print('obj: Object') self.modeObjButton.setText("Object") self.dataThread.send_data('CMDO\0') else: self.body = 1 print('obj: Human Body') self.modeObjButton.setText("Body") self.dataThread.send_data('CMDO\1') ''' def obj_common(self): print('obj: common') self.dataThread.send_data('CMDO\1') def sys_slp(self): print('sleep') self.dataThread.send_data('CMDS\1') ''' def draw(self): if len(hetaData) == 0: return font = QFont() color = QColor() font.setPointSize(self.fontSize) font.setFamily("Microsoft YaHei") font.setLetterSpacing(QFont.AbsoluteSpacing, 0) index = 0 lock.acquire() frame = hetaData.pop(0) lock.release() p = QPainter(self.cameraBuffer) p.fillRect(0, 0, self.width, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) # draw camera color = QColor() for yIndex in range(int(self.height / self.pixelSize)): for xIndex in range(int(self.width / self.pixelSize)): color.setHsvF(frame[index] / 360, 1.0, 1.0) p.fillRect(xIndex * self.pixelSize, yIndex * self.pixelSize, self.pixelSize, self.pixelSize, QBrush(color)) index = index + 1 self.cameraItem.setPixmap(self.cameraBuffer) # draw text p = QPainter(self.hetTextBuffer) p.fillRect(0, 0, self.width, self.height + self.textLineHeight, QBrush(QColor(Qt.black))) hetDiff = maxHet - minHet bastNum = round(minHet) interval = round(hetDiff / 5) for i in range(5): hue = constrain( mapValue((bastNum + (i * interval)), minHet, maxHet, minHue, maxHue), minHue, maxHue) color.setHsvF(hue / 360, 1.0, 1.0) p.setPen(color) p.setFont(font) p.drawText(i * self.textInterval, self.fontSize + 3, str(bastNum + (i * interval)) + "°") self.hetTextItem.setPixmap(self.hetTextBuffer) # draw center het text cneter = round( mapValue(frame[self.centerIndex], minHue, maxHue, minHet, maxHet), 1) centerText = "<font color=white>%s</font>" self.centerTextItem.setFont(font) self.centerTextItem.setHtml(centerText % (str(cneter) + "°")) self.frameCount = self.frameCount + 1 print("picture->" + str(self.frameCount))
def _set_line(line: QGraphicsLineItem, x1, y1, x2, y2): """Helper to set `line` ends to (x1, y1) and (x2, y2)""" """setLine should set to 0,0 first, then call setPos. Otherwise it messes the scene coordinate system.""" line.setLine(0, 0, x2 - x1, y2 - y1) line.setPos(QPointF(x1, y1))