class Curve1(Curve): def __init__(self): Curve.__init__(self) self.setPen( QColor( 150, 150, 200 ), 2 ) self.setStyle( Qwt.QwtPlotCurve.Lines ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setSplineSize( 150 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.XCross ) symbol.setPen( Qt.yellow ) symbol.setSize( 7 ) self.setSymbol( symbol ) # somewhere to the left self.transform = QTransform() self.transform.scale( 1.5, 1.0 ); self.transform.translate( 1.5, 3.0 ); self.setTransformation( self.transform ) def points(self, phase ): pnts = QPolygonF() numSamples = 15; for i in range(numSamples): v = 6.28 * i / ( numSamples - 1 ) pnts += QPointF( math.sin( v - phase ), v ) return pnts def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase )))
def updateZoom(self, zx, zy): trans = QTransform() trans.scale(1.0 / zx, 1.0 / zy) # self.setTransform( trans ) self.VP.setTransform(trans) self.preBP.setTransform(trans) self.postBP.setTransform(trans) self.updateTPPos()
def setZoom(self, x, y): self.zx = x self.zy = y trans = QTransform() trans.scale(self.zx, self.zy) self.setTransform(trans) for vert in self.vertItems: vert.updateZoom(self.zx, self.zy)
def setZoom( self, x, y ): self.zx = x self.zy = y trans = QTransform() trans.scale( self.zx, self.zy ) self.setTransform( trans ) for vert in self.vertItems: vert.updateZoom( self.zx, self.zy )
def updateZoom( self, zx, zy ): trans = QTransform() trans.scale( 1.0/zx, 1.0/zy ) # self.setTransform( trans ) self.VP.setTransform( trans ) self.preBP.setTransform( trans ) self.postBP.setTransform( trans ) self.updateTPPos()
def __init__(self): Curve.__init__(self) self.d_points = QPolygonF() self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( Qt.red, 2 ) self.initSamples() # somewhere in the center transform = QTransform() transform.translate( 7.0, 3.0 ) transform.scale( 1.5, 1.5 ) self.setTransformation( transform )
def transform(self): try: return self.__dict__['transform'] if self.scale else QTransform() except KeyError: transform = QTransform() image = self.client.image if image is not None and not image.isNull(): scale = min(self.width()/image.width(), self.height()/image.height()) transform.translate((self.width() - image.width()*scale)/2, (self.height() - image.height()*scale)/2) transform.scale(scale, scale) transform = self.__dict__.setdefault('transform', transform) return transform
def _plat_get_blocks(self, block_count_per_side, orientation): image = QImage(str(self.path)) image = image.convertToFormat(QImage.Format_RGB888) # MYSTERY TO SOLVE: For reasons I cannot explain, orientations 5 and 7 don't work for # duplicate scanning. The transforms seems to work fine (if I try to save the image after # the transform, we see that the image has been correctly flipped and rotated), but the # analysis part yields wrong blocks. I spent enought time with this feature, so I'll leave # like that for now. (by the way, orientations 5 and 7 work fine under Cocoa) if 2 <= orientation <= 8: t = QTransform() if orientation == 2: t.scale(-1, 1) elif orientation == 3: t.rotate(180) elif orientation == 4: t.scale(1, -1) elif orientation == 5: t.scale(-1, 1) t.rotate(90) elif orientation == 6: t.rotate(90) elif orientation == 7: t.scale(-1, 1) t.rotate(270) elif orientation == 8: t.rotate(270) image = image.transformed(t) return getblocks(image, block_count_per_side)
def transform(self): try: return self.__dict__['transform'] if self.scale else QTransform() except KeyError: transform = QTransform() image = self.client.image if image is not None and not image.isNull(): scale = min(self.width() / image.width(), self.height() / image.height()) transform.translate( (self.width() - image.width() * scale) / 2, (self.height() - image.height() * scale) / 2) transform.scale(scale, scale) transform = self.__dict__.setdefault('transform', transform) return transform
def setImageMove(self, scale, pos, angle): log_debug("New scale = %s" % (scale,)) self.scale = scale self.min_scale = self.data_manager.minScale() self.img_scale = (scale[0]/self.min_scale, scale[1]/self.min_scale) back_matrix = QTransform() back_matrix.scale(*self.img_scale) back_matrix.translate(pos.x(), pos.y()) back_matrix.rotate(angle) self.back_matrix = back_matrix rect = back_matrix.mapRect(QRectF(self.background_image.rect())) inv, ok = back_matrix.inverted() if not ok: raise ValueError("The movement is not invertible !?!") self.invert_back_matrix = inv self.real_scene_rect = rect
def __init__(self): Curve.__init__(self) self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( QColor( 100, 200, 150 ), 2 ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setFitMode( Qwt.QwtSplineCurveFitter.ParametricSpline ) curveFitter.setSplineSize( 200 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) # somewhere in the top right corner transform = QTransform() transform.translate( 7.0, 7.5 ) transform.scale( 2.0, 2.0 ) self.setTransformation( transform )
def inicializarUI(self): self.setWindowTitle("BlueKing::Reversa") self.setGeometry(0,0,320,240) self.setAutoFillBackground(True) #QGraphicsView/Scene self.view = QGraphicsView() self.view.setStyleSheet("border: 0px;margin: 0px;background-color: #000000;") self.scene = QGraphicsScene(0,0,320,240) self.view.setScene(self.scene) self.baseLayout = QVBoxLayout() self.baseLayout.setContentsMargins(0,0,0,0) self.baseLayout.addWidget(self.view) #Decoracion car_logo = QPixmap("imagenes/car_logo.png") car_logo_item = QGraphicsPixmapItem(car_logo) car_logo_item.setPos(5,5) self.scene.addItem(car_logo_item) self.distlabel = QLabel("-") self.distlabel.setGeometry(20, 20, 280, 200) self.distlabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.distlabel.setStyleSheet("color: #00FFFF;font-size: 150px;background-color: transparent;") self.scene.addWidget(self.distlabel) self.measureLabel=QLabel("metros") self.measureLabel.setGeometry(10,190,300,30) self.measureLabel.setAlignment(QtCore.Qt.AlignRight |QtCore.Qt.AlignVCenter) self.measureLabel.setStyleSheet("color: #FFFF00;font-size: 30px; font-weight: bold; font-style: italic;background-color: transparent;") self.scene.addWidget(self.measureLabel) self.setLayout(self.baseLayout) transformacion = QTransform() transformacion.scale(1.0,-1.0) #self.view.setTransform(transformacion) self.show()
def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), QColor('#101010')) image = self._image if image is not None: if self.height() < 240: fast_scaler = QTransform() scale = 297 / image.height() if self.mirror: fast_scaler.scale(-scale, scale) else: fast_scaler.scale(scale, scale) rect = event.rect() painter.drawPixmap( rect, QPixmap.fromImage( image.transformed(fast_scaler)).scaledToHeight( self.height(), Qt.SmoothTransformation), rect) else: transform = QTransform() scale = min(self.width() / image.width(), self.height() / image.height()) if self.mirror: transform.translate( (self.width() + image.width() * scale) / 2, (self.height() - image.height() * scale) / 2) transform.scale(-scale, scale) else: transform.translate( (self.width() - image.width() * scale) / 2, (self.height() - image.height() * scale) / 2) transform.scale(scale, scale) inverse_transform, invertible = transform.inverted() rect = inverse_transform.mapRect(event.rect()).adjusted( -1, -1, 1, 1).intersected(image.rect()) painter.setTransform(transform) if self.height() > 400: painter.drawPixmap(rect, QPixmap.fromImage(image), rect) else: painter.drawImage(rect, image, rect) painter.end()
def paintEvent(self, event): painter = QPainter(self) painter.fillRect(self.rect(), QColor('#101010')) image = self._image if image is not None: if self.height() < 240: fast_scaler = QTransform() scale = 297/image.height() if self.mirror: fast_scaler.scale(-scale, scale) else: fast_scaler.scale(scale, scale) rect = event.rect() painter.drawPixmap(rect, QPixmap.fromImage(image.transformed(fast_scaler)).scaledToHeight(self.height(), Qt.SmoothTransformation), rect) else: transform = QTransform() scale = min(self.width()/image.width(), self.height()/image.height()) if self.mirror: transform.translate((self.width() + image.width()*scale)/2, (self.height() - image.height()*scale)/2) transform.scale(-scale, scale) else: transform.translate((self.width() - image.width()*scale)/2, (self.height() - image.height()*scale)/2) transform.scale(scale, scale) inverse_transform, invertible = transform.inverted() rect = inverse_transform.mapRect(event.rect()).adjusted(-1, -1, 1, 1).intersected(image.rect()) painter.setTransform(transform) if self.height() > 400: painter.drawPixmap(rect, QPixmap.fromImage(image), rect) else: painter.drawImage(rect, image, rect) painter.end()
def paintEvent(self, event): painter = QPainter(self) width = self.width() height = self.height() if DEBUG: painter.fillRect(0, 0, width, height, Qt.blue) else: painter.fillRect(event.rect(), self.plot.canvas_color) y_min_scale = self.plot.y_scale.value_min y_max_scale = self.plot.y_scale.value_max factor_x = float(width) / self.plot.x_diff factor_y = float(height - 1) / max( y_max_scale - y_min_scale, EPSILON) # -1 to accommodate the 1px width of the curve if self.plot.x_min != None and self.plot.x_max != None: x_min = self.plot.x_min x_max = self.plot.x_max if self.plot.curve_start == 'left': curve_x_offset = 0 else: curve_x_offset = round( (self.plot.x_diff - (x_max - x_min)) * factor_x) transform = QTransform() transform.translate( curve_x_offset, height - 1 + self.plot.curve_y_offset ) # -1 to accommodate the 1px width of the curve transform.scale(factor_x, -factor_y) transform.translate(-x_min, -y_min_scale) if self.plot.curve_motion_granularity > 1: self.plot.partial_update_width = math.ceil( transform.map(QLineF(0, 0, 1.5, 0)).length()) inverted_event_rect = transform.inverted()[0].mapRect( QRectF(event.rect())) painter.save() painter.setTransform(transform) if False and self.plot.curves_visible[0]: # Currently unused support for bar graphs. # If we need this later on we should add an option to the # PlotWidget for it. # I tested this for the Sound Pressure Level Bricklet and it works, # but it didnt't look good. curve_x = self.plot.curves_x[0] curve_y = self.plot.curves_y[0] t = time.time() if self.max_points == None: self.max_points = [] for y in curve_y: self.max_points.append((t, y)) else: for i in range(len(curve_y)): if (curve_y[i] > self.max_points[i][1]) or ( (t - self.max_points[i][0]) > 5): self.max_points[i] = (t, curve_y[i]) for i in range(len(self.plot.curves_x[0])): painter.setPen(self.plot.curve_configs[0].color) painter.drawLine(QPoint(curve_x[i], 0), QPoint(curve_x[i], curve_y[i])) painter.setPen(Qt.white) painter.drawLine(QPoint(curve_x[i], curve_y[i]), QPoint(curve_x[i], y_max_scale)) painter.setPen(Qt.darkGreen) painter.drawPoint(QPoint(curve_x[i], self.max_points[i][1])) else: for c in range(len(self.plot.curves_x)): if not self.plot.curves_visible[c]: continue curve_x = self.plot.curves_x[c] curve_y = self.plot.curves_y[c] path = QPainterPath() lineTo = path.lineTo if self.plot.curve_motion_granularity > 1: start = max( min( bisect.bisect_left(curve_x, inverted_event_rect.left()), len(curve_x) - 1) - 1, 0) else: start = 0 path.moveTo(curve_x[start], curve_y[start]) for i in xrange(start + 1, len(curve_x)): lineTo(curve_x[i], curve_y[i]) painter.setPen(self.plot.curve_configs[c].color) painter.drawPath(path) painter.restore()
def get_letter(clt, char): if not clt in CLT_STYLES: clt = 0 font = CLT_STYLES[clt].font hscale = CLT_STYLES[clt].scale / 100.0 vscale = CLT_STYLES[clt].scale / 100.0 try: info = FONT_DATA[font][char] except: # This is the character the game replaces unknown characters with. info = FONT_DATA[font][u'\u2261'] expand_l = 0 expand_r = 0 expand_t = 0 expand_b = 0 box = QRect(info['x'] - expand_l, info['y'] - expand_t, info['w'] + expand_l + expand_r, info['h'] + expand_t + expand_b) #box = QRect(info['x'] - expand_l, info['y'] - expand_t, info['w'], info['h']) expand_l += CLT_STYLES[clt].border_size expand_r += CLT_STYLES[clt].border_size expand_t += CLT_STYLES[clt].border_size expand_b += CLT_STYLES[clt].border_size xshift = -expand_l yshift = +expand_t if font == 1: yshift += 0 elif font == 2: yshift -= 2 final_w = info['w'] final_h = info['h'] if hscale != 1.0: final_w = (final_w * hscale) if vscale != 1.0: old_h = final_h final_h = (final_h * vscale) yshift = yshift + ((old_h - final_h) / 2.0) final_w += expand_l + expand_r final_h += expand_t + expand_b letter = FONTS[CLT_STYLES[clt].font].copy(box) if hscale != 1.0 or vscale != 1.0: matrix = QTransform() matrix.scale(hscale, vscale) letter = letter.transformed(matrix, Qt.Qt.SmoothTransformation) top_color = CLT_STYLES[clt].top_color bottom_color = CLT_STYLES[clt].bottom_color if top_color and not bottom_color: letter = replace_all_colors(letter, top_color) elif top_color and bottom_color: letter = add_v_gradient(letter, [top_color, bottom_color]) border_size = CLT_STYLES[clt].border_size border_color = CLT_STYLES[clt].border_color if border_size: letter = add_border(letter, border_color, border_size) return letter, (xshift, yshift, final_w, final_h)
def inicializarUI(self): self.setWindowTitle("BlueKing HUD") self.setGeometry(0,0,320,240) self.setAutoFillBackground(True) self.view = QGraphicsView() self.view.setStyleSheet("border: 0px;margin: 0px;background-color: #000000;") self.scene = QGraphicsScene(0,0,320,240) self.view.setScene(self.scene) self.baseLayout = QVBoxLayout() self.baseLayout.setContentsMargins(0,0,0,0) self.baseLayout.addWidget(self.view) # Decoracion car_logo = QPixmap("imagenes/car_logo.png").scaled(32,32, QtCore.Qt.KeepAspectRatio) car_logo_item = QGraphicsPixmapItem(car_logo) car_logo_item.setPos(5,5) self.scene.addItem(car_logo_item) # Etiqueta km/h kmLabel = QLabel("Km/h") kmLabel.setGeometry(250,120, 70, 25) kmLabel.setStyleSheet("font-size: 25px; color: #C8FF00; background: transparent;text-decoration: italic") self.scene.addWidget(kmLabel) # Etiqueta RPM rpmSigLabel = QLabel("R.P.M.") rpmSigLabel.setGeometry(250, 152, 70, 25) rpmSigLabel.setStyleSheet("font-size: 25px; color: #C8FF00; background: transparent;text-decoration: italic") self.scene.addWidget(rpmSigLabel) # Icono Temperatura thermometro = QPixmap("imagenes/termometro_rojo.png").scaled(25,25, QtCore.Qt.KeepAspectRatio) thermometro_item = QGraphicsPixmapItem(thermometro) thermometro_item.setPos(290, 210) self.scene.addItem(thermometro_item) # Indicadores # Velocidad self.gaugeWidget = BKGauge() self.gaugeWidget.setGeometry(70,50,180,180) self.gaugeWidget.colorDial="#00FF00" self.gaugeWidget.maxValor=250 self.scene.addWidget(self.gaugeWidget) self.velocidadLabel = QLabel("250") self.velocidadLabel.setGeometry(115,90,130,60) self.velocidadLabel.setAlignment(QtCore.Qt.AlignRight |QtCore.Qt.AlignVCenter) self.velocidadLabel.setStyleSheet("font-family: Blutter;font-size: 60px;color: #00FFFF; background: transparent; font-weight: bold; text-align: right;") self.scene.addWidget(self.velocidadLabel) # RPM self.rpmGaugeWidget = BKGauge() self.rpmGaugeWidget.setGeometry(60, 40, 200, 200) self.rpmGaugeWidget.maxValor=25000 self.rpmGaugeWidget.anchoLinea = 20 self.rpmGaugeWidget.colorDial = "#FF0000" self.scene.addWidget(self.rpmGaugeWidget) self.rpmLabel = QLabel("2658") self.rpmLabel.setGeometry(160, 150, 85, 30) self.rpmLabel.setAlignment(QtCore.Qt.AlignRight |QtCore.Qt.AlignVCenter) self.rpmLabel.setStyleSheet("font-family: Blutter;font-size: 30px;color: #FF0009; background-color: transparent;") self.scene.addWidget(self.rpmLabel) # Temperatura Motor self.engTempLabel = QLabel("180") self.engTempLabel.setGeometry(240, 210, 50, 25) self.engTempLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.engTempLabel.setStyleSheet("font-family: Blutter; font-size: 20px; color: #00FF00;background-color: transparent;") self.scene.addWidget(self.engTempLabel) self.setLayout(self.baseLayout) transformacion = QTransform() transformacion.scale(1.0,-1.0) self.view.setTransform(transformacion) self.show()
start = time.time() path_items = generate_path_items_for_labels(pen_table, labels_img, None) print "generate took {}".format(time.time() - start) # 52 ms edges_item = SegmentationEdgesItem(path_items, pen_table) def assign_random_color(id_pair, buttons): print "handling click: {}".format(id_pair) pen = pen_table[id_pair] if pen: pen = QPen(pen) else: pen = QPen() random_color = QColor(*list(np.random.randint(0, 255, (3, )))) pen.setColor(random_color) pen_table[id_pair] = pen edges_item.edgeClicked.connect(assign_random_color) scene = QGraphicsScene() scene.addItem(edges_item) transform = QTransform() transform.scale(5.0, 5.0) view = QGraphicsView(scene) view.setTransform(transform) view.show() view.raise_() app.exec_()
start = time.time() path_items = generate_path_items_for_labels(pen_table, labels_img, None) print "generate took {}".format(time.time() - start) # 52 ms edges_item = SegmentationEdgesItem(path_items, pen_table) def assign_random_color( id_pair): print "handling click: {}".format(id_pair) pen = pen_table[id_pair] if pen: pen = QPen(pen) else: pen = QPen() random_color = QColor( *list( np.random.randint(0,255,(3,)) ) ) pen.setColor(random_color) pen_table[id_pair] = pen edges_item.edgeClicked.connect(assign_random_color) scene = QGraphicsScene() scene.addItem(edges_item) transform = QTransform() transform.scale(5.0, 5.0) view = QGraphicsView(scene) view.setTransform(transform) view.show() view.raise_() app.exec_()
def setZoom(self, scale): """Scale to selected factor """ transform = QTransform() transform.scale(scale, scale) self.graphicsView.setTransform(transform)
def run_loader(self): filename = self.result try: self.retryObject = None # First, prepare the data by getting the images and computing how big they # should be f = open(filename) first_line = f.readline() f.close() if first_line.startswith("TRKR_VERSION"): result = Result(None) result.load(self.result, **self._loading_arguments) result_type = "Growth" else: result = TrackingData() result.load(self.result, **self._loading_arguments) result_type = "Data" self.result = result self.result_type = result_type if result_type == "Data": data = result images = data.images_name if data.cells: self.has_cells = True self.has_walls = True else: self.has_cells = False self.has_walls = False self.has_points = bool(data.cell_points) else: data = result.data images = result.images self.has_cells = False self.has_walls = False self.has_points = False self.images = images cache = image_cache.cache self.update_nb_images(len(result)) bbox = QRectF() ms = data.minScale() for i in range(len(result)): img_name = images[i] img_data = data[img_name] img = cache.image(data.image_path(img_name)) matrix = QTransform() matrix = img_data.matrix() sc = QTransform() sc.scale(1.0 / ms, 1.0 / ms) matrix *= sc r = QRectF(img.rect()) rbox = matrix.map(QPolygonF(r)).boundingRect() bbox |= rbox log_debug( "Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n" % (img_name, r.width(), r.height(), rbox.width(), rbox.height(), rbox.left(), rbox.top(), bbox.width(), bbox.height(), bbox.left(), bbox.top())) log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" % (matrix.m11(), matrix.m12(), matrix.dx(), matrix.m21(), matrix.m22(), matrix.dy())) if result_type == "Growth": if result.cells[i]: self.has_cells = True if result.walls[i]: self.has_walls = True self.has_points = bool(result.data.cell_points) self.nextImage() translate = bbox.topLeft() translate *= -1 self.translate = translate size = bbox.size().toSize() self.img_size = size self._crop = QRect(QPoint(0, 0), size) self.finished() self._loading_arguments = { } # All done, we don't need that anymore except RetryTrackingDataException as ex: ex.filename = filename self.retryObject = ex self.finished() return except Exception as ex: _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise
def run_loader(self): filename = self.result try: self.retryObject = None # First, prepare the data by getting the images and computing how big they # should be f = open(filename) first_line = f.readline() f.close() if first_line.startswith("TRKR_VERSION"): result = Result(None) result.load(self.result, **self._loading_arguments) result_type = "Growth" else: result = TrackingData() result.load(self.result, **self._loading_arguments) result_type = "Data" self.result = result self.result_type = result_type if result_type == "Data": data = result images = data.images_name if data.cells: self.has_cells = True self.has_walls = True else: self.has_cells = False self.has_walls = False self.has_points = bool(data.cell_points) else: data = result.data images = result.images self.has_cells = False self.has_walls = False self.has_points = False self.images = images cache = image_cache.cache self.update_nb_images(len(result)) bbox = QRectF() ms = data.minScale() for i in range(len(result)): img_name = images[i] img_data = data[img_name] img = cache.image(data.image_path(img_name)) matrix = QTransform() matrix = img_data.matrix() sc = QTransform() sc.scale(1.0/ms, 1.0/ms) matrix *= sc r = QRectF(img.rect()) rbox = matrix.map(QPolygonF(r)).boundingRect() bbox |= rbox log_debug("Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n" % (img_name, r.width(), r.height(), rbox.width(), rbox.height(), rbox.left(), rbox.top(), bbox.width(), bbox.height(), bbox.left(), bbox.top())) log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" % (matrix.m11(), matrix.m12(), matrix.dx(), matrix.m21(), matrix.m22(), matrix.dy())) if result_type == "Growth": if result.cells[i]: self.has_cells = True if result.walls[i]: self.has_walls = True self.has_points = bool(result.data.cell_points) self.nextImage() translate = bbox.topLeft() translate *= -1 self.translate = translate size = bbox.size().toSize() self.img_size = size self._crop = QRect(QPoint(0,0), size) self.finished() self._loading_arguments = {} # All done, we don't need that anymore except RetryTrackingDataException as ex: ex.filename = filename self.retryObject = ex self.finished() return except Exception as ex: _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise
def paintEvent(self, event): painter = QPainter(self) width = self.width() height = self.height() if DEBUG: painter.fillRect(0, 0, width, height, Qt.blue) else: painter.fillRect(event.rect(), self.plot.canvas_color) y_min_scale = self.plot.y_scale.value_min y_max_scale = self.plot.y_scale.value_max factor_x = float(width) / self.plot.history_length_x factor_y = float(height - 1) / max( y_max_scale - y_min_scale, EPSILON ) # -1 to accommodate the 1px width of the curve if self.plot.x_min != None and self.plot.x_max != None: x_min = self.plot.x_min x_max = self.plot.x_max if self.plot.curve_start == "left": curve_x_offset = 0 else: curve_x_offset = round((self.plot.history_length_x - (x_max - x_min)) * factor_x) transform = QTransform() transform.translate( curve_x_offset, height - 1 + self.plot.curve_y_offset ) # -1 to accommodate the 1px width of the curve transform.scale(factor_x, -factor_y) transform.translate(-x_min, -y_min_scale) if self.plot.curve_motion_granularity > 1: self.plot.partial_update_width = math.ceil(transform.map(QLineF(0, 0, 1.5, 0)).length()) inverted_event_rect = transform.inverted()[0].mapRect(QRectF(event.rect())) painter.save() painter.setTransform(transform) for c in range(len(self.plot.curves_x)): if not self.plot.curves_visible[c]: continue curve_x = self.plot.curves_x[c] curve_y = self.plot.curves_y[c] path = QPainterPath() lineTo = path.lineTo if self.plot.curve_motion_granularity > 1: start = max(min(bisect.bisect_left(curve_x, inverted_event_rect.left()), len(curve_x) - 1) - 1, 0) else: start = 0 path.moveTo(curve_x[start], curve_y[start]) for i in xrange(start + 1, len(curve_x)): lineTo(curve_x[i], curve_y[i]) painter.setPen(self.plot.configs[c][1]) painter.drawPath(path) painter.restore()