def add_clearance_graph(self): print("-----------------------------------------") horizontal_clearance = self.clearance_analysis.horizontal_clearance x_init = self.graph_zero[0] + self.line_extend y_init = self.graph_zero[1] for i in range(len(horizontal_clearance)): clearance_points = horizontal_clearance[i] x = x_init + i * self.dimension_analysis.section_distance * self.length_multiplier left = -self.dimension_analysis.domain_length right = self.dimension_analysis.domain_length if clearance_points[0]: left = clearance_points[0] if clearance_points[1]: right = clearance_points[1] clearance = right - left y_top = y_init + left * self.height_multiplier y_bottom = y_init + right * self.height_multiplier pen_red = QPen() red = Color.create_qcolor_from_rgb_tuple(Color.red) pen_red.setColor(red) pen_green = QPen() green = Color.create_qcolor_from_rgb_tuple(Color.green) pen_green.setColor(green) line = QGraphicsLineItem(x, y_top, x, y_bottom) if clearance < self.min_horizontal_clearance: line.setPen(pen_red) else: line.setPen(pen_green) self.addToGroup(line) pass
def paintEvent(self, event): _size = self.size() - QSize(2, 2) if (_size.isEmpty()): return origX = (_size.width() - self.mNewSize.width() * self.mScale) / 2 + 0.5 origY = (_size.height() - self.mNewSize.height() * self.mScale) / 2 + 0.5 oldRect = QRect(self.mOffset, self.mOldSize) painter = QPainter(self) painter.translate(origX, origY) painter.scale(self.mScale, self.mScale) pen = QPen(Qt.black) pen.setCosmetic(True) painter.setPen(pen) painter.drawRect(QRect(QPoint(0, 0), self.mNewSize)) pen.setColor(Qt.white) painter.setPen(pen) painter.setBrush(Qt.white) painter.setOpacity(0.5) painter.drawRect(oldRect) pen.setColor(Qt.black) pen.setStyle(Qt.DashLine) painter.setOpacity(1.0) painter.setBrush(Qt.NoBrush) painter.setPen(pen) painter.drawRect(oldRect) painter.end()
def _drawState(self, qp, xpos, width, data, hovering=False): # Set pen and brush style if hovering: color = SignalLogWidget.SIGNAL_COLOR_HOVER else: color = SignalLogWidget.SIGNAL_COLOR pen = QPen(color) pen.setWidth(2) brush = QBrush(color) qp.setPen(pen) qp.setBrush(brush) size = self.size() h = size.height() # Draw datastripe when data contains tokens if data == []: qp.drawLine(xpos, h / 2, xpos + width, h / 2) else: qp.setPen(Qt.NoPen) qp.drawRect(xpos, 2, width, h - 4) pen.setColor(SignalLogWidget.TEXT_COLOR) qp.setPen(pen) rect = QRect(xpos + 3, 3, width - 3, h - 6) qp.drawText(rect, Qt.AlignCenter, str(data)[1:-1])
def drawForeground(self, painter, rect): if self._tiling is None: return if self._showTileOutlines: tile_nos = self._tiling.intersected(rect) for tileId in tile_nos: ## draw tile outlines # Dashed black line pen = QPen() pen.setWidth(0) pen.setDashPattern([5, 5]) painter.setPen(pen) painter.drawRect(self._tiling.imageRects[tileId]) # Dashed white line # (offset to occupy the spaces in the dashed black line) pen = QPen() pen.setWidth(0) pen.setDashPattern([5, 5]) pen.setDashOffset(5) pen.setColor(QColor(Qt.white)) painter.setPen(pen) painter.drawRect(self._tiling.imageRects[tileId])
def create_multicut_disagreement_layer(self): ActionInfo = ShortcutManager.ActionInfo op = self.__topLevelOperatorView if not op.Output.ready(): return None # Final segmentation -- Edges default_pen = QPen(SegmentationEdgesLayer.DEFAULT_PEN) default_pen.setColor(Qt.transparent) layer = SegmentationEdgesLayer( LazyflowSource(op.Superpixels), default_pen ) layer.name = "Multicut Disagreements" layer.visible = False # Off by default... layer.opacity = 1.0 self.disagreement_layer = layer self.__update_disagreement_edges() # Initialize layer.shortcutRegistration = ( "d", ActionInfo( "Multicut", "MulticutDisagrementVisibility", "Show/Hide Multicut Disagreement Edges", layer.toggleVisible, self.viewerControlWidget(), layer ) ) return layer
def paint(self, painter, option, widget=None): with painter_context(painter): pen = QPen(painter.pen()) pen.setWidth(10.0) pen.setColor(QColor(255, 0, 0)) painter.setPen(pen) shrunken_rectf = self.rectf.adjusted(10, 10, -10, -10) painter.drawRoundedRect(shrunken_rectf, 50, 50, Qt.RelativeSize)
def penForID(self, penId): pen = QPen() if penId == PenID.Axis: pen.setColor(Qt.darkGray) pen.setWidthF(self.LINE_WIDTH) elif penId == PenID.AxisOverlay: pen.setColor(Qt.darkGray) pen.setWidthF(self.OVERLAY_AXIS_WIDTH) return pen
def penForID(self, penId): if penId == PenID.Graph: return self.linePen elif penId == PenID.TodayLine: pen = QPen(self.linePen) pen.setColor(Qt.red) return pen else: return GraphView.penForID(self, penId)
def paintEvent(self, event): QWidget.paintEvent(self, event) width, height = self.width(), self.height() polygon = QPolygon() for i, rate in enumerate(self.loads): x = width - i * self.pointDistance y = height - rate * height if x < self.boxWidth: break polygon.append(QPoint(x, y)) painter = QPainter(self) pen = QPen() pen.setColor(Qt.darkGreen) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing, True) #画网格 painter.setOpacity(0.5) gridSize = self.pointDistance * 4 deltaX = (width - self.boxWidth) % gridSize + self.boxWidth deltaY = height % gridSize for i in range(int(width / gridSize)): x = deltaX + gridSize * i painter.drawLine(x, 0, x, height) for j in range(int(height / gridSize)): y = j * gridSize + deltaY painter.drawLine(self.boxWidth, y, width, y) #画折线 pen.setColor(Qt.darkCyan) pen.setWidth(2) painter.setPen(pen) painter.setOpacity(1) painter.drawPolyline(polygon) #画展示框 if len(self.loads) > 0: rate = self.loads[0] else: rate = 1.0 rect1 = QRect(4, height * 0.05, self.boxWidth - 9, height * 0.7) rect2 = QRect(4, height * 0.8, self.boxWidth - 9, height * 0.2) centerX = int(rect1.width() / 2) + 1 pen.setWidth(1) for i in range(rect1.height()): if i % 4 == 0: continue if (rect1.height() - i) / rect1.height() > rate: pen.setColor(Qt.darkGreen) else: pen.setColor(Qt.green) painter.setPen(pen) for j in range(rect1.width()): if centerX - 1 <= j <= centerX + 1: continue painter.drawPoint(rect1.x() + j, rect1.y() + i) pen.setColor(Qt.black) painter.setPen(pen) painter.drawText(rect2, Qt.AlignHCenter | Qt.AlignVCenter, str(int(rate * 100)) + "%")
def drawWidget(self, qp): color = self.palette().color(QPalette.Background) qp.setBrush(QColor(100,0,0)) pen=QPen() pen.setWidth(self.width()/10) pen.setColor(QColor(0,0,255)) pen.setCapStyle(Qt.RoundCap) w=self.width()/2 x_shift=w+w*0.05 y_shift=w+w*0.05 r=0.35*w r1=w*0.8 qp.setPen(pen) my_max=100 p=[] c=[] for phi in range(0,360,30): p.append(phi) c.append(0) f=0 for i in range(0,len(p)): if p[i]>self.delta: f=i break i=f m=1.0 while(i>=0): c[i]=m m=m*0.7 i=i-1 i=len(c)-1 while(i>f): c[i]=m m=m*0.7 i=i-1 for i in range(0,len(p)): self.pos=p[i] x = r * cos( (2*pi)*self.pos/360 ) y = r * sin( (2*pi)*self.pos/360 ) x1 = r1 * cos( (2*pi)*self.pos/360 ) y1 = r1 * sin( (2*pi)*self.pos/360 ) cb=self.blue_target*c[i]+color.blue()*(1.0-c[i]) cg=self.green_target*c[i]+color.green()*(1.0-c[i]) cr=self.red_target*c[i]+color.red()*(1.0-c[i]) pen.setColor(QColor(cr,cg,cb)) qp.setPen(pen) qp.drawLine(x+x_shift,y+y_shift,x1+x_shift,y1+y_shift)
def valueChanged(self, property, value): if (not self.propertyToId.contains(property)): return if (not self.currentItem or self.currentItem.isNone()): return tp = type(value) id = self.propertyToId[property] if tp == float: if (id == "xpos"): self.currentItem.setX(value) elif (id == "ypos"): self.currentItem.setY(value) elif (id == "zpos"): self.currentItem.setZ(value) elif tp == str: if (id == "text"): if (self.currentItem.rtti() == RttiValues.Rtti_Text): i = self.currentItem i.setText(value) elif tp == QColor: if (id == "color"): if (self.currentItem.rtti() == RttiValues.Rtti_Text): i = self.currentItem i.setColor(value) elif (id == "brush"): if (self.currentItem.rtti() == RttiValues.Rtti_Rectangle or self.currentItem.rtti() == RttiValues.Rtti_Ellipse): i = self.currentItem b = QBrush(i.brush()) b.setColor(value) i.setBrush(b) elif (id == "pen"): if (self.currentItem.rtti() == RttiValues.Rtti_Rectangle or self.currentItem.rtti() == RttiValues.Rtti_Line): i = self.currentItem p = QPen(i.pen()) p.setColor(value) i.setPen(p) elif tp == QFont: if (id == "font"): if (self.currentItem.rtti() == RttiValues.Rtti_Text): i = self.currentItem i.setFont(value) elif tp == QPoint: if (self.currentItem.rtti() == RttiValues.Rtti_Line): i = self.currentItem if (id == "endpoint"): i.setPoints(i.startPoint().x(), i.startPoint().y(), value.x(), value.y()) elif tp == QSize: if (id == "size"): if (self.currentItem.rtti() == RttiValues.Rtti_Rectangle): i = self.currentItem i.setSize(value.width(), value.height()) elif (self.currentItem.rtti() == RttiValues.Rtti_Ellipse): i = self.currentItem i.setSize(value.width(), value.height()) self.canvas.update()
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
def _drawFill(self, painter, backcolor): """ draw background for fill type button """ if self._gradient: pen = QPen(backcolor) for y in range( self._rect().height() ): pen.setColor( backcolor.lighter(100 + (y*2)) ) painter.setPen( pen ) painter.drawLine( 0, y, self._rect().width(), y ) else: painter.fillRect(self._rect(), backcolor )
def paintEvent(self, ev): pen = QPen() pen.setStyle(Qt.DotLine) pen.setWidth(2) pen.setColor(QColor(Qt.white)) brush = QBrush() brush.setStyle(Qt.SolidPattern) brush.setColor(QColor(0, 0, 0)) painter = QPainter(self) painter.setPen(pen) painter.setBrush(brush) painter.drawRect(ev.rect())
def _dialog_paintEvent(self, d, event): QDialog.paintEvent(d, event) pen = QPen() pen.setWidth(2) pen.setColor(QColor(200, 200, 200)) rect = d.rect() rect = rect.adjusted(0, 0, -1, -1) painter = QPainter(d) painter.setRenderHint(QPainter.Antialiasing, True) painter.setPen(pen) painter.setOpacity(0.8) painter.setBrush(QBrush(QColor(Qt.white))) painter.drawRoundedRect(rect, 15, 15)
def __init__(self, itemId, bodyspecName, margin): super(BodyItem, self).__init__(0, 0, 0, 0); self.deleted = False; self.itemId = itemId; self.bodyspecName = bodyspecName; self.margin = 0; pen = QPen(Qt.SolidLine); pen.setColor(QColor(230, 230, 230)) pen.setWidth(0); self.setPen(pen); self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable); self.pixmap = None; self.img = None;
def create_distance_pointer(self): self.distance_pointer = QGraphicsLineItem() pen = QPen() pen.setWidthF(1.0) pen.setStyle(Qt.DashDotLine) color = Color.create_qcolor_from_rgb_tuple_f((1,0,0)) pen.setColor(color) self.distance_pointer.setPen(pen) self.distance_pointer.setZValue(1.0) self.addToGroup(self.distance_pointer) self.distance_label = QGraphicsSimpleTextItem() self.distance_label.setZValue(1.0) self.addToGroup(self.distance_label)
def updateImage(self): if self.fid is not None: self.readCurrentFrame() else: self._normalizeImage() self.mainImage._canvas.setCursor(Qt.CrossCursor) if self.h5path in self.eggs: if self.frame_number in self.eggs[self.h5path]: current_list = self.eggs[self.h5path][self.frame_number] painter = QPainter() painter.begin(self.frame_qimg) pen = QPen() pen.setWidth(2) pen.setColor(Qt.red) painter.setPen(pen) painter.setBrush(Qt.red) for (x,y) in current_list: #painter.drawEllipse(x,y, 1,1) painter.drawPoint(x,y) painter.end() #set number of eggs eggs n_eggs_txt = "{} Eggs".format(len(self.eggs[self.h5path][self.frame_number])) self.ui.number_of_eggs.setText(n_eggs_txt) else: self.ui.number_of_eggs.setText("0 Eggs") prev_frame = self.frame_number-1 if self.ui.show_prev.isChecked() and prev_frame in self.eggs[self.h5path]: prev_list = self.eggs[self.h5path][prev_frame] painter = QPainter() painter.begin(self.frame_qimg) pen = QPen() pen.setWidth(1) pen.setColor(Qt.blue) painter.setPen(pen) for (x,y) in prev_list: painter.drawEllipse(x-3,y-3, 5,5) #painter.drawPoint(x,y) painter.end() self.mainImage.setPixmap(self.frame_qimg)
def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image.scaledToWidth(self.width*self.image_pixel_width, Qt.SmoothTransformation)) if self.agc_roi_from != None and self.agc_roi_to != None and not self.image_is_16bit: pen = QPen() pen.setColor(Qt.green) pen.setWidth(1) painter.setPen(pen) roi = self.parent.get_agc_roi() painter.drawRect(roi[0] * self.image_pixel_width + 1, roi[1] * self.image_pixel_width + 1, (roi[2] - roi[0]) * self.image_pixel_width + 1, (roi[3] - roi[1]) * self.image_pixel_width + 1) self.parent.update_agc_roi_label() if self.spotmeter_roi_from != None and self.spotmeter_roi_to != None: pen = QPen() pen.setColor(Qt.white) pen.setWidth(1) painter.setPen(pen) from_x, from_y, to_x, to_y = self.parent.get_spotmeter_roi() from_x = from_x * self.image_pixel_width + 1 from_y = from_y * self.image_pixel_width + 1 to_x = to_x * self.image_pixel_width + 1 to_y = to_y * self.image_pixel_width + 1 cross_x = from_x + (to_x-from_x) / 2.0 cross_y = from_y + (to_y-from_y) / 2.0 if to_x-from_x > 5 or to_y - from_y > 5: lines = [QLineF(from_x, from_y, from_x + self.crosshair_width, from_y), QLineF(from_x, from_y, from_x, from_y + self.crosshair_width), QLineF(to_x, to_y, to_x, to_y - self.crosshair_width), QLineF(to_x, to_y, to_x - self.crosshair_width, to_y), QLineF(from_x, to_y, from_x, to_y-self.crosshair_width), QLineF(from_x, to_y, from_x + self.crosshair_width, to_y), QLineF(to_x, from_y, to_x, from_y+self.crosshair_width), QLineF(to_x, from_y, to_x - self.crosshair_width, from_y)] painter.drawLines(lines) lines = [QLineF(cross_x - self.crosshair_width, cross_y, cross_x + self.crosshair_width, cross_y), QLineF(cross_x, cross_y - self.crosshair_width, cross_x, cross_y+self.crosshair_width)] painter.drawLines(lines) self.parent.update_spotmeter_roi_label()
def __init__(self, id_pair, painter_path, initial_pen=None): super(SingleEdgeItem, self).__init__() self.parent = None # Should be initialized with set_parent() self.id_pair = id_pair if not initial_pen: initial_pen = QPen() initial_pen.setCosmetic(True) initial_pen.setCapStyle(Qt.RoundCap) initial_pen.setColor(Qt.white) initial_pen.setWidth(3) self.setPen(initial_pen) self.setPath(painter_path)
def __set_penAlpha(self, alpha): """Summary Args: alpha (TYPE): Description Returns: TYPE: Description """ pen = QPen(self.item.pen()) color = QColor(self.item.pen().color()) color.setAlpha(alpha) pen.setColor(color) self.item.setPen(pen)
def _init_probability_colortable(self): self.probability_colortable = [] for v in np.linspace(0.0, 1.0, num=101): self.probability_colortable.append( QColor(255*(v), 255*(1.0-v), 0) ) self.probability_pen_table = [] for color in self.probability_colortable: pen = QPen(SegmentationEdgesLayer.DEFAULT_PEN) pen.setColor(color) self.probability_pen_table.append(pen) # When the edge probabilities are dirty, update the probability edge layer pens op = self.topLevelOperatorView cleanup_fn = op.EdgeProbabilitiesDict.notifyDirty( self.update_probability_edges, defer=True ) self.__cleanup_fns.append( cleanup_fn )
def __init__(self, origX, origY, perCell, n): super(GridItem, self).__init__(); length = perCell*n/2; pen = QPen(Qt.DashLine); pen.setColor(QColor(230, 230, 230)) pen.setWidth(0); x1, y1, x2, y2 = origX-length, origY-length, origX-length, origY+length for i in range(1, n): line = QGraphicsLineItem(x1, y1, x2, y2, self) line.setPen(pen) x1, y1, x2, y2 = x1+perCell, y1, x2+perCell, y2 x1, y1, x2, y2 = origX-length, origY-length, origX+length, origY-length for i in range(1, n): line = QGraphicsLineItem(x1, y1, x2, y2, self) line.setPen(pen) x1, y1, x2, y2 = x1, y1+perCell, x2, y2+perCell
def drawPixmapForPartiallyChecked(self): self.pixmapPartiallyChecked = QPixmap(self.itemWidth, self.itemHeight) self.pixmapPartiallyChecked.fill(Qt.transparent) painter = QPainter() painter.begin(self.pixmapPartiallyChecked) painter.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(2) painter.setPen(pen) painter.drawRect(QRect(5,5,self.itemWidth-10, self.itemHeight-10)) pen.setWidth(4) pen.setColor(QColor(139,137,137)) painter.setPen(pen) painter.drawLine(old_div(self.itemWidth,2)-5, old_div(self.itemHeight,2), old_div(self.itemWidth,2), self.itemHeight-9) painter.drawLine(old_div(self.itemWidth,2), self.itemHeight-9, old_div(self.itemWidth,2)+10, 2) painter.end()
def __init_disagreement_label_colortable(self): self.disagreement_colortable = [ QColor(255, 0, 255, 255), # magenta QColor(0, 255, 255, 255) ] # cyan self.disagreement_pen_table = [] for color in self.disagreement_colortable: pen = QPen(SegmentationEdgesLayer.DEFAULT_PEN) pen.setColor(color) pen.setWidth(3) self.disagreement_pen_table.append(pen) op = self.topLevelOperatorView op.EdgeLabelDisagreementDict.notifyReady( self.__update_disagreement_edges ) self.__cleanup_fns.append( partial( op.EdgeLabelDisagreementDict.unregisterReady, self.__update_disagreement_edges ) ) op.EdgeLabelDisagreementDict.notifyDirty( self.__update_disagreement_edges ) self.__cleanup_fns.append( partial( op.EdgeLabelDisagreementDict.unregisterDirty, self.__update_disagreement_edges ) )
def __init__(self, parent, child): ''' Create a new connection between a parent and a child item ''' super(Connection, self).__init__(parent) self.parent = parent self.child = child self._start_point = None self._end_point = None self._middle_points = [] pen = QPen() pen.setColor(Qt.blue) pen.setCosmetic(False) self.setPen(pen) self.parent_rect = parent.sceneBoundingRect() self.childRect = child.sceneBoundingRect() # Activate cache mode to boost rendering by calling paint less often self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
def _init_edge_label_colortable(self): self.edge_label_colortable = [ QColor( 0, 0, 0, 0), # transparent QColor( 0, 255, 0, 255), # green QColor(255, 0, 0, 255) ] # red self.edge_label_pen_table = [] for color in self.edge_label_colortable: pen = QPen(SegmentationEdgesLayer.DEFAULT_PEN) pen.setColor(color) pen.setWidth(5) self.edge_label_pen_table.append(pen) # When the edge labels are dirty, update the edge label layer pens op = self.topLevelOperatorView cleanup_fn = op.EdgeLabelsDict.notifyDirty( self.update_labeled_edges, defer=True ) self.__cleanup_fns.append( cleanup_fn )
def drawContents(self, painter): if self._to_stop: return painter.save() painter.setPen(QColor(255, 255, 255, 255)) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.Antialiasing, True) version = Application.getInstance().getVersion().split("-") buildtype = Application.getInstance().getBuildType() if buildtype: version[0] += " (%s)" % buildtype # draw version text font = QFont() # Using system-default font here font.setPixelSize(37) painter.setFont(font) painter.drawText(215, 66, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[0]) if len(version) > 1: font.setPixelSize(16) painter.setFont(font) painter.setPen(QColor(200, 200, 200, 255)) painter.drawText(247, 105, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[1]) painter.setPen(QColor(255, 255, 255, 255)) # draw the loading image pen = QPen() pen.setWidth(6 * self._scale) pen.setColor(QColor(32, 166, 219, 255)) painter.setPen(pen) painter.drawArc(60, 150, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) # draw message text if self._current_message: font = QFont() # Using system-default font here font.setPixelSize(13) pen = QPen() pen.setColor(QColor(255, 255, 255, 255)) painter.setPen(pen) painter.setFont(font) painter.drawText(100, 128, 170, 64, Qt.AlignLeft | Qt.AlignVCenter | Qt.TextWordWrap, self._current_message) painter.restore() super().drawContents(painter)
def set_style(self, style): super().set_style(style) # minute pen = QPen(self.style.foreground_color) pen.setWidth(12) pen.setCapStyle(Qt.RoundCap) self.minutes_hand.setPen(pen) # hour pen = QPen(self.style.foreground_color) pen.setWidth(16) pen.setCapStyle(Qt.RoundCap) self.hours_hand.setPen(pen) # second pen = QPen(self.style.midcolor) pen.setWidth(4) pen.setCapStyle(Qt.RoundCap) self.seconds_hand.setPen(pen) # outer circle pen = QPen(self.style.foreground_color) pen.setWidth(6) self.circle.setPen(pen) # inner circle self.hand_circle.setBrush(QBrush(self.style.background_color)) # minute lines pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(self.style.midcolor) pen.setWidth(4) bold_pen = QPen() bold_pen.setCapStyle(Qt.RoundCap) bold_pen.setColor(self.style.foreground_color) bold_pen.setWidth(6) for i, line in enumerate(self.lines): if i % 5 == 0: line.setPen(bold_pen) else: line.setPen(pen) self.layout()
def drawSkel(self, worm_img, worm_qimg, row_data, roi_corner = (0,0)): if not self.skel_file or not isinstance(self.trajectories_data, pd.DataFrame): return c_ratio_y = worm_qimg.width()/worm_img.shape[1]; c_ratio_x = worm_qimg.height()/worm_img.shape[0]; skel_id = int(row_data['skeleton_id']) qPlg = {} with tables.File(self.skel_file, 'r') as ske_file_id: for tt in ['skeleton', 'contour_side1', 'contour_side2']: dat = ske_file_id.get_node('/' + tt)[skel_id]; dat[:,0] = (dat[:,0]-roi_corner[0])*c_ratio_x dat[:,1] = (dat[:,1]-roi_corner[1])*c_ratio_y qPlg[tt] = QPolygonF() for p in dat: qPlg[tt].append(QPointF(*p)) if 'is_good_skel' in row_data and row_data['is_good_skel'] == 0: self.skel_colors = {'skeleton':(102, 0, 0 ), 'contour_side1':(102, 0, 0 ), 'contour_side2':(102, 0, 0 )} else: self.skel_colors = {'skeleton':(27, 158, 119 ), 'contour_side1':(217, 95, 2), 'contour_side2':(231, 41, 138)} pen = QPen() pen.setWidth(2) painter = QPainter() painter.begin(worm_qimg) for tt, color in self.skel_colors.items(): pen.setColor(QColor(*color)) painter.setPen(pen) painter.drawPolyline(qPlg[tt]) pen.setColor(Qt.black) painter.setBrush(Qt.white) painter.setPen(pen) radius = 3 painter.drawEllipse(qPlg['skeleton'][0], radius, radius) painter.end()
def paint(self, force=False): pos = self.mapFromGlobal(QCursor.pos()) if pos.x() > self.x() and pos.x() < self.x() + self.width() and pos.y( ) > self.y() and pos.y() < self.y() + self.height(): label = "x:{} y:{}".format(*[ round(e, 1) for e in self.convert_gui_point_to_chart_point( pos.x(), pos.y()) ]) self.curor_val_label.setText(label) if self.profile is self.last_profile and not False: return self.last_profile = list(self.profile) pixmap = QPixmap(self.size()) pixmap.fill(QColor(0, 0, 0, 0)) qp = QPainter() qp.begin(pixmap) pen = QPen() pen.setColor(QColor(50, 50, 50, 200)) pen.setWidth(1.5) qp.setPen(pen) x_slider_scale = self.x_slider.value() / 10 y_slider_scale = self.y_slider.value() / 10 self.x_slider_label.setText(str(round(x_slider_scale, 1))) self.y_slider_label.setText(str(round(y_slider_scale, 1))) if abs(self.drag_offset[0]) / x_slider_scale > self.axis_rect.width(): self.drag_offset[0] = self.axis_rect.width() * x_slider_scale * ( 1 if self.drag_offset[0] >= 0 else -1) if abs(self.drag_offset[1]) / y_slider_scale > self.axis_rect.height(): self.drag_offset[1] = self.axis_rect.height() * y_slider_scale * ( 1 if self.drag_offset[1] >= 0 else -1) self.num_x_ticks = 10 self.num_y_ticks = 10 self.x_min = 0 self.x_max = len(self.left_profile) * self.left_profile[0].dt self.x_scale = self.axis_rect.width() / (self.x_max - self.x_min) * x_slider_scale profiles = [] if self.first_box.isChecked(): profiles += self.left_profile if self.second_box.isChecked(): profiles += self.right_profile if self.main_box.isChecked(): profiles += self.profile y_vals = [] if self.accel_box.isChecked(): y_vals.append([e.acceleration for e in profiles]) if self.vel_box.isChecked(): y_vals.append([e.velocity for e in profiles]) if self.pos_box.isChecked(): y_vals.append([e.position for e in profiles]) if not y_vals: return self.y_min = min([min(e) for e in y_vals]) self.y_max = max([max(e) for e in y_vals]) self.y_scale = self.axis_rect.height() / (self.y_max - self.y_min) * y_slider_scale qp.drawLine(self.axis_rect.x(), self.axis_rect.y() + self.axis_rect.height(), self.axis_rect.x() + self.axis_rect.width(), self.axis_rect.y() + self.axis_rect.height()) # Draw x axis qp.drawText( QRect(self.axis_rect.x() + self.axis_rect.width() / 2 - 50, self.axis_rect.y() + self.axis_rect.height() + 25, 100, 15), Qt.AlignCenter, "Time (s)") qp.drawLine(*self.convert_chart_point_to_gui_point(0, 0, offset_x=False), *self.convert_chart_point_to_gui_point( self.x_max, 0, offset_x=False)) # Draw 0 line x_tick_rate = self.axis_rect.width() / self.num_x_ticks for i in range(0, self.num_x_ticks + 1): # Draw x ticks x = self.axis_rect.x() + i * x_tick_rate y = self.axis_rect.y() + self.axis_rect.height() label = str( round( i * x_tick_rate / self.x_scale - self.drag_offset[0] / self.x_scale - self.x_min, 2)) temp_pen = QPen(pen) temp_pen.setColor(QColor(50, 50, 50, 50)) qp.setPen(temp_pen) qp.drawLine(x, self.y(), x, self.y() + self.height()) qp.setPen(pen) qp.drawLine(x, y, x, y + 5) qp.drawText(QRect(x - 15, y + 10, 30, 15), Qt.AlignCenter, label) qp.drawLine(self.axis_rect.x(), self.axis_rect.y(), self.axis_rect.x(), self.axis_rect.y() + self.axis_rect.height()) # Draw y axis y_tick_rate = round(self.axis_rect.height() / self.num_y_ticks) for i in range(0, self.num_y_ticks + 1): # Draw y ticks x = self.axis_rect.x() y = self.axis_rect.y() + self.axis_rect.height() - i * y_tick_rate label = str( round((i * y_tick_rate + self.drag_offset[1]) / self.y_scale + self.y_min, 1)) temp_pen = QPen(pen) temp_pen.setColor(QColor(50, 50, 50, 50)) qp.setPen(temp_pen) qp.drawLine(self.x(), y, self.x() + self.width(), y) qp.setPen(pen) qp.drawLine(x - 5, y, x, y) qp.drawText(QRect(x - 50, y - 7, 40, 15), Qt.AlignRight, label) # Draw Data get_val = [ lambda e: e.position, lambda e: e.velocity, lambda e: e.acceleration ] pen = QPen() pen.setWidth(2) keys = ['first', 'second', 'main'] val_keys = ['pos', 'vel', 'accel'] for p in range(len(keys)): if not eval("self." + keys[p] + "_box").isChecked(): continue profile = [self.left_profile, self.right_profile, self.profile][p] pen.setColor(self.legend_info[keys[p]]['color']) for i in range(1, len(profile)): # Draw points pnt = profile[i] pnt2 = profile[i - 1] x = i * pnt.dt for j in range(len(val_keys)): if not eval("self." + val_keys[j] + "_box").isChecked(): continue pen.setStyle(self.legend_info[val_keys[j]]['style']) qp.setPen(pen) qp.drawLine( *self.convert_chart_point_to_gui_point( x, get_val[j](pnt)), *self.convert_chart_point_to_gui_point( x - pnt.dt, get_val[j](pnt2))) qp.end() self.setPixmap(pixmap)
class QrReaderVideoOverlay(QWidget): """ Overlays the QR scanner results over the video """ BG_RECT_PADDING = 10 BG_RECT_CORNER_RADIUS = 10.0 BG_RECT_OPACITY = 0.75 def __init__(self, parent: QWidget = None): super().__init__(parent) self.results = [] self.flip_x = False self.validator_results = None self.crop = None self.resolution = None self.qr_outline_pen = QPen() self.qr_outline_pen.setColor(Qt.red) self.qr_outline_pen.setWidth(3) self.qr_outline_pen.setStyle(Qt.DotLine) self.text_pen = QPen() self.text_pen.setColor(Qt.black) self.bg_rect_pen = QPen() self.bg_rect_pen.setColor(Qt.black) self.bg_rect_pen.setStyle(Qt.DotLine) self.bg_rect_fill = QColor(255, 255, 255, 255 * self.BG_RECT_OPACITY) def set_results(self, results: List[QrCodeResult], flip_x: bool, validator_results: QrReaderValidatorResult): self.results = results self.flip_x = flip_x self.validator_results = validator_results self.update() def set_crop(self, crop: QRect): self.crop = crop def set_resolution(self, resolution: QSize): self.resolution = resolution def paintEvent(self, _event: QPaintEvent): if not self.crop or not self.resolution: return painter = QPainter(self) # Keep a backup of the transform and create a new one transform = painter.worldTransform() # Set scaling transform transform = transform.scale(self.width() / self.resolution.width(), self.height() / self.resolution.height()) # Compute the transform to flip the coordinate system on the x axis transform_flip = QTransform() if self.flip_x: transform_flip = transform_flip.translate(self.resolution.width(), 0.0) transform_flip = transform_flip.scale(-1.0, 1.0) # Small helper for tuple to QPoint def toqp(point): return QPoint(point[0], point[1]) # Starting from here we care about AA painter.setRenderHint(QPainter.Antialiasing) # Draw all the QR code results for res in self.results: painter.setWorldTransform(transform_flip * transform, False) # Draw lines between all of the QR code points pen = QPen(self.qr_outline_pen) if res in self.validator_results.result_colors: pen.setColor(self.validator_results.result_colors[res]) painter.setPen(pen) num_points = len(res.points) for i in range(0, num_points): i_n = i + 1 line_from = toqp(res.points[i]) line_from += self.crop.topLeft() line_to = toqp( res.points[i_n] if i_n < num_points else res.points[0]) line_to += self.crop.topLeft() painter.drawLine(line_from, line_to) # Draw the QR code data # Note that we reset the world transform to only the scaled transform # because otherwise the text could be flipped. We only use transform_flip # to map the center point of the result. painter.setWorldTransform(transform, False) font_metrics = painter.fontMetrics() data_metrics = QSize(font_metrics.horizontalAdvance(res.data), font_metrics.capHeight()) center_pos = toqp(res.center) center_pos += self.crop.topLeft() center_pos = transform_flip.map(center_pos) text_offset = QPoint(data_metrics.width(), data_metrics.height()) text_offset = text_offset / 2 text_offset.setX(-text_offset.x()) center_pos += text_offset padding = self.BG_RECT_PADDING bg_rect_pos = center_pos - QPoint(padding, data_metrics.height() + padding) bg_rect_size = data_metrics + (QSize(padding, padding) * 2) bg_rect = QRect(bg_rect_pos, bg_rect_size) bg_rect_path = QPainterPath() radius = self.BG_RECT_CORNER_RADIUS bg_rect_path.addRoundedRect(QRectF(bg_rect), radius, radius, Qt.AbsoluteSize) painter.setPen(self.bg_rect_pen) painter.fillPath(bg_rect_path, self.bg_rect_fill) painter.drawPath(bg_rect_path) painter.setPen(self.text_pen) painter.drawText(center_pos, res.data)
class Scribbles(QObject): log = pyqtSignal(str) def __init__(self, scene): super(Scribbles, self).__init__() self.scene = scene self.points = [] self.size = [] self.current_size = 30 self.border_pen = QPen(Qt.black, self.current_size) self.border_pen.setCapStyle(Qt.RoundCap) self.border_pen.setCosmetic(False) self.current_label = Label("Background", "Background", description=None, fill=[0, 0, 0]) self.qpath_gitem = None self.qpath_list = [] # scale factor of the cursor self.scale_factor = 1.0 self.setCustomCursor() def reset(self): for qpath_gitem in self.qpath_list: qpath_gitem.setPath(QPainterPath()) self.points = [] self.label = [] self.size = [] def setCustomCursor(self): cursor_size = self.current_size * self.scale_factor pxmap = QPixmap(cursor_size, cursor_size) pxmap.fill(QColor("transparent")) painter = QPainter(pxmap) color = self.current_label.fill brush = QBrush(QColor(color[0], color[1], color[2])) painter.setBrush(brush) painter.drawEllipse(0, 0, cursor_size, cursor_size) painter.end() custom_cursor = QCursor(pxmap) QApplication.setOverrideCursor(custom_cursor) def setLabel(self, label): self.current_label = label # new cursor color color = label.fill qt_color = QColor(color[0], color[1], color[2]) self.border_pen.setColor(qt_color) self.setCustomCursor() def setScaleFactor(self, scale_factor): self.scale_factor = scale_factor def setSize(self, delta_size): new_size = self.current_size + delta_size if new_size < 10: new_size = 10 elif new_size > 200: new_size = 200 self.current_size = new_size self.border_pen.setWidth(self.current_size) self.setCustomCursor() # return true if the first points for a tool def startDrawing(self, x, y): first_start = False if len(self.points) == 0: # first point, initialize first_start = True message = "[TOOL] DRAWING starts.." self.log.emit(message) self.points.append(np.array([[x, y]])) self.label.append(self.current_label) self.size.append(self.current_size) self.qpath_gitem = self.scene.addPath(QPainterPath(), self.border_pen) self.qpath_gitem.setZValue(5) path = self.qpath_gitem.path() path.moveTo(QPointF(x, y)) self.qpath_list.append(self.qpath_gitem) self.qpath_gitem.setPath(path) self.scene.invalidate() return first_start def move(self, x, y): if len(self.points) == 0: return # check that a move didn't happen before a press last_line = self.points[-1] last_point = self.points[-1][-1] if x != last_point[0] or y != last_point[1]: self.points[-1] = np.append(last_line, [[x, y]], axis=0) path = self.qpath_list[-1].path() path.lineTo(QPointF(x, y)) self.qpath_gitem.setPath(path) self.qpath_gitem.setPen(self.border_pen) self.scene.invalidate()
class Window(QtWidgets.QMainWindow): def __init__(self): QtWidgets.QWidget.__init__(self) uic.loadUi("window.ui", self) self.setMouseTracking(True) self.scene = QtWidgets.QGraphicsScene(0, 0, 600, 600) self.view.setScene(self.scene) self.image = QImage(600, 600, QImage.Format_MonoLSB) self.pen = QPen(black) self.funcs.addItems(["2 * cos(x * z)", "5*sin(x) - cos(z)", "exp(sin(sqrt(x**2 + z**2)))", "cos(x) * sin(z)", "cos(x**2 + z**2)", "(x**2+z**2)**0.5", "1-abs(x+z)-abs(z-x)"]) self.pen.setColor(green) self.image.setColor(0, qRgb(255, 111, 105)) self.image.setColor(1, qRgb(0, 0, 0)) self.image.fill(bg_color) self.scene.setBackgroundBrush(QBrush(black)) self.x_angle.valueChanged.connect(lambda: self.angle_changed(self)) self.y_angle.valueChanged.connect(lambda: self.angle_changed(self)) self.z_angle.valueChanged.connect(lambda: self.angle_changed(self)) self.draw.clicked.connect(lambda: self.draw_on_click_button(self)) self.scene.installEventFilter(self) #----------------- click event ------------------------------------ def eventFilter(self, object, event): if event.type() == QtCore.QEvent.GraphicsSceneMousePress: point = event.scenePos() self.add_point_mouse(point) return False def add_point_mouse(self, point): print("coords : ", point.x(), point.y()); #----------------- buttons ------------------------------------ def draw_on_click_button(self, win): self.angle_changed(win) #----------------- methods ------------------------------------ def f(self, x, z): return eval(self.funcs.currentText()) def angle_changed(self, win): self.scene.clear() self.image.fill(bg_color) self.floating_horizon() pix = QPixmap() pix.convertFromImage(self.image) self.scene.addPixmap(pix) def floating_horizon(self): top = [0 for x in range(1, int(self.scene.width())+1)] bottom = [self.scene.height() for x in range(1, int(self.scene.width())+1)] xl, xr = -1, -1 yl, yr = -1, -1 zMax = self.max_z.value() zMin = self.min_z.value() xMax = self.max_x.value() xMin = self.min_x.value() zStep = self.step_z.value() xStep = self.step_x.value() z = zMax while z>=zMin: xPrev = xMin yPrev = self.f(xMin, z) xPrev, yPrev, zT = self.transform(xPrev, yPrev, z) if xl != -1: top, bottom, self.image = horizon(xl, yl, xPrev, yPrev, top, bottom, self.image) xl = xPrev yl = yPrev x = xMin while x <= xMax: y = self.f(x, z) xCurr, yCurr, zT = self.transform(x, y, z) top, bottom, self.image = horizon(xPrev, yPrev, xCurr, yCurr, top, bottom, self.image) xPrev = xCurr yPrev = yCurr x += xStep if z != zMax: xr = xMax yr = self.f(xr, z-zStep) xr, yr, zT = self.transform(xr, yr, z) top, bottom, self.image = horizon(xr, yr, xPrev, yPrev, top, bottom, self.image) z -= zStep def transform(self, x, y, z): x, y, z = rotateX(x, y, z, self.x_angle.value()) x, y, z = rotateY(x, y, z, self.y_angle.value()) x, y, z = rotateZ(x, y, z, self.z_angle.value()) x = x * k + shx y = y * k + shy return round(x), round(y), round(z)
class Viewer(QGraphicsView): def __init__(self, gridsize_label, position_label, help_label): QGraphicsView.__init__(self) self.gridsize_label = gridsize_label self.position_label = position_label self.help_label = help_label # Create a QGraphicsScene which this view looks at self.scene = QGraphicsScene(self) self.scene.setSceneRect(QRectF()) self.setScene(self.scene) # Customize QGraphicsView self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setInteractive(False) self.scale(1,-1) # Flips around the Y axis # Use OpenGL http://ralsina.me/stories/BBS53.html # self.setViewport(QtOpenGL.QGLWidget()) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.pen = QPen(QtCore.Qt.black, 0) self.portpen = QPen(PORT_COLOR, 3) self.portpen.setCosmetic(True) # Makes constant width self.portfont = QtGui.QFont('Arial', pointSize = 14) self.portfontcolor = PORT_COLOR self.subportpen = QPen(SUBPORT_COLOR, 3) self.subportpen.setCosmetic(True) # Makes constant width self.subportfont = QtGui.QFont('Arial', pointSize = 14) self.subportfontcolor = SUBPORT_COLOR # Tracking ports # Various status variables self._mousePressed = None self._rb_origin = QPoint() self.zoom_factor_total = 1 # Grid variables self.gridpen = QPen(QtCore.Qt.black, 0) self.gridpen.setStyle(QtCore.Qt.DotLine) self.gridpen.setDashPattern([1,4]) self.gridpen.setColor(QtGui.QColor(0, 0, 0, 125)) # self.gridpen = QPen(QtCore.Qt.black, 1) # self.gridpen.setCosmetic(True) # Makes constant width self.scene_polys = [] self.initialize() def add_polygons(self, polygons, color = '#A8F22A', alpha = 1): qcolor = QColor() qcolor.setNamedColor(color) qcolor.setAlphaF(alpha) for points in polygons: qpoly = QPolygonF( [QPointF(p[0], p[1]) for p in points] ) scene_poly = self.scene.addPolygon(qpoly) scene_poly.setBrush(qcolor) scene_poly.setPen(self.pen) self.scene_polys.append(scene_poly) # Update custom bounding box sr = scene_poly.sceneBoundingRect() if len(self.scene_polys) == 1: self.scene_xmin = sr.left() self.scene_xmax = sr.right() self.scene_ymin = sr.top() self.scene_ymax = sr.bottom() else: self.scene_xmin = min(self.scene_xmin, sr.left()) self.scene_xmax = max(self.scene_xmax, sr.right()) self.scene_ymin = min(self.scene_ymin, sr.top()) self.scene_ymax = max(self.scene_ymax, sr.bottom()) def reset_view(self): # The SceneRect controls how far you can pan, make it larger than # just the bounding box so middle-click panning works panning_rect = QRectF(self.scene_bounding_rect) panning_rect_center = panning_rect.center() panning_rect_size = max(panning_rect.width(), panning_rect.height())*3 panning_rect.setSize(QSizeF(panning_rect_size, panning_rect_size)) panning_rect.moveCenter(panning_rect_center) self.setSceneRect(panning_rect) self.fitInView(self.scene_bounding_rect, Qt.KeepAspectRatio) self.zoom_view(0.8) self.update_grid() def add_port(self, port, is_subport = False): if (port.width is None) or (port.width == 0): x,y = port.midpoint cs = 1 # cross size pn = QPointF(x, y+cs) ps = QPointF(x, y-cs) pe = QPointF(x+cs, y) pw = QPointF(x-cs, y) qline1 = self.scene.addLine(QLineF(pn, ps)) qline2 = self.scene.addLine(QLineF(pw, pe)) port_shapes = [qline1,qline2] else: point1, point2 = port.endpoints point1 = QPointF(point1[0], point1[1]) point2 = QPointF(point2[0], point2[1]) qline = self.scene.addLine(QLineF(point1, point2)) arrow_points, text_pos = _port_marker(port, is_subport) arrow_qpoly = QPolygonF( [QPointF(p[0], p[1]) for p in arrow_points] ) port_scene_poly = self.scene.addPolygon(arrow_qpoly) # port_scene_poly.setRotation(port.orientation) # port_scene_poly.moveBy(port.midpoint[0], port.midpoint[1]) port_shapes = [qline,port_scene_poly] qtext = self.scene.addText(str(port.name), self.portfont) qtext.setPos(QPointF(text_pos[0], text_pos[1])) qtext.setFlag(QGraphicsItem.ItemIgnoresTransformations) port_items = port_shapes + [qtext] if not is_subport: [shape.setPen(self.portpen) for shape in port_shapes] qtext.setDefaultTextColor(self.portfontcolor) self.portitems += port_items else: [shape.setPen(self.subportpen) for shape in port_shapes] qtext.setDefaultTextColor(self.subportfontcolor) self.subportitems += port_items # self.portlabels.append(qtext) def add_aliases(self, aliases): for name, ref in aliases.items(): qtext = self.scene.addText(str(name), self.portfont) x,y = ref.center qtext.setPos(QPointF(x,y)) qtext.setFlag(QGraphicsItem.ItemIgnoresTransformations) self.aliasitems += [qtext] def set_port_visibility(self, visible = True): for item in self.portitems: item.setVisible(visible) self.ports_visible = visible def set_subport_visibility(self, visible = True): for item in self.subportitems: item.setVisible(visible) self.subports_visible = visible def set_alias_visibility(self, visible = True): for item in self.aliasitems: item.setVisible(visible) self.aliases_visible = visible def initialize(self): self.scene.clear() self.polygons = {} self.portitems = [] self.subportitems = [] self.aliasitems = [] self.aliases_visible = True self.ports_visible = True self.subports_visible = True self.mouse_position = [0,0] self.grid_size_snapped = 0 self.setMouseTracking(True) self.scene_bounding_rect = None self.scene_polys = [] self.scene_xmin = 0 self.scene_xmax = 1 self.scene_ymin = 0 self.scene_ymax = 1 def finalize(self): self.scene_bounding_rect = QRectF(QPointF(self.scene_xmin,self.scene_ymin), QPointF(self.scene_xmax,self.scene_ymax)) # self.scene_center = [self.scene_bounding_rect.center().x(), self.scene_bounding_rect.center().y()] self.scene_size = [self.scene_bounding_rect.width(), self.scene_bounding_rect.height()] self.create_grid() self.update_grid() #============================================================================== # Grid creation #============================================================================== def update_grid(self): grid_pixels = 50 grid_snaps = [1,2,4] # Number of pixels in the viewer view_width, view_height = self.rect().width(), self.rect().height() # Rectangle of viewport in terms of scene coordinates r = self.mapToScene(self.rect()).boundingRect() width, height = r.width(), r.height() xmin, ymin, xmax, ymax = r.x(), r.y(), r.x() + width, r.y() + height grid_size = grid_pixels*(width / view_width) exponent = np.floor( np.log10(grid_size) ) digits = round(grid_size / 10**(exponent), 2) digits_snapped = min(grid_snaps, key=lambda x:abs(x-digits)) grid_size_snapped = digits_snapped * 10**(exponent) # Starting coordinates for gridlines x = round((xmin - 2*width )/grid_size_snapped) * grid_size_snapped y = round((ymin - 2*height)/grid_size_snapped) * grid_size_snapped for gl in self.gridlinesx: gl.setLine(x, -1e10, x, 1e10) x += grid_size_snapped for gl in self.gridlinesy: gl.setLine(-1e10, y, 1e10, y) y += grid_size_snapped self.grid_size_snapped = grid_size_snapped self.update_gridsize_label() def update_gridsize_label(self): self.gridsize_label.setText('grid size = ' + str(self.grid_size_snapped)) self.gridsize_label.move(QPoint(5, self.height()-25)) def update_mouse_position_label(self): self.position_label.setText('X = %0.4f / Y = %0.4f' % (self.mouse_position[0],self.mouse_position[1])) self.position_label.move(QPoint(self.width() - 250, self.height()-25)) def update_help_label(self): self.help_label.setText('Press "?" key for help') self.help_label.move(QPoint(self.width() - 175, 0)) def create_grid(self): self.gridlinesx = [self.scene.addLine(-10,-10,10,10, self.gridpen) for n in range(300)] self.gridlinesy = [self.scene.addLine(-10,-10,10,10, self.gridpen) for n in range(300)] self.update_grid() #============================================================================== # Mousewheel zoom, taken from http://stackoverflow.com/a/29026916 #============================================================================== def wheelEvent(self, event): # Zoom Factor zoom_percentage = 1.4 # Set Anchors self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) # Save the scene pos oldPos = self.mapToScene(event.pos()) # Zoom mousewheel_rotation = event.angleDelta().y() # Typically = 120 on most mousewheels zoom_factor = zoom_percentage**(mousewheel_rotation/120) zoom_factor = np.clip(zoom_factor, 0.5, 2.0) # Check to make sure we're not overzoomed min_width = 0.01 min_height = 0.01 window_width = self.rect().width() window_height = self.rect().height() scene_upper_left_corner = self.mapToScene(QPoint(0,0)) scene_bottom_right_corner = self.mapToScene(QPoint(window_width,window_height)) scene_width = (scene_bottom_right_corner - scene_upper_left_corner).x() scene_height = (scene_upper_left_corner - scene_bottom_right_corner).y() max_width = self.scene_bounding_rect.width()*3 max_height = self.scene_bounding_rect.height()*3 if ((scene_width > max_width) and (scene_height > max_height)) and (zoom_factor < 1): pass elif ((scene_width < min_width) and (scene_height < min_height)) and (zoom_factor > 1): pass else: self.zoom_view(zoom_factor) # Get the new position and move scene to old position newPos = self.mapToScene(event.pos()) delta = newPos - oldPos self.translate(delta.x(), delta.y()) self.update_grid() def zoom_view(self, zoom_factor): old_center = self.mapToScene(self.rect().center()) self.scale(zoom_factor, zoom_factor) self.centerOn(old_center) self.zoom_factor_total *= zoom_factor def resizeEvent(self, event): super(QGraphicsView, self).resizeEvent(event) if self.scene_bounding_rect is not None: self.reset_view() self.update_gridsize_label() self.update_mouse_position_label() self.update_help_label() def mousePressEvent(self, event): super(QGraphicsView, self).mousePressEvent(event) #============================================================================== # Zoom to rectangle, from # https://wiki.python.org/moin/PyQt/Selecting%20a%20region%20of%20a%20widget #============================================================================== if event.button() == Qt.RightButton: self._mousePressed = Qt.RightButton self._rb_origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self._rb_origin, QSize())) self.rubberBand.show() #============================================================================== # Mouse panning, taken from # http://stackoverflow.com/a/15043279 #============================================================================== elif event.button() == Qt.MidButton: self._mousePressed = Qt.MidButton self._mousePressedPos = event.pos() self.setCursor(QtCore.Qt.ClosedHandCursor) self._dragPos = event.pos() def mouseMoveEvent(self, event): super(QGraphicsView, self).mouseMoveEvent(event) # # Useful debug # try: # self.debug_label.setText(str(itemsBoundingRect_nogrid().width())) # except: # print('Debug statement failed') # Update the X,Y label indicating where the mouse is on the geometry mouse_position = self.mapToScene(event.pos()) self.mouse_position = [mouse_position.x(), mouse_position.y()] self.update_mouse_position_label() if not self._rb_origin.isNull() and self._mousePressed == Qt.RightButton: self.rubberBand.setGeometry(QRect(self._rb_origin, event.pos()).normalized()) # Middle-click-to-pan if self._mousePressed == Qt.MidButton: newPos = event.pos() diff = newPos - self._dragPos self._dragPos = newPos self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - diff.x()) self.verticalScrollBar().setValue(self.verticalScrollBar().value() - diff.y()) # event.accept() def mouseReleaseEvent(self, event): if event.button() == Qt.RightButton: self.rubberBand.hide() rb_rect = QRect(self._rb_origin, event.pos()) rb_center = rb_rect.center() rb_size = rb_rect.size() if abs(rb_size.width()) > 3 and abs(rb_size.height()) > 3: viewport_size = self.viewport().geometry().size() zoom_factor_x = abs(viewport_size.width() / rb_size.width()) zoom_factor_y = abs(viewport_size.height() / rb_size.height()) new_center = self.mapToScene(rb_center) zoom_factor = min(zoom_factor_x, zoom_factor_y) self.zoom_view(zoom_factor) self.centerOn(new_center) self.update_grid() if event.button() == Qt.MidButton: self.setCursor(Qt.ArrowCursor) self._mousePressed = None self.update_grid() def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.reset_view() if event.key() == Qt.Key_F1: self.set_alias_visibility(not self.aliases_visible) if event.key() == Qt.Key_F2: self.set_port_visibility(not self.ports_visible) if event.key() == Qt.Key_F3: self.set_subport_visibility(not self.subports_visible) if event.key() == Qt.Key_Question: help_str = """ Mouse control: Mousewheel: Zoom in and out Right-click & drag: Zoom to rectangle Middle-click & drag: Pan Keyboard shortcuts: Esc: Reset view F1: Show/hide alias names F2: Show/hide ports F3: Show/hide subports (ports in underlying references) """ QMessageBox.about(self, 'PHIDL Help', help_str)
def createGraphics(self): """ Create the graphical representation of the FMU's inputs and outputs """ def variableColor(variable): if variable.type == 'Real': return QColor.fromRgb(0, 0, 127) elif variable.type in ['Integer', 'Enumeration']: return QColor.fromRgb(255, 127, 0) elif variable.type == 'Boolean': return QColor.fromRgb(255, 0, 255) elif variable.type == 'String': return QColor.fromRgb(0, 128, 0) else: return QColor.fromRgb(0, 0, 0) inputVariables = [] outputVariables = [] maxInputLabelWidth = 0 maxOutputLabelWidth = 0 textItem = QGraphicsTextItem() fontMetrics = QFontMetricsF(textItem.font()) for variable in self.modelDescription.modelVariables: if variable.causality == 'input': inputVariables.append(variable) elif variable.causality == 'output': outputVariables.append(variable) for variable in inputVariables: maxInputLabelWidth = max(maxInputLabelWidth, fontMetrics.width(variable.name)) for variable in outputVariables: maxOutputLabelWidth = max(maxOutputLabelWidth, fontMetrics.width(variable.name)) from math import floor scene = QGraphicsScene() self.ui.graphicsView.setScene(scene) group = QGraphicsItemGroup() scene.addItem(group) group.setPos(200.5, -50.5) lh = 15 # line height w = max(150., maxInputLabelWidth + maxOutputLabelWidth + 20) h = max(50., 10 + lh * max(len(inputVariables), len(outputVariables))) block = QGraphicsRectItem(0, 0, w, h, group) block.setPen(QColor.fromRgb(0, 0, 255)) pen = QPen() pen.setWidthF(1) font = QFont() font.setPixelSize(10) # inputs y = floor((h - len(inputVariables) * lh) / 2 - 2) for variable in inputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(3) text.setY(y) polygon = QPolygonF([ QPointF(-13.5, y + 4), QPointF(1, y + 11), QPointF(-13.5, y + 18) ]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) contour.setPen(QPen(Qt.NoPen)) contour.setBrush(variableColor(variable)) y += lh # outputs y = floor((h - len(outputVariables) * lh) / 2 - 2) for variable in outputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(w - 3 - text.boundingRect().width()) text.setY(y) polygon = QPolygonF([ QPointF(w, y + 0 + 7.5), QPointF(w + 7, y + 3.5 + 7.5), QPointF(w, y + 7 + 7.5) ]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) pen = QPen() pen.setColor(variableColor(variable)) pen.setJoinStyle(Qt.MiterJoin) contour.setPen(pen) y += lh
class main_gui(Ui_ConvexHullGui, QWidget): def __init__(self): super(QWidget, self).__init__() self.setupUi(self) self.set_Scene() self.set_Pen() self.Point_list = list() self.Line_list = list() self.run = False self.vertexconfirm.clicked.connect(self.generate_p) self.runbutton.clicked.connect(self.find_convex_hull) self.show() def set_Scene(self): self.Max_x = 750 self.Max_y = 490 self.gscene = QGraphicsScene(self) self.graphicsView.setScene(self.gscene) def set_Pen(self): self.POINT_PEN_Width = 2 self.LINE_PEN_Width = 1 self.POINT_PEN_Color = QColor(0, 0, 255) self.LINE_PEN_Color = QColor(0, 0, 0) self.pointPen = QPen() self.pointPen.setWidth(self.POINT_PEN_Width) self.pointPen.setColor(self.POINT_PEN_Color) self.linePen = QPen() self.linePen.setWidth(self.LINE_PEN_Width) self.linePen.setColor(self.LINE_PEN_Color) def add_Point(self, p): assert isinstance(p, Point) point = QGraphicsEllipseItem(p.x, p.y, self.POINT_PEN_Width, self.POINT_PEN_Width) point.setPen(self.pointPen) self.gscene.addItem(point) def add_Line(self, l): assert isinstance(l, Line) line = QGraphicsLineItem(l.End_p[0].x, l.End_p[0].y, l.End_p[1].x, l.End_p[1].y) line.setPen(self.linePen) self.Line_list.append(line) self.gscene.addItem(line) def remove_last_Line(self): self.gscene.removeItem(self.Line_list.pop()) def clear(self): self.gscene.clear() self.Point_list.clear() self.Line_list.clear() def all_input_disable(self): self.inputbox.setEnabled(False) self.vertexconfirm.setEnabled(False) self.runbutton.setEnabled(False) def all_input_enable(self): self.inputbox.setEnabled(True) self.vertexconfirm.setEnabled(True) self.runbutton.setEnabled(True) def generate_p(self): self.all_input_disable() self.clear() self.run = False for i in range(self.inputbox.value()): p = Point.random_generate() self.Point_list.append(p) self.add_Point(p) self.all_input_enable() def find_convex_hull(self): self.all_input_disable() if len(self.Point_list) > 3 and not self.run: self.run = True self.Point_list.sort(key=lambda k: k.y) button = self.Point_list[-1] flag = False point_pre = Point(button.x - 1, button.y) point_cur = button while point_cur is not button or not flag: flag = True max_radians = 0 target = None for point_nex in self.Point_list: if point_nex != point_cur and point_nex != point_pre: rad = Point.get_radians(point_pre, point_cur, point_nex) if rad > max_radians: max_radians = rad target = point_nex point_pre = point_cur point_cur = target self.Point_list.remove(target) self.add_Line(Line(point_pre, point_cur)) self.all_input_enable()
class QImagePainter(QSmoothGraphicsView): # signals imageFlattened = pyqtSignal(QImage) def __init__(self): super().__init__() self.scene = QGraphicsScene(self) self.setScene(self.scene) self.setRenderHint(QPainter.Antialiasing) self.mainPixmapItem = self.scene.addPixmap(QPixmap()) self._appContext = None # policies # self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) # self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.toolbar = QToolBar() self.initToolbar() self._pen = QPen() self._pen.setWidth(50) self.setDefaultPenColor() self._drawStartPos = None self._dynamicOval = None self._drawnItems = [] self.updateDragMode() @property def appContext(self): return self._appContext @appContext.setter def appContext(self, context): self._appContext = context self.toolbar.clear() self.initToolbar() def setMainPixmapFromPath(self, imgPath): # set image image = QImage(str(imgPath)) pixmap = self.mainPixmapItem.pixmap() pixmap.convertFromImage(image) self.setMainPixmap(pixmap) def setMainPixmap(self, pixmap): self.mainPixmapItem.setPixmap(pixmap) # set scene rect boundingRect = self.mainPixmapItem.boundingRect() margin = 0 boundingRect += QMarginsF(margin, margin, margin, margin) self.scene.setSceneRect(boundingRect) def saveImage(self, fileName): image = self.flattenImage() image.save(fileName) def flattenImageIfDrawnOn(self): if not len(self._drawnItems) == 0: self.flattenImage() def flattenImage(self): # get region of scene area = self.mainPixmapItem.boundingRect() # create a QImage to render to and fix up a QPainter for it image = QImage(area.width(), area.height(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(image) # render the region of interest to the QImage self.scene.render(painter, QRectF(image.rect()), area) painter.end() # set this flattened image to this view pixmap = self.mainPixmapItem.pixmap() pixmap.convertFromImage(image) self.setMainPixmap(pixmap) # clear the drawings from the view self.clearDrawnItems() # emit flattened image signal self.imageFlattened.emit(image) # return the flattened image return image def clearDrawnItems(self): for item in self._drawnItems: self.scene.removeItem(item) self._drawnItems.clear() def removeLastDrawnItem(self): try: item = self._drawnItems.pop() except IndexError: pass else: self.scene.removeItem(item) def scaleView(self, scaleFactor): # print(f'self.width: {self.width()}') # print(f'pixmap.width(): {self.scene.map.mainPixmapItem.boundingRect().width()}') self.scale(scaleFactor, scaleFactor) def centerImage(self): self.centerOn(self.mainPixmapItem) def bestFitImage(self): self.fitInView(self.mainPixmapItem, Qt.KeepAspectRatio) def keyPressEvent(self, event: QKeyEvent): key = event.key() if key == Qt.Key_Space: self.bestFitImage() else: super().keyPressEvent(event) def mousePressEvent(self, event): self._drawStartPos = None if self.ovalModeAct.isChecked(): if self.mainPixmapItem.isUnderMouse(): self._drawStartPos = self.mapToScene(event.pos()) self._dynamicOval = self.scene.addEllipse( QRectF(self._drawStartPos.x(), self._drawStartPos.y(), 1, 1), self._pen) else: super().mousePressEvent(event) def mouseMoveEvent(self, event): if self._dynamicOval: pos = self.mapToScene(event.pos()) self._dynamicOval.setRect( QRectF(self._drawStartPos.x(), self._drawStartPos.y(), pos.x() - self._drawStartPos.x(), pos.y() - self._drawStartPos.y())) else: super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): if self._dynamicOval: self._drawnItems.append(self._dynamicOval) self._dynamicOval = None else: super().mouseReleaseEvent(event) def toggleSelectionMode(self): if self.selectionModeAct.isChecked(): self.ovalModeAct.setChecked(False) else: self.selectionModeAct.setChecked(True) self.updateDragMode() def toggleOvalMode(self): if self.ovalModeAct.isChecked(): self.selectionModeAct.setChecked(False) else: self.ovalModeAct.setChecked(True) self.updateDragMode() def updateDragMode(self): if self.selectionModeAct.isChecked(): self.setDragMode(QGraphicsView.ScrollHandDrag) else: self.setDragMode(QGraphicsView.NoDrag) @property def penWidth(self): return self._pen.width() @penWidth.setter def penWidth(self, value): self._pen.setWidth(value) @property def penColor(self): return self._pen.color() @penColor.setter def penColor(self, value): self._pen.setColor(QColor(value)) def setDefaultPenColor(self): self.setPenColor(COLORS['Teleric Blue']) def promptForPenWidth(self): width, okPressed = QInputDialog.getInt(self, 'Pen Width', 'Pen width (px):', self.penWidth, 1, 100, 1) if okPressed: self.penWidth = width def setResourcePaths(self): if self.appContext is None: self.selectionModeFp = './icons/selectIcon.png' self.ovalModeFp = './icons/ovalIcon.png' self.flattenFp = './icons/saveIcon.png' self.undoFp = './icons/undoIcon.png' self.penFp = './icons/pen.png' self.penWidthFp = './icons/penWidth.png' else: self.selectionModeFp = self.appContext.get_resource( 'selectIcon.png') self.ovalModeFp = self.appContext.get_resource('ovalIcon.png') self.flattenFp = self.appContext.get_resource('saveIcon.png') self.undoFp = self.appContext.get_resource('undoIcon.png') self.penFp = self.appContext.get_resource('pen.png') self.penWidthFp = self.appContext.get_resource('penWidth.png') def createActions(self): self.setResourcePaths() self.selectionModeAct = QAction(QIcon(self.selectionModeFp), 'Select (v)', self, checkable=True, checked=True, shortcut=Qt.Key_V, triggered=self.toggleSelectionMode) self.ovalModeAct = QAction(QIcon(self.ovalModeFp), 'Draw &Oval (o)', self, checkable=True, checked=False, shortcut=Qt.Key_O, triggered=self.toggleOvalMode) self.flattenAct = QAction(QIcon(self.flattenFp), 'Save', self, shortcut=QKeySequence.Save, triggered=self.flattenImage) self.undoAct = QAction(QIcon(self.undoFp), 'Undo', self, shortcut=QKeySequence.Undo, triggered=self.removeLastDrawnItem) self.setPenWidthAct = QAction(QIcon(self.penWidthFp), 'Set Pen Width', self, triggered=self.promptForPenWidth) def addPenToolMenu(self): penButton = QToolButton(self) penButton.setText('Pen') penButton.setIcon(QIcon(self.penFp)) penButton.setPopupMode(QToolButton.InstantPopup) self.penMenu = QMenu(penButton) self.penMenu.addAction(self.setPenWidthAct) self.addPaletteToMenu(self.penMenu) penButton.setMenu(self.penMenu) self.toolbar.addWidget(penButton) def setPenColor(self, color): qColor = QColor(color) for a in self.penMenu.actions(): a.setChecked(False) try: actionColor = QColor(a.color) except AttributeError: pass else: if actionColor == qColor: a.setChecked(True) self.penColor = actionColor def addPaletteToMenu(self, menu): for name, color in COLORS.items(): paletteIcon = QPaletteIcon(color) action = QAction(paletteIcon, name, self, checkable=True) action.color = color action.triggered.connect( lambda checked, color=color: self.setPenColor(color)) menu.addAction(action) def initToolbar(self): self.createActions() # self.toolbar.addAction(self.flattenAct) self.toolbar.addAction(self.undoAct) # self.toolbar.addSeparator() self.toolbar.addAction(self.selectionModeAct) self.toolbar.addAction(self.ovalModeAct) self.addPenToolMenu()
class BorderItem(QGraphicsObject): def __init__(self, scene, view_scale, shape, transform=QTransform(), parent=None): super(BorderItem, self).__init__(parent) self.setTransform(transform) self.shape = shape self._item_path = QPainterPath(QPoint(0, 0)) self._pen = QPen() self._pen.setWidthF(adjust_pen_width(PEN_STANDARD_WIDTH, view_scale)) # 设置蚂蚁线数据 self._line_len = 4 self._line_step = .2 self._line_speed = 100 self._line_color = Qt.black # 线条的长度 self._dashes = 4 # 空白长度 self._spaces = 10 self._dash_pattern = [self._line_len] * 20 self._timer = QTimer() self._timer.timeout.connect(self.update_value) if scene: scene.clearSelection() scene.addItem(self) def is_empty(self): return self._item_path.isEmpty() def get_path(self): return self._item_path def get_scene_path(self): return self.mapToScene(self.get_path()) def copy(self): new_item = SelectionItem( position=self.scenePos(), scene=None, view_scale=1, path=self._item_path, shape=self.get_shape(), transform=self.transform(), parent=self.parent() ) new_item.pen = self.pen return new_item def set_item_path_by_size(self, width=0, height=0): self._item_path = QPainterPath(QPoint(0, 0)) self._item_path.addRect(QRectF(0, 0, width, height)) self.update(self.boundingRect()) def set_item_path_by_path(self, path): self._item_path = path def set_pen_width_by_scale(self, width: [int, float]): pen_width = adjust_pen_width(PEN_STANDARD_WIDTH, width) self._pen.setWidthF(pen_width) def set_pen_width_by_width(self, width: [int, float]): if isinstance(width, int): self._pen.setWidth(width) elif isinstance(width, float): self._pen.setWidthF(width) @property def pen(self): return self._pen @pen.setter def pen(self, new_pen: QPen): self._pen = new_pen def update_value(self): """""" if self._dashes >= self._line_len and self._spaces >= self._line_len: self._dashes = self._spaces = 0. if self._dashes <= 0 and self._spaces < self._line_len: self._spaces += self._line_step elif self._dashes < self._line_len <= self._spaces: self._dashes += self._line_step self._dash_pattern[0] = self._dashes self._dash_pattern[1] = self._spaces self.update(self.boundingRect()) def add_area(self, path: QPainterPath): """TODO""" def cut_area(self, path: QPainterPath): """TODO""" def combine_area(self, path: QPainterPath): """TODO""" def intersects(self, other) -> bool: p1 = self.mapToScene(self.get_path()) p2 = other.mapToScene(other.get_path()) return p1.intersects(p2) def shape(self): return self._item_path # 继承QGraphicsItem类必须实现 boundingRect() paint()两个方法 # 返回本item的 包围和矩形 QRectF 用于item的点击等判断 def boundingRect(self): return self._item_path.boundingRect().adjusted(0, 0, 2, 2) def paint(self, painter: QPainter, option, widget=None) -> None: self._pen.setColor(Qt.white) self._pen.setStyle(Qt.SolidLine) painter.setPen(self._pen) painter.drawPath(self._item_path) self._pen.setColor(Qt.black) self._pen.setDashPattern(self._dash_pattern) painter.setPen(self._pen) painter.drawPath(self._item_path) def __add__(self, other): """ 轮廓 +operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) new_path = self.mapFromScene(p1 + p2) new_item = self.copy() new_item.set_item_path_by_path(new_path) return new_item def __iadd__(self, other): """ 轮廓 +=operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) new_path = self.mapFromScene(p1 + p2) new_path.closeSubpath() self._item_path = new_path return self def __sub__(self, other): """ 轮廓 -operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) new_path = self.mapFromScene(p1 - p2) new_path.closeSubpath() new_item = self.copy() new_item.set_item_path_by_path(new_path) return new_item def __isub__(self, other): """ 轮廓 -=operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) new_path = self.mapFromScene(p1 - p2) new_path.closeSubpath() self._item_path = new_path self.update() return self def __and__(self, other): """ 轮廓 &operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) new_path = self.mapFromScene(p1 & p2) new_path.closeSubpath() new_item = self.copy() new_item.set_item_path_by_path(new_path) return new_item def __iand__(self, other): """ 轮廓 &=operation :param other: :return: self """ p1 = self.mapToScene(self._item_path) p2 = other.mapToScene(other.get_path()) self._item_path = self.mapFromScene(p1 & p2) self._item_path.closeSubpath() self.update() return self
def draw_skeletons(self, painter, roi_id, row_data, is_current_index): if self.traj_worm_index_grouped is None: return if self.coordinates_fields is None: return worm_index = int(row_data[self.worm_index_type]) skel_id = int(row_data['skeleton_id']) if self.coordinates_fields is None or skel_id < 0: return skel_dat = {} with tables.File(self.skeletons_file, 'r') as skel_file_id: # print(self.coordinates_group) # print(self.coordinates_fields) for ff, tt in self.coordinates_fields.items(): field = self.coordinates_group + ff if field in skel_file_id: dat = skel_file_id.get_node(field)[skel_id] dat /= self.microns_per_pixel if self.stage_position_pix is not None and self.stage_position_pix.size > 0: #subtract stage motion if necessary dat -= self.stage_position_pix[self.frame_number] #dat[:, 0] = (dat[:, 0] - roi_corner[0] + 0.5) * c_ratio_x #dat[:, 1] = (dat[:, 1] - roi_corner[1] + 0.5) * c_ratio_y else: dat = np.full((1,2), np.nan) skel_dat[tt] = dat if 'is_good_skel' in row_data and row_data['is_good_skel'] == 0: skel_colors = BAD_SKEL_COLOURS else: skel_colors = GOOD_SKEL_COLOURS qPlg = {} for tt, dat in skel_dat.items(): qPlg[tt] = QPolygonF() for p in dat: #do not add point if it is nan if p[0] == p[0]: qPlg[tt].append(QPointF(*p)) if not qPlg or len(qPlg['skeleton']) == 0: #all nan skeleton nothing to do here... return pen = QPen() pen.setWidth(0.5) # pen.setColor(QColor(col)) # painter.setPen(pen) # painter.drawPolyline(pol_v) for k, pol_v in qPlg.items(): color = skel_colors[k] pen.setColor(QColor(*color)) painter.setPen(pen) painter.drawPolyline(pol_v) pen.setColor(Qt.black) painter.setBrush(Qt.white) painter.setPen(pen) radius = 2 painter.drawEllipse(qPlg['skeleton'][0], radius, radius) painter.drawEllipse(QPointF(0,0), radius, radius)
class Window(QtWidgets.QMainWindow): def __init__(self): QtWidgets.QWidget.__init__(self) uic.loadUi("window.ui", self) self.setMouseTracking(True) self.scene = QtWidgets.QGraphicsScene(0, 0, 520, 520) self.view.setScene(self.scene) self.image = QImage(520, 520, QImage.Format_ARGB32_Premultiplied) self.pen = QPen(black) self.lines = [] self.cut = [] self.mode = None self.click_check = False self.prev_point = None self.clear.clicked.connect(lambda: self.clean_on_click_button(self)) self.line.clicked.connect(lambda: self.add_line_mode(self)) self.line_2.clicked.connect(lambda: self.add_par_line(self)) self.paint.clicked.connect(lambda: self.paint_on_click_button(self)) self.cutter.clicked.connect(lambda: self.add_cutter_mode(self)) self.scene.installEventFilter(self) #----------------- click event ------------------------------------ def eventFilter(self, object, event): if event.type() == QtCore.QEvent.GraphicsSceneMousePress: point = event.scenePos() if (self.mode == "line_mode"): self.add_line(event.scenePos()) if (self.mode == "cutter_mode"): self.add_cutter(event.scenePos()) return False def add_point_mouse(self, point): print("coords : ", point.x(), point.y()) def add_line(self, point): print("line coords : ", point.x(), point.y()) if self.click_check: line = [] line.append(self.prev_point) line.append(point) if line not in self.lines: self.pen.setColor(blue) self.add_row(line) self.lines.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) self.pen.setColor(black) else: self.prev_point = point self.click_check = False if self.click_check else True def add_cutter(self, point): print("cutter coords : ", point.x(), point.y()) if self.click_check: line = [] line.append(self.prev_point) line.append(point) if not self.cut: self.cut = line self.scene.addRect(line[0].x(), line[0].y(), abs(line[1].x() - line[0].x()), abs(line[1].y() - line[0].y()), self.pen) else: self.prev_point = point self.click_check = False if self.click_check else True #----------------- buttons ------------------------------------ def add_line_mode(self, win): self.mode = None if self.mode != None else "line_mode" self.button_mode_set() self.click_check = False def add_cutter_mode(self, win): self.mode = None if self.mode != None else "cutter_mode" self.button_mode_set() self.click_check = False def paint_on_click_button(self, win): if not self.cut or not self.lines: print("Check your input data to continue...") return self.pen.setColor(red) lines_to_fill = self.make_cut() self.pen.setColor(blue) def clean_on_click_button(self, win): self.line_2.setEnabled(False) self.scene.clear() self.table.clear() self.lines = [] self.cut = [] self.image.fill(white) self.pen.setColor(black) r = self.table.rowCount() for i in range(r, -1, -1): self.table.removeRow(i) def add_par_line(self, win): if not self.cut: return xl = self.cut[0].x() xr = self.cut[1].x() ya = self.cut[0].y() yb = self.cut[1].y() xl, xr = min(xl, xr), max(xl, xr) ya, yb = max(ya, yb), min(ya, yb) self.pen.setColor(blue) point1 = QPoint(xl + abs(xr - xl) / 10, ya) point2 = QPoint(xr - abs(xr - xl) / 10, ya) line = [] line.append(point1) line.append(point2) if line not in self.lines: self.add_row(line) self.lines.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) point1 = QPoint(xl + abs(xr - xl) / 10, yb) point2 = QPoint(xr - abs(xr - xl) / 10, yb) line = [] line.append(point1) line.append(point2) if line not in self.lines: self.add_row(line) self.lines.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) point1 = QPoint(xl, ya - abs(ya - yb) / 10) point2 = QPoint(xl, yb + abs(ya - yb) / 10) line = [] line.append(point1) line.append(point2) if line not in self.lines: self.add_row(line) self.lines.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) point1 = QPoint(xr, ya - abs(ya - yb) / 10) point2 = QPoint(xr, yb + abs(ya - yb) / 10) line = [] line.append(point1) line.append(point2) if line not in self.lines: self.add_row(line) self.lines.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) self.pen.setColor(black) #----------------- methods ------------------------------------ def button_mode_set(self): if self.mode == None: if self.cut: self.line_2.setEnabled(True) self.clear.setEnabled(True) self.paint.setEnabled(True) self.cutter.setEnabled(True) self.line.setEnabled(True) if self.mode == "line_mode": self.clear.setEnabled(False) self.paint.setEnabled(False) self.cutter.setEnabled(False) self.line_2.setEnabled(False) if self.mode == "cutter_mode": self.clear.setEnabled(False) self.paint.setEnabled(False) self.line.setEnabled(False) self.line_2.setEnabled(False) def add_row(self, line): self.table.insertRow(self.table.rowCount()) i = self.table.rowCount() - 1 item_b = QTableWidgetItem("[{0}, {1}]".format(line[0].x(), line[0].y())) item_e = QTableWidgetItem("[{0}, {1}]".format(line[1].x(), line[1].y())) self.table.setItem(i, 0, item_b) self.table.setItem(i, 1, item_e) def make_cut(self): xl = self.cut[0].x() xr = self.cut[1].x() ya = self.cut[0].y() yb = self.cut[1].y() xl, xr = min(xl, xr), max(xl, xr) ya, yb = max(ya, yb), min(ya, yb) for line in self.lines: p1 = line[0] p2 = line[1] t1, t2 = self.get_codes(p1.x(), p1.y(), p2.x(), p2.y(), xl, xr, ya, yb) visible = True draw_point1 = None draw_point2 = None m = 10**30 if (t1 | t1 == 0 and t2 | t2 == 0): draw_point1 = p1 draw_point2 = p2 else: if t1 & t2: visible = False else: if (t1 | t1 == 0): # check if first point inside zone draw_point1 = p1 q = p2 draw_point2 = self.find_crossings( p1, p2, q, xl, xr, ya, yb) if not draw_point2: visible = False print("The line visibility is ", visible) elif (t2 | t2 == 0): # check if second pointn inside zone draw_point1 = p2 q = p1 draw_point2 = self.find_crossings( p1, p2, q, xl, xr, ya, yb) if not draw_point2: visible = False print("The line visibility is ", visible) else: # other situations print("+++") q = p1 draw_point1 = self.find_crossings( p1, p2, q, xl, xr, ya, yb) print(draw_point1) q = p2 draw_point2 = self.find_crossings( p1, p2, q, xl, xr, ya, yb) print(draw_point2) if not draw_point1 or not draw_point2: visible = False print("The line visibility is ", visible) if visible: self.scene.addLine(draw_point1.x(), draw_point1.y(), draw_point2.x(), draw_point2.y(), self.pen) print(line) def find_crossings(self, p1, p2, q, xl, xr, ya, yb): draw_point = None if p1.x() != p2.x(): m = (p2.y() - p1.y()) / (p2.x() - p1.x()) if q.x() < xl: y_crossing = m * (xl - q.x()) + q.y() print(y_crossing) if y_crossing < ya and y_crossing > yb: draw_point = QPointF(xl, y_crossing) if q.x() > xr: y_crossing = m * (xr - q.x()) + q.y() print("2: ", y_crossing) if y_crossing < ya and y_crossing > yb: draw_point = QPointF(xr, y_crossing) if m: if q.y() > ya: x_crossing = 1 / m * (ya - q.y()) + q.x() print(x_crossing) if x_crossing < xr and x_crossing > xl: draw_point = QPointF(x_crossing, ya) if q.y() < yb: x_crossing = 1 / m * (yb - q.y()) + q.x() print("2: ", x_crossing) if x_crossing < xr and x_crossing > xl: draw_point = QPointF(x_crossing, yb) return draw_point def get_codes(self, x1, y1, x2, y2, xl, xr, ya, yb): t1 = self.get_code_for_dot(x1, y1, xl, xr, ya, yb) t2 = self.get_code_for_dot(x2, y2, xl, xr, ya, yb) return t1, t2 def get_code_for_dot(self, x, y, xl, xr, ya, yb): t = 0 if x < xl: t = t | 0b0001 if x > xr: t = t | 0b0010 if y < yb: t = t | 0b0100 if y > ya: t = t | 0b1000 print(bin(t)) return t
def run(self): #cap = cv.VideoCapture(0) cap = cv.VideoCapture(self.video_path) frame_timer1 = 0 box_color = (255, 0, 0) myQPen = QPen() myQFont = QFont() myQFont.setPixelSize(20) print(self.save_show_label[0]) if self.save_show_label[0] != 0: fps = cap.get(cv.CAP_PROP_FPS) size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))) vw = cv.VideoWriter("./result/" + "test.mp4", cv.VideoWriter_fourcc(*'mp4v'), fps, size) while (cap.isOpened() == True): self.pause.lock() ret, frame = cap.read() if ret: rgbImage = cv.cvtColor(frame, cv.COLOR_BGR2RGB) Qface = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888) #:proess the image if frame_timer1 % self.INTERVAL == 0: rects = self.get_faces(rgbImage) color_list = [] person_name_list = [] for rect in rects: person, confidence = self.get_prediction( rect, rgbImage) person_name = "unknown" if ((person.decode() in self.selected_people) == True) and confidence > self.confidence: self.store_label = 1 person_name = person.decode() box_color = (255, 0, 0) color_list.append(box_color) person_name_list.append(person_name) Qdetected_face = Qface.copy( rect.left(), rect.top(), rect.width(), rect.height()) #:在匹配的人脸上写字 if self.save_show_label[1] == 1: myQPainter = QPainter(Qdetected_face) myQFont.setPixelSize(int(rect.width() / 5)) myQPen.setColor(Qt.red) myQPainter.setPen(myQPen) myQPainter.setFont(myQFont) myQPainter.drawText(Qdetected_face.rect(), Qt.AlignTop, str(round(confidence, 3))) myQPainter.end() #发送信号 self.get_detected_face.emit(Qdetected_face) #在视屏中框出人脸 cv.rectangle(rgbImage, (rect.left(), rect.top()), (rect.right(), rect.bottom()), box_color, 2) cv.putText(rgbImage, person_name, (rect.left(), rect.top()), cv.FONT_HERSHEY_PLAIN, rect.width() / 80, box_color, 2) else: self.store_label = 0 person_name = "unknown" Qrejected_face = Qface.copy( rect.left(), rect.top(), rect.width(), rect.height()) box_color = (0, 255, 0) color_list.append(box_color) person_name_list.append(person_name) #:在匹配的人脸上写字 myQPainter = QPainter(Qrejected_face) myQFont.setPixelSize(int(rect.width() / 5)) myQPen.setColor(Qt.green) myQPainter.setPen(myQPen) myQPainter.setFont(myQFont) myQPainter.drawText(Qrejected_face.rect(), Qt.AlignTop, str(round(confidence, 3))) myQPainter.end() # 发送信号 self.get_rejected_face.emit(Qrejected_face) # 在视屏中框出人脸 cv.rectangle(rgbImage, (rect.left(), rect.top()), (rect.right(), rect.bottom()), box_color, 2) cv.putText(rgbImage, person_name, (rect.left(), rect.top()), cv.FONT_HERSHEY_PLAIN, rect.width() / 80, box_color, 2) if self.save_show_label[0] != 0: vw.write(cv.cvtColor(rgbImage, cv.COLOR_BGR2RGB)) #:for test### QrgbImage = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888) QrgbImage.save( "./saved_image/main/{}.jpg".format(self.save_main_num), "JPG", 100) self.save_main_num = self.save_main_num + 1 ############# else: for i, rect in enumerate(rects): cv.rectangle(rgbImage, (rect.left(), rect.top()), (rect.right(), rect.bottom()), color_list[i], 2) cv.putText(rgbImage, person_name_list[i], (rect.left(), rect.top()), cv.FONT_HERSHEY_PLAIN, rect.width() / 80, color_list[i], 2) pass if self.save_show_label[0] == 2: vw.write(cv.cvtColor(rgbImage, cv.COLOR_BGR2RGB)) elif self.save_show_label[0] == 1: if self.store_label == 1: vw.write(cv.cvtColor(rgbImage, cv.COLOR_BGR2RGB)) if self.save_show_label[1] == 1: QrgbImage = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888) self.changePixmap.emit(QrgbImage) frame_timer1 = (frame_timer1 + 1) % self.INTERVAL #time.sleep(0.01) #控制视频播放的速度 else: break self.pause.unlock()
def __init__(self): super(KVWidget, self).__init__() self.setMouseTracking(True) # 获取数据 self.stocks = read_tick_data() self.k_view = KLineChartView(self.stocks[:100]) self.v_view = VLineChartView(self.stocks[:100]) self.k_view.candles_hovered.connect(self.on_series_hovered) self.v_view.bar_hovered.connect(self.on_series_hovered) btn_widget = QWidget() h_layout = QHBoxLayout() btn_clear = QPushButton('清除') btn_add = QPushButton('添加') h_layout.addStretch() h_layout.addWidget(btn_clear) h_layout.addWidget(btn_add) btn_widget.setLayout(h_layout) btn_clear.clicked.connect(self.on_clear_clicked) btn_add.clicked.connect(self.on_add_clicked) self.v_splitter = QSplitter(Qt.Vertical, self) self.v_splitter.addWidget(self.k_view) self.v_splitter.addWidget(self.v_view) self.v_splitter.addWidget(btn_widget) self.v_splitter.setStretchFactor(0, 3) self.v_splitter.setStretchFactor(1, 2) self.v_splitter.setStretchFactor(2, 1) layout = QVBoxLayout() # layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.v_splitter) self.setLayout(layout) # self.showMaximized() # 鼠标跟踪的十字线 pen = QPen() pen.setStyle(Qt.DotLine) pen.setColor(QColor(0x40, 0x99, 0xF5)) pen.setWidth(1) self.k_line_h = QGraphicsLineItem(self.k_view.chart()) self.k_line_v = QGraphicsLineItem(self.k_view.chart()) self.v_line_h = QGraphicsLineItem(self.v_view.chart()) self.v_line_v = QGraphicsLineItem(self.v_view.chart()) self.k_line_h.setPen(pen) self.k_line_v.setPen(pen) self.v_line_h.setPen(pen) self.v_line_v.setPen(pen) self.k_line_h.setZValue(100) self.k_line_v.setZValue(100) self.v_line_h.setZValue(100) self.v_line_v.setZValue(100) self.k_line_h.hide() self.k_line_v.hide() self.v_line_h.hide() self.v_line_v.hide() # 鼠标在图表的位置, 初始化在左上角 self.tool_tip_widget = GraphicsProxyWidget(self.k_view.chart()) self.k_zero_point = self.k_view.min_point() self.k_max_point = self.k_view.max_point() self.v_zero_point = self.v_view.min_point() self.v_max_point = self.v_view.max_point() self._hovered_pos_left = QPointF(self.k_zero_point.x(), self.k_max_point.y()) self._hovered_pos_right = QPointF( self.k_max_point.x() - self.tool_tip_widget.width(), self.k_max_point.y()) self._hovered_pos = self._hovered_pos_left # 鼠标在中心左边 self._is_left = True # 事件过滤 QApplication.instance().installEventFilter(self)
def paintEvent(self, _event: QPaintEvent): if not self.crop or not self.resolution: return painter = QPainter(self) # Keep a backup of the transform and create a new one transform = painter.worldTransform() # Set scaling transform transform = transform.scale(self.width() / self.resolution.width(), self.height() / self.resolution.height()) # Compute the transform to flip the coordinate system on the x axis transform_flip = QTransform() if self.flip_x: transform_flip = transform_flip.translate( float(self.resolution.width()), 0.0) transform_flip = transform_flip.scale(-1.0, 1.0) # Small helper for tuple to QPoint def toqp(point): return QPoint(int(point[0]), int(point[1])) # Starting from here we care about AA painter.setRenderHint(QPainter.Antialiasing) # Draw the QR code finder overlay painter.setWorldTransform(transform_flip * transform, False) painter.setOpacity(self.QR_FINDER_OPACITY) qr_finder_size = self.crop.size() * self.QR_FINDER_SIZE tmp = (self.crop.size() - qr_finder_size) / 2 qr_finder_pos = QPoint(tmp.width(), tmp.height()) + self.crop.topLeft() qr_finder_rect = QRect(qr_finder_pos, qr_finder_size) self.qr_finder.render(painter, QRectF(qr_finder_rect)) painter.setOpacity(1.0) # Draw all the QR code results for res in self.results: painter.setWorldTransform(transform_flip * transform, False) # Draw lines between all of the QR code points pen = QPen(self.qr_outline_pen) if res in self.validator_results.result_colors: pen.setColor(self.validator_results.result_colors[res]) painter.setPen(pen) num_points = len(res.points) for i in range(0, num_points): i_n = i + 1 line_from = toqp(res.points[i]) line_from += self.crop.topLeft() line_to = toqp( res.points[i_n] if i_n < num_points else res.points[0]) line_to += self.crop.topLeft() painter.drawLine(line_from, line_to) # Draw the QR code data # Note that we reset the world transform to only the scaled transform # because otherwise the text could be flipped. We only use transform_flip # to map the center point of the result. painter.setWorldTransform(transform, False) font_metrics = painter.fontMetrics() data_metrics = QSize(font_metrics.horizontalAdvance(res.data), font_metrics.capHeight()) center_pos = toqp(res.center) center_pos += self.crop.topLeft() center_pos = transform_flip.map(center_pos) text_offset = QPoint(data_metrics.width(), data_metrics.height()) text_offset = text_offset / 2 text_offset.setX(-text_offset.x()) center_pos += text_offset padding = self.BG_RECT_PADDING bg_rect_pos = center_pos - QPoint(padding, data_metrics.height() + padding) bg_rect_size = data_metrics + (QSize(padding, padding) * 2) bg_rect = QRect(bg_rect_pos, bg_rect_size) bg_rect_path = QPainterPath() radius = self.BG_RECT_CORNER_RADIUS bg_rect_path.addRoundedRect(QRectF(bg_rect), radius, radius, Qt.AbsoluteSize) painter.setPen(self.bg_rect_pen) painter.fillPath(bg_rect_path, self.bg_rect_fill) painter.drawPath(bg_rect_path) painter.setPen(self.text_pen) painter.drawText(center_pos, res.data)
def paint(self, painter, option, index): painter.save() comment = index.data(Qt.UserRole) fm = option.fontMetrics # size for render comment body_width = option.rect.width() - self._margin_h * 2 body_height = option.rect.height() - self._margin_v * 2 painter.translate( QPoint(option.rect.x() + self._margin_h, option.rect.y() + self._margin_v)) # draw comment author name painter.save() font = QFont() font.setBold(True) painter.setFont(font) name_rect = QRect(0, 0, body_width, self._name_height) painter.drawText(name_rect, Qt.AlignLeft, comment.user.name) painter.restore() # draw comment other metadata painter.save() metadata_rect = QRect(0, 0, body_width, self._name_height) text_list = [] if comment.time: dt = datetime.fromtimestamp(comment.time) text_list.append(dt.strftime('%Y-%m-%d %H:%M')) if comment.liked_count != -1: liked_count_text = human_readable_number_v1(comment.liked_count) text_list.append(f'♥ {liked_count_text}') text = ' | '.join(text_list) text_color = option.palette.color(QPalette.Text) text_color.setAlpha(100) pen = QPen() pen.setColor(text_color) painter.setPen(pen) if text: painter.drawText(metadata_rect, Qt.AlignRight, text) painter.restore() # draw comment content painter.save() name_height = self._name_height + self._name_content_margin painter.translate(QPoint(0, name_height)) content_height = self._get_text_height(fm, body_width, comment.content) content_rect = QRect(0, 0, body_width, content_height) painter.drawText(content_rect, Qt.TextWordWrap, comment.content) parent_comment = comment.parent if parent_comment is not None: p_margins = self._parent_comment_margins p_paddings = self._parent_comment_paddings text = f'{parent_comment.user_name}:{parent_comment.content}' p_width = body_width - p_margins.width p_height = self._get_text_height(fm, p_width, text) p_body_rect = QRect(p_margins.left, p_margins.top + content_height, p_width, p_height + p_paddings.height) p_content_rect = QRect(p_body_rect.x() + p_paddings.left, p_body_rect.y() + p_paddings.top, p_body_rect.width() - p_paddings.width, p_body_rect.height() - p_paddings.height) bg_color = option.palette.color(QPalette.Window) if bg_color.lightness() > 150: bg_color = bg_color.darker(100) else: bg_color = bg_color.lighter(100) painter.fillRect(p_body_rect, bg_color) painter.drawText(p_content_rect, Qt.TextWordWrap, text) painter.restore() # draw a dotted line under each row painter.save() painter.translate(QPoint(0, body_height + self._margin_v)) text_color = option.palette.color(QPalette.Text) if text_color.lightness() > 150: non_text_color = text_color.darker(140) else: non_text_color = text_color.lighter(150) non_text_color.setAlpha(30) painter.setPen(QPen(non_text_color, 1, Qt.DotLine)) painter.drawLine(QPoint(0, 0), QPoint(body_width, 0)) painter.restore() painter.restore()
class GraphicLine(QGraphicsLineItem): """ This class is a graphic line with an arrow which connects two blocks in the scene. Attributes ---------- origin : QGraphicsRectItem Origin rect of the line. destination : QGraphicsRectItem Destination rect of the line. scene : QGraphicsScene Current drawing scene. brush : QBrush Brush to draw the arrow. pen : QPen Pen to draw the arrow. arrow_head : QGraphicsPolygonItem Final arrow of the line. arrow_size : int Size of the head of the arrow. dim_label : QGraphicsTextItem Text showing the dimensions of the edge. is_valid : bool Flag monitoring whether the connection is consistent. Methods ---------- gen_endpoints(QRectF, QRectF) Returns the shortest connection between the two rects. draw_arrow() Draws the polygon for the arrow. set_valid(bool) Assign validity for this line. update_dims(tuple) Update the line dimensions. update_pos(QRectF) Update the line position given the new rect position. remove_self() Delete this line. """ def __init__(self, origin: QGraphicsRectItem, destination: QGraphicsRectItem, scene): super(GraphicLine, self).__init__() self.origin = origin self.destination = destination self.scene = scene # This flag confirms a legal connection self.is_valid = True # Get the four sides of the rects destination_lines = u.get_sides_of(self.destination.sceneBoundingRect()) origin_lines = u.get_sides_of(self.origin.sceneBoundingRect()) # Get the shortest edge between the two blocks self.setLine(self.gen_endpoints(origin_lines, destination_lines)) self.brush = QBrush(QColor(style.GREY_0)) self.pen = QPen(QColor(style.GREY_0)) self.pen.setWidth(4) self.pen.setCapStyle(Qt.RoundCap) self.pen.setJoinStyle(Qt.RoundJoin) self.setPen(self.pen) # Dimensions labels self.dim_label = QGraphicsTextItem() self.dim_label.setZValue(6) self.scene.addItem(self.dim_label) # Arrow head self.arrow_head = QGraphicsPolygonItem() self.arrow_head.setPen(self.pen) self.arrow_head.setBrush(self.brush) self.arrow_size = 15.0 self.draw_arrow() @staticmethod def gen_endpoints(origin_sides: dict, destination_sides: dict) -> QLineF: """ This method finds the shortest path between two rectangles. Parameters ---------- origin_sides : dict The dictionary {side_label: side_size} of the starting rect. destination_sides : dict The dictionary {side_label: side_size} of the ending rect. Returns ---------- QLineF The shortest line. """ # Init the line with the maximum possible value shortest_line = QLineF(-sys.maxsize / 2, -sys.maxsize / 2, sys.maxsize / 2, sys.maxsize / 2) for o_side, origin_side in origin_sides.items(): o_mid_x, o_mid_y = u.get_midpoint(o_side, origin_side) for d_side, destination_side in destination_sides.items(): d_mid_x, d_mid_y = u.get_midpoint(d_side, destination_side) # Update line line = QLineF(o_mid_x, o_mid_y, d_mid_x, d_mid_y) if line.length() < shortest_line.length(): shortest_line = line return shortest_line def draw_arrow(self) -> None: """ This method draws an arrow at the end of the line. """ polygon_arrow_head = QPolygonF() # Compute the arrow angle angle = math.acos(self.line().dx() / self.line().length()) angle = ((math.pi * 2) - angle) # Compute the direction where the arrow points (1 up, -1 down) arrow_direction = 1 if math.asin(self.line().dy() / self.line().length()) < 0: arrow_direction = -1 # First point of the arrow tail arrow_p1 = self.line().p2() - arrow_direction * QPointF( arrow_direction * math.sin(angle + math.pi / 2.5) * self.arrow_size, math.cos(angle + math.pi / 2.5) * self.arrow_size) # Second point of the arrow tail arrow_p2 = self.line().p2() - arrow_direction * QPointF( arrow_direction * math.sin(angle + math.pi - math.pi / 2.5) * self.arrow_size, math.cos(angle + math.pi - math.pi / 2.5) * self.arrow_size) # Third point is the line end polygon_arrow_head.append(self.line().p2()) polygon_arrow_head.append(arrow_p2) polygon_arrow_head.append(arrow_p1) # Add the arrow to the scene self.arrow_head.setZValue(1) self.arrow_head.setParentItem(self) self.arrow_head.setPolygon(polygon_arrow_head) def set_valid(self, valid: bool) -> None: """ This method changes the arrow style: if the connection is not valid the arrow becomes red, otherwise it remains grey with dimensions displayed. Parameters ---------- valid : bool New value for the legality flag. """ if valid: self.is_valid = True self.pen.setColor(QColor(style.GREY_0)) self.brush.setColor(QColor(style.GREY_0)) self.dim_label.setVisible(False) else: self.is_valid = False self.pen.setColor(QColor(style.RED_2)) self.brush.setColor(QColor(style.RED_2)) if self.scene.is_dim_visible: self.dim_label.setVisible(True) def update_dims(self, dims: tuple) -> None: """ This method updates the input & output dimensions. Parameters ---------- dims : tuple The new dimensions to update. """ self.dim_label.setHtml("<div style = 'background-color: " + style.RED_2 + "; color: white; font-family: consolas;'>" + str(dims) + "</div>") self.dim_label.setPos(self.line().center()) def update_pos(self, new_target: QRectF): """ This method updates the line as it origin or its destination has changed location. Parameters ---------- new_target : QRectF """ if new_target == self.destination: self.destination = new_target elif new_target == self.origin: self.origin = new_target # Get the four sides of the rects destination_lines = u.get_sides_of(self.destination.sceneBoundingRect()) origin_lines = u.get_sides_of(self.origin.sceneBoundingRect()) # Get the shortest edge between the two blocks self.setLine(self.gen_endpoints(origin_lines, destination_lines)) self.draw_arrow() self.dim_label.setPos(self.line().center()) def remove_self(self) -> None: """ The line is removed from the scene along with origin and destination pointers. """ self.scene.removeItem(self) self.scene.edges.remove(self) self.scene.removeItem(self.dim_label) self.origin = None self.destination = None
def setupLayers(self): layers = [] op = self.topLevelOperatorView ActionInfo = ShortcutManager.ActionInfo superpixels_ready = op.Superpixels.ready() with_training = op.TrainRandomForest.value # Superpixels -- Edge Labels if superpixels_ready and op.EdgeLabelsDict.ready() and with_training: edge_labels = op.EdgeLabelsDict.value layer = LabelableSegmentationEdgesLayer( createDataSource(op.Superpixels), self.edge_label_pen_table, edge_labels) layer.name = "Edge Labels" layer.visible = True layer.opacity = 1.0 self.update_labeled_edges() # Initialize layer.labelsChanged.connect(self._handle_edge_label_clicked) layer.contexts.append(self.create_prefetch_menu("Edge Labels")) layer.shortcutRegistration = ( "0", ActionInfo( "Edge Training Layers", "LabelVisibility", "Show/Hide Edge Labels", layer.toggleVisible, self.viewerControlWidget(), layer, ), ) layers.append(layer) del layer # Superpixels -- Edge Probabilities if superpixels_ready and op.EdgeProbabilitiesDict.ready( ) and with_training: layer = SegmentationEdgesLayer(createDataSource(op.Superpixels)) layer.name = "Edge Probabilities" # Name is hard-coded in multiple places: grep before changing. layer.visible = False layer.opacity = 1.0 self.update_probability_edges() # Initialize layer.contexts.append( self.create_prefetch_menu("Edge Probabilities")) layer.shortcutRegistration = ( "p", ActionInfo( "Edge Training Layers", "EdgePredictionsVisibility", "Show/Hide Edge Predictions", layer.toggleVisible, self.viewerControlWidget(), layer, ), ) layers.append(layer) del layer # Superpixels -- Edges if superpixels_ready: default_pen = QPen(SegmentationEdgesLayer.DEFAULT_PEN) default_pen.setColor(Qt.yellow) layer = SegmentationEdgesLayer(createDataSource(op.Superpixels), default_pen) layer.name = "Superpixel Edges" layer.visible = True layer.opacity = 1.0 layers.append(layer) del layer # Naive Segmentation if op.NaiveSegmentation.ready(): layer = self.createStandardLayerFromSlot(op.NaiveSegmentation) layer.name = "Naive Segmentation" layer.visible = False layer.opacity = 0.5 layer.shortcutRegistration = ( "n", ActionInfo( "Edge Training Layers", "NaiveSegmentationVisibility", "Show/Hide Naive Segmentation (shows output if classifier output is respected verbatim)", layer.toggleVisible, self.viewerControlWidget(), layer, ), ) layers.append(layer) del layer # Groundtruth if op.GroundtruthSegmentation.ready(): layer = self.createStandardLayerFromSlot( op.GroundtruthSegmentation) layer.name = "Groundtruth" layer.visible = False layer.opacity = 0.5 layer.shortcutRegistration = ( "g", ActionInfo( "Edge Training Layers", "GroundtruthVisibility", "Show/Hide Groundtruth", layer.toggleVisible, self.viewerControlWidget(), layer, ), ) layers.append(layer) del layer # Voxel data if op.VoxelData.ready(): layer = self._create_grayscale_layer_from_slot( op.VoxelData, op.VoxelData.meta.getTaggedShape()["c"]) layer.name = "Voxel Data" layer.visible = False layer.opacity = 1.0 layers.append(layer) del layer # Raw Data (grayscale) if op.RawData.ready(): layer = self.createStandardLayerFromSlot(op.RawData) layer.name = "Raw Data" layer.visible = True layer.opacity = 1.0 layers.append(layer) layer.shortcutRegistration = ( "i", ActionInfo( "Edge Training Layers", "Hide all but Raw", "Hide all but Raw", partial(self.toggle_show_raw, "Raw Data"), self.viewerControlWidget(), layer, ), ) del layer return layers
def __init__(self): super(GraphicsPathItem, self).__init__() pen = QPen() pen.setColor(Qt.black) pen.setWidth(10) self.setPen(pen)
class XYGraph(QWidget): def __init__(self, parent=None): super(XYGraph, self).__init__(parent) self.handleBrush = QBrush(QColor(140, 140, 140)) self.backgroundBrush = QBrush(QColor(180, 180, 180)) self.linePen = QPen(Qt.SolidLine) self.linePen.setColor(QColor(220, 220, 220)) self.linePen.setWidth(3) self.currentHandle = None self.dragStartPos = None self.setMinimumSize(300, 300) self.move(0, 0) self.handles = [Handle('H1', 165, 165, 50)] for handle in self.handles: self.positionlabel = QLabel(self) self.positionlabel.setStyleSheet(""" QLabel{ color:white; } """) self.positiontext = "%d, %d" % (handle.pos.x(), handle.pos.y()) self.positionlabel.setText(self.positiontext) self.positionlabel.move(handle.pos.x() - 20, handle.pos.y() - 5) handle.handleMoved.connect(self.updateLabel) #handle represented by a QPoint def updateLabel(self, handle): self.positiontext = "%d, %d" % (handle.x(), handle.y()) self.positionlabel.setText(self.positiontext) self.positionlabel.move(handle.x() - 20, handle.y() - 5) # This method gets called every time an Outline needs to draw itself # to the screen. def paintEvent(self, event): qp = QPainter(self) qp.setPen(self.linePen) qp.setBrush(self.backgroundBrush) qp.drawEllipse(50, 50, 230, 230) # draw an outline around the graph # qp.drawEllipse(self.rect()) qp.setBrush(self.handleBrush) lasthandle = None for handle in self.handles: qp.drawEllipse(handle.bounds()) if lasthandle != None: qp.drawLine(lasthandle.x(), lasthandle.y(), handle.x(), handle.y()) lasthandle = handle def mousePressEvent(self, event): mouseX = event.pos().x() mouseY = event.pos().y() # Check if the mouse is inside the bounds of a handle self.currentHandle = None for handle in self.handles: h = handle.bounds() if mouseX > h.left() and mouseX < h.right() and mouseY > h.top( ) and mouseY < h.bottom(): # mouse is inside this handle's bounding box print("Glide Location: " + self.positiontext) self.currentHandle = handle self.dragStartPos = QPoint(handle.x(), handle.y()) break def mouseMoveEvent(self, event): if self.currentHandle != None: w = self.width() h = self.height() mouse = event.pos() if mouse.x() > 50 and mouse.x() < w - 90 and mouse.y( ) > 50 and mouse.y() < h - 60: self.currentHandle.setPos(mouse) else: self.currentHandle.setPos(self.dragStartPos) self.dragStartPos = None self.currentHandle = None self.update() def mouseReleaseEvent(self, event): if self.currentHandle != None: self.currentHandle = None print("Glide Location: " + self.positiontext)
class StripChart(QWidget): """Permits display of a numerical quantitiy as well as a plot of its history.""" def __init__(self, ylim=[-1, 1], buffer_length=ccfg.plot_buffer_length, color=ccfg.plot_line_color, line_width=ccfg.plot_line_width, ytick_interval=None, print_function=lambda val: '%0.1e' % val, hlines=[0.0]): super(StripChart, self).__init__() self.layout = QVBoxLayout() self.lbl = QLabel() self.plot = QLabel() self.pixmap = QPixmap() self.buf = np.zeros(buffer_length) self.buffer_length = buffer_length self.buffer_current_index = 0 self.layout.addWidget(self.lbl) self.layout.addWidget(self.plot) self.setLayout(self.layout) self.x = np.arange(buffer_length) self.hlines = hlines self.data_y_max = ylim[1] self.data_y_min = ylim[0] if ytick_interval is not None: t0 = np.fix(float(self.data_y_min) / float(ytick_interval)) * ytick_interval t1 = np.fix(float(self.data_y_max) / float(ytick_interval)) * ytick_interval self.yticks = np.arange(t0, t1, ytick_interval) else: self.yticks = [] self.plot_width_px = ccfg.plot_width_px self.plot_height_px = ccfg.plot_height_px self.xtick0 = 0 self.xtick1 = ccfg.plot_xtick_length self.plot.setMinimumWidth(ccfg.plot_width_px) self.lbl.setMinimumWidth(ccfg.plot_width_px) self.xscale = float(ccfg.plot_width_px) / float(self.buffer_length - 1) # there's a slight penalty for drawing a 32 bit pixmap instead of an 8 # bit pixmap, but it dowsn't look like it really affects performance # so it's probably safe to make this false permit_only_gray_plots = False if permit_only_gray_plots: self.bmp = np.ones((ccfg.plot_height_px, ccfg.plot_width_px), dtype=np.uint8) * 255 bpl = int(self.bmp.nbytes / ccfg.plot_height_px) self.plot_background = QImage(self.bmp, ccfg.plot_width_px, ccfg.plot_height_px, bpl, QImage.Format_Indexed8) else: A = np.ones((ccfg.plot_height_px, ccfg.plot_width_px), dtype=np.uint32) * ccfg.plot_background_color[3] R = np.ones((ccfg.plot_height_px, ccfg.plot_width_px), dtype=np.uint32) * ccfg.plot_background_color[0] G = np.ones((ccfg.plot_height_px, ccfg.plot_width_px), dtype=np.uint32) * ccfg.plot_background_color[1] B = np.ones((ccfg.plot_height_px, ccfg.plot_width_px), dtype=np.uint32) * ccfg.plot_background_color[2] val = (A << 24 | R << 16 | G << 8 | B).flatten() bpl = int(val.nbytes / ccfg.plot_height_px) self.plot_background = QImage(val, ccfg.plot_width_px, ccfg.plot_height_px, bpl, QImage.Format_ARGB32) self.pixmap.convertFromImage(self.plot_background) self.lbl.setFixedHeight(ccfg.caption_height_px * 2) self.setMinimumWidth(ccfg.plot_width_px) self.setMinimumHeight(ccfg.plot_height_px + ccfg.caption_height_px * 2) self.print_function = print_function self.plot.setFrameShape(QFrame.Box) self.plot.setLineWidth(1) self.pen = QPen() self.pen.setColor(QColor(*color)) self.pen.setWidth(line_width) self.ytick_pen = QPen() self.ytick_pen.setColor(QColor(0, 0, 0, 255)) self.ytick_pen.setWidth(0.5) self.ytick_pen.setStyle(Qt.DotLine) self.xtick_pen = QPen() self.xtick_pen.setColor(QColor(0, 0, 0, 255)) self.xtick_pen.setWidth(2.0) self.xtick_pen.setStyle(Qt.SolidLine) self.hline_pen = QPen() self.hline_pen.setColor(QColor(0, 0, 0, 255)) self.hline_pen.setWidth(1.0) self.hline_pen.setStyle(Qt.SolidLine) self.painter = QPainter() def setText(self, new_text): self.lbl.setText(new_text) def setValue(self, new_value): self.buf[self.buffer_current_index] = new_value self.buffer_current_index = (self.buffer_current_index + 1) % self.buffer_length self.setText('%s\nsmoothed:%s' % (self.print_function(new_value), self.print_function(self.buf.mean()))) def scale_y(self, vec): h = self.plot.height() out = (h - (vec - self.data_y_min) / (self.data_y_max - self.data_y_min) * h) return out def setAlignment(self, new_alignment): self.lbl.setAlignment(new_alignment) def paintEvent(self, ev): pixmap = QPixmap() pixmap.convertFromImage(self.plot_background) self.painter.begin(pixmap) self.painter.setPen(self.ytick_pen) temp = self.scale_y( np.array( list(self.buf[self.buffer_current_index:]) + list(self.buf[:self.buffer_current_index]))) for yt in self.yticks: self.painter.drawLine( QLine(0, self.scale_y(yt), self.buffer_length * self.xscale, self.scale_y(yt))) self.painter.setPen(self.hline_pen) for hline in self.hlines: self.painter.drawLine( QLine(0, self.scale_y(hline), self.buffer_length * self.xscale, self.scale_y(hline))) self.painter.setPen(self.pen) for idx in range(self.buffer_length - 1): x1 = (idx) * self.xscale x2 = (idx + 1) * self.xscale y1 = temp[idx] y2 = temp[idx + 1] self.painter.drawLine(QLine(x1, y1, x2, y2)) interval = self.buffer_length // 10 interval = ccfg.plot_xtick_interval if idx % interval == 0: self.painter.setPen(self.xtick_pen) self.painter.drawLine( QLine((x1 - self.buffer_current_index * self.xscale) % (self.buffer_length * self.xscale), self.xtick0, (x1 - self.buffer_current_index * self.xscale) % (self.buffer_length * self.xscale), self.xtick1)) self.painter.setPen(self.pen) #if True:#20<self.buffer_current_index<80: # painter.drawEllipse(x1,y1,x2,y2) self.painter.end() self.plot.setPixmap(pixmap)
def paintEvent(self, objQPaintEvent): p = QPainter() p.begin(self) pen = QPen(Qt.black, 2, Qt.SolidLine) p.setPen(pen) p.drawLine(20, 15, 150, 15) pen.setStyle(Qt.DashLine) p.setPen(pen) p.drawLine(20, 35, 150, 35) pen.setStyle(Qt.DotLine) p.setPen(pen) p.drawLine(20, 55, 150, 55) pen.setStyle(Qt.DashDotLine) p.setPen(pen) p.drawLine(20, 75, 150, 75) pen.setStyle(Qt.DashDotDotLine) p.setPen(pen) p.drawLine(20, 95, 150, 95) pen.setStyle(Qt.CustomDashLine) pen.setDashPattern([1, 4, 5, 4]) p.setPen(pen) p.drawLine(20, 115, 150, 115) pen.setWidth(1) pen.setStyle(Qt.SolidLine) p.setPen(pen) brush = QBrush(Qt.SolidPattern) p.setBrush(brush) p.drawRect(180, 10, 40, 30) brush = QBrush(Qt.Dense5Pattern) p.setBrush(brush) p.drawRect(240, 10, 40, 30) brush = QBrush(Qt.Dense7Pattern) p.setBrush(brush) p.drawRect(300, 10, 40, 30) brush = QBrush(Qt.green, Qt.HorPattern) p.setBrush(brush) p.drawRect(180, 50, 40, 30) brush = QBrush(Qt.green, Qt.VerPattern) p.setBrush(brush) p.drawRect(240, 50, 40, 30) brush = QBrush(Qt.green, Qt.Dense6Pattern) brush = QBrush(Qt.green, Qt.CrossPattern) p.setBrush(brush) p.drawRect(300, 50, 40, 30) brush = QBrush(Qt.blue, Qt.BDiagPattern) p.setBrush(brush) p.drawRect(180, 90, 40, 30) brush = QBrush(Qt.blue, Qt.FDiagPattern) p.setBrush(brush) p.drawRect(240, 90, 40, 30) brush = QBrush(Qt.blue, Qt.DiagCrossPattern) p.setBrush(brush) p.drawRect(300, 90, 40, 30) g = QLinearGradient(180, 130, 220, 160) g.setColorAt(0, Qt.red) g.setColorAt(1, Qt.blue) brush = QBrush(g) p.setBrush(brush) p.drawRect(180, 130, 40, 30) g = QRadialGradient(260, 145, 20) g.setColorAt(0, Qt.red) g.setColorAt(0.5, Qt.yellow) g.setColorAt(1, Qt.blue) p.setBrush(g) p.drawRect(240, 130, 40, 30) g = QConicalGradient(320, 145, 0) g.setColorAt(0, Qt.red) g.setColorAt(0.4, Qt.yellow) g.setColorAt(0.8, Qt.blue) g.setColorAt(1, Qt.red) p.setBrush(g) p.drawRect(300, 130, 40, 30) brush = QBrush() brush.setTexture(QPixmap(":appres.img/texture.jpg")) p.setBrush(brush) pen.setColor(Qt.transparent) p.setPen(pen) p.drawRect(15, 130, 135, 35) p.end()
class fsScene(QGraphicsScene): """ Class for viewing and editing a flowsheet. """ # Mouse Modes MODE_SELECT = 1 MODE_ADDNODE = 2 MODE_ADDEDGE = 3 ITEM_NONE = 0 ITEM_NODE = 1 ITEM_EDGE = 2 def __init__(self, parent=None): """ Initialize the flowsheet display """ super(fsScene, self).__init__(parent) # Location of mouse events and whether the mouse button is down self.mouseDown = False self.pressX = 0.0 self.pressY = 0.0 self.releaseX = 0.0 self.releaseY = 0.0 # self.minorGrid = 20 # Minor grid spacing self.majorGrid = 100 # Major grid spacing self.xMaxGrid = 800 # Extent of grid area up x self.xMinGrid = -800 # Extent of grid area lo x self.yMaxGrid = 600 # Extent of grid area up y self.yMinGrid = -600 # Extent of grid area lo y self.nodeSize = 20 # size of node self.edgeArrowSize = 16 # size of the edge arrows self.actNodeSize = 25 # size of an active node self.mode = self.MODE_SELECT # Mouse mode self.p = parent # Parent class self.node1 = None # Node 1 for drawing edges self.node2 = None # Node 2 for drawing edges self.selectedNodes = [] # Set of selected nodes self.selectedEdges = [] # Set of selected edges self.majorGridPen = None # Pen for major grids self.minorGridPen = None # Pen for minor grids self.edgePen = None # Pen for edges self.tearEdgePen = None # Pen for tear edges self.nodePen = None # Pen for nodes self.activeNodePen = None # Pen for active node self.selectionPen = None # Pen for node selection markers self.eSelectionPen = None # Pen for edge selection markers # # Line styles self.lcMajorGrid = QColor(255, 190, 240) # minor grid color self.lcMinorGrid = QColor(190, 240, 255) # major grid color self.ltGrid = QtCore.Qt.DashLine # grid line type self.lwMinorGrid = 1 # grid line width self.lwMajorGrid = 1 # # self.lcEdge = QColor(0, 50, 200) self.ltEdge = QtCore.Qt.SolidLine self.lwEdge = 2 self.lcTear = QColor(100, 200, 255) self.ltTear = QtCore.Qt.SolidLine # self.lcNode = QColor(0, 0, 0) self.ltNode = QtCore.Qt.SolidLine self.lwNode = 2 self.lcActNode = QColor(0, 0, 0) # self.lcSelect = QColor(0, 255, 0) self.ltSelect = QtCore.Qt.SolidLine self.lwSelect = 4 self.lwEdgeSelect = 10 # # Set font self.font = None self.fontSize = 12 # # Set Brushes self.nodeBrush = None self.actNodeBrush = None # self.fcNode = QColor(128, 128, 128) self.fcActNode = QColor(128, 250, 128) self.fpNode = QtCore.Qt.SolidPattern self.fpActNode = QtCore.Qt.SolidPattern # self.edgeArrowBrush = None self.fcEdgeArrow = QColor(0, 50, 200) self.fpEdgeArrow = QtCore.Qt.SolidPattern # self.whiteBrush = None self.fcWB = QColor(240, 240, 240) self.fpWB = QtCore.Qt.SolidPattern # self.loadPens() # setup pens, brushes, and font def loadPens(self): # Create pens self.majorGridPen = QPen() self.minorGridPen = QPen() self.edgePen = QPen() self.tearEdgePen = QPen() self.nodePen = QPen() self.activeNodePen = QPen() self.selectionPen = QPen() # Set color self.majorGridPen.setColor(self.lcMajorGrid) self.minorGridPen.setColor(self.lcMinorGrid) self.edgePen.setColor(self.lcEdge) self.tearEdgePen.setColor(self.lcTear) self.nodePen.setColor(self.lcNode) self.activeNodePen.setColor(self.lcActNode) self.selectionPen.setColor(self.lcSelect) # set line style self.majorGridPen.setStyle(self.ltGrid) self.minorGridPen.setStyle(self.ltGrid) self.edgePen.setStyle(self.ltEdge) self.tearEdgePen.setStyle(self.ltTear) self.nodePen.setStyle(self.ltNode) self.activeNodePen.setStyle(self.ltNode) self.selectionPen.setStyle(self.ltSelect) # set line width self.majorGridPen.setWidth(self.lwMajorGrid) self.minorGridPen.setWidth(self.lwMinorGrid) self.edgePen.setWidth(self.lwEdge) self.tearEdgePen.setWidth(self.lwEdge) self.nodePen.setWidth(self.lwNode) self.activeNodePen.setWidth(self.lwNode) self.selectionPen.setWidth(self.lwSelect) # Set edge selection pen self.eSelectionPen = QPen(self.selectionPen) self.eSelectionPen.setWidth(self.lwEdgeSelect) # Set font self.font = QFont() self.font.setPixelSize(self.fontSize) # set up brushes self.nodeBrush = QBrush() self.actNodeBrush = QBrush() self.edgeArrowBrush = QBrush() self.whiteBrush = QBrush() # self.nodeBrush.setColor(self.fcNode) self.actNodeBrush.setColor(self.fcActNode) self.edgeArrowBrush.setColor(self.fcEdgeArrow) self.whiteBrush.setColor(self.fcWB) # self.nodeBrush.setStyle(self.fpNode) self.actNodeBrush.setStyle(self.fpActNode) self.edgeArrowBrush.setStyle(self.fpEdgeArrow) self.whiteBrush.setStyle(self.fpWB) def drawGrid(self): """ Draw the grid for the drawing area """ # Add vertical minor grids path = QPainterPath() minLoc = self.xMinGrid + self.minorGrid maxLoc = self.xMaxGrid gStep = self.minorGrid for i in range(minLoc, maxLoc, gStep): path.moveTo(i, self.yMinGrid) path.lineTo(i, self.yMaxGrid) self.addPath(path, self.minorGridPen) # Add horizontal minor grids path = QPainterPath() for i in range(minLoc, maxLoc, gStep): path.moveTo(self.xMinGrid, i) path.lineTo(self.xMaxGrid, i) self.addPath(path, self.minorGridPen) # Add vertical minor grids path = QPainterPath() minLoc = self.xMinGrid maxLoc = self.xMaxGrid gStep = self.majorGrid for i in range(minLoc, maxLoc, gStep): path.moveTo(i, self.yMinGrid) path.lineTo(i, self.yMaxGrid) self.addPath(path, self.majorGridPen) # Add vertical minor grids path = QPainterPath() for i in range(minLoc, maxLoc, gStep): path.moveTo(self.xMinGrid, i) path.lineTo(self.xMaxGrid, i) self.addPath(path, self.majorGridPen) def addTextCenteredOn(self, x, y, text): """ Add text vertically and horizontally centered on (x, y) """ text = self.addText(text, self.font) text.setPos( x - text.boundingRect().width() / 2.0, y - text.boundingRect().height() / 2.0, ) def drawNode(self, x, y, nodeName, nodeType): """ Draw a node centered at x,y. Text lines are centered under the node for the node name and node type --Args-- x: x coordinate of node y: y coordinate of node nodeName: text for the first line under the node nodeType: text for the second line under the node """ # draw a square centered on x,y path = QPainterPath() path.addRect( x - self.nodeSize / 2.0, y - self.nodeSize / 2.0, self.nodeSize, self.nodeSize, ) # If the node is selected draw it highlighted else draw it normal if nodeName in self.selectedNodes: gitem = self.addPath(path, self.selectionPen, self.nodeBrush) else: gitem = self.addPath(path, self.nodePen, self.nodeBrush) # Store some data about the node, so that if you click on it # we can determine what you clicked on gitem.setData(1, nodeName) # The name of the node gitem.setData(2, "node") # the fact that it is a node # Draw text labels self.addTextCenteredOn( x, y + self.nodeSize / 2 + self.fontSize / 2 + 4, nodeName ) self.addTextCenteredOn(x, y + self.nodeSize / 2 + self.fontSize + 16, nodeType) def drawEdge(self, x1, y1, x2, y2, index, curve, tear=False): """ Draw an edge from x1, y1 to x2, y2. Edges connect two nodes --Args-- index: the edge index curve: distance from center of straight edge to a point on curved edge (can be positive or negitive. Used to keep edges from overlapping. tear: if true draw in tear edge style """ # determine if edge conntects a node to itself. if abs(x1 - x2) < 0.01 and abs(y1 - y2) < 0.01: path = QPainterPath() curve = curve * 2 path.addEllipse(x1, y1 - curve / 2.0, curve, curve) if tear: gi = self.addPath(path, self.edgePen) else: gi = self.addPath(path, self.tearEdgePen) else: # mid point of the edge if it is a straight line xmid = (x1 + x2) / 2.0 ymid = (y1 + y2) / 2.0 # get the angle of the edge and the angle perpendicular ang = math.atan2((y2 - y1), (x2 - x1)) ang_perp = math.atan2((x1 - x2), (y2 - y1)) # calculate the mid point of the curved edge xcurve = xmid + curve * math.cos(ang_perp) ycurve = ymid + curve * math.sin(ang_perp) # calculate control point for drawing quaratic curve xcontrol = 2 * xcurve - xmid ycontrol = 2 * ycurve - ymid # draw Edge path = QPainterPath() path.moveTo(x1, y1) path.quadTo(xcontrol, ycontrol, x2, y2) p2 = QPainterPathStroker() path = p2.createStroke(path) # if edge is selected draw it highlighted if index in self.selectedEdges: self.addPath(path, self.eSelectionPen) # if edge is a tear draw it tear style else draw it normal if tear: gi = self.addPath(path, self.tearEdgePen) else: gi = self.addPath(path, self.edgePen) # Add data to edge so if seleted we can determine that it # is an edge and which edge it is. gi.setData(1, index) gi.setData(2, "edge") # Draw the arrow path = QPainterPath() xs = xcurve + self.edgeArrowSize * math.cos(ang) ys = ycurve + self.edgeArrowSize * math.sin(ang) path.moveTo(xs, ys) path.lineTo( xs - self.edgeArrowSize * math.cos(ang) + self.edgeArrowSize / 2.0 * math.cos(ang_perp), ys - self.edgeArrowSize * math.sin(ang) + self.edgeArrowSize / 2.0 * math.sin(ang_perp), ) path.lineTo( xs - self.edgeArrowSize * math.cos(ang) - self.edgeArrowSize / 2.0 * math.cos(ang_perp), ys - self.edgeArrowSize * math.sin(ang) - self.edgeArrowSize / 2.0 * math.sin(ang_perp), ) path.lineTo(xs, ys) gi = self.addPath(path, self.edgePen, self.edgeArrowBrush) # Add data so selecting the arrow in like selecting the edge gi.setData(1, index) gi.setData(2, "edge") def nearestGrid(self, x, y): """ Find the nearest minor grid to a point. """ xg = round(x / self.minorGrid) * self.minorGrid yg = round(y / self.minorGrid) * self.minorGrid return xg, yg def deleteSelected(self): """ Delete the selected nodes and edges then redraw the flowsheet """ self.p.dat.flowsheet.deleteEdges(self.selectedEdges) self.selectedEdges = [] self.p.dat.flowsheet.deleteNodes(self.selectedNodes) self.selectedNodes = [] self.p.noneSelectedEmit() self.p.createScene() def mouseMoveEvent(self, evnt): """ If the mouse button is held down move selected nodes """ # if mouse button is down check if you want to move nodes if not evnt.buttons() == QtCore.Qt.LeftButton: return if self.mode != self.MODE_SELECT: return dx = evnt.scenePos().x() - self.pressX dy = evnt.scenePos().y() - self.pressY for i, node in enumerate(self.selectedNodes): x = self.ipos[i][0] + dx y = self.ipos[i][1] + dy x, y = self.nearestGrid(x, y) # snap to minor grids self.p.dat.flowsheet.nodes[node].x = x self.p.dat.flowsheet.nodes[node].y = y self.p.createScene() self.p.updateFSPos.emit() # update the flowsheet and node editor def mousePressEvent( self, evnt, dbg_x=None, dbg_y=None, dbg_mod=None, dbg_name=None ): """ The mouse was clicked on the flowsheet editor window. Check what was selected on the mouse mode and do something. """ # Get the location of the mouse event if evnt is None: mod = dbg_mod x = dbg_x y = dbg_y else: mod = self.parent().parent().parent().app.keyboardModifiers() x = evnt.scenePos().x() y = evnt.scenePos().y() self.pressX = x self.pressY = y # Check if there is an object that was clicked on s_item = self.itemAt(x, y, self.parent().transform()) if s_item is not None: itemIndex = s_item.data(1) itemType = s_item.data(2) else: itemType = None itemIndex = None # Selection Mode select nodes or edges holding shift allows # you to select multiple nodels and edges. if self.mode == self.MODE_SELECT: if mod != QtCore.Qt.SHIFT: self.selectedEdges = [] self.selectedNodes = [] if itemType == "edge": self.selectedEdges.append(itemIndex) self.p.edgeSelectedEmit(self.selectedEdges[-1]) elif itemType == "node": self.selectedNodes.append(itemIndex) self.p.nodeSelectedEmit(self.selectedNodes[-1]) elif mod != QtCore.Qt.SHIFT: # don't clear the selection if shift is down this # prevents you form selecting a bunch of stuff and # mistakenly clearing it all because you missed what # you were aiming for. self.selectedEdges = [] self.selectedNodes = [] self.p.noneSelectedEmit() self.p.createScene() # Add node mode elif self.mode == self.MODE_ADDNODE: xg, yg = self.nearestGrid(x, y) if dbg_name is None: name, ok = QInputDialog.getText( self.p, "Node Name", "New node name:", QLineEdit.Normal ) else: ok = True name = dbg_name if ok and name != "": if name in self.p.dat.flowsheet.nodes: QMessageBox.warning( self.p, "Invalid Name", "That node name is already being used." ) return if " " in name: QMessageBox.warning( self.p, "Invalid Name", "Node name should not contain any spaces.", ) return self.p.dat.flowsheet.addNode(name, xg, yg, 0) self.p.updateEdgeEditEmit() self.p.nodeSelectedEmit(name) self.p.createScene() # Add Edge mode elif self.mode == self.MODE_ADDEDGE: if self.selectedNodes == []: if itemType == "node": self.node1 = self.selectedNodes.append(itemIndex) else: if len(self.selectedNodes) == 1 and itemType == "node": self.selectedNodes.append(itemIndex) if self.selectedNodes[0] != self.selectedNodes[1]: ind = self.p.dat.flowsheet.addEdge( self.selectedNodes[0], self.selectedNodes[1] ) self.p.updateEdgeEditEmit() self.selectedNodes = [] else: self.selectedNodes = [] self.p.createScene() # original location of selected nodes for moving self.ipos = [(0, 0)] * len(self.selectedNodes) for i, node in enumerate(self.selectedNodes): self.ipos[i] = ( self.p.dat.flowsheet.nodes[node].x, self.p.dat.flowsheet.nodes[node].y, )
class ChartWidget: def __init__(self, parent, home_button, zoom_button, repaint_callback): self.parent = parent self.home_button = home_button self.zoom_button = zoom_button self.repaint_callback = repaint_callback self.parent.wheelEvent = self.wheelEvent self.parent_resizeEvent = self.parent.resizeEvent self.parent.resizeEvent = self.resizeEvent self.parent.mousePressEvent = self.mousePressEvent self.parent.mouseMoveEvent = self.mouseMoveEvent self.parent.mouseReleaseEvent = self.mouseReleaseEvent self.pages = [] self.last_lines = [] self.x_scale = 1 self.y_scale = 1 self.origin_offset = [0, 0] self.data_margin = 70 self.axis_margin = [50, 30] self.axis_pen = QPen() self.axis_pen.setWidth(1) self.axis_pen.setColor(QColor(50, 50, 50)) self.grid_pen = QPen() self.grid_pen.setWidth(1) self.grid_pen.setColor(QColor(50, 50, 50)) self.sub_grid_pen = QPen() self.sub_grid_pen.setWidth(1) self.sub_grid_pen.setColor(QColor(200, 200, 200)) self.sub_grid_pen.setStyle(Qt.DotLine) self.should_repaint = True self.last_axis_pixmap = None self.last_lines_pixmap = None self.last_tracker_pixmap = None self.last_important_mouse_pos = None self.current_mouse_pos = None self.last_size = self.parent.size() self.quick_drag_offset = [0, 0] self.mouse_mode = None self.zoom_button.clicked.connect(self.handle_zoom_button) self.home_button.clicked.connect(self.fit_data) def fit_data(self): if self.last_lines: min_x = min([min(line.get_data()[0]) for line in self.last_lines]) max_x = max([max(line.get_data()[0]) for line in self.last_lines]) min_y = min([min(line.get_data()[1]) for line in self.last_lines]) max_y = max([max(line.get_data()[1]) for line in self.last_lines]) self.x_range = max_x - min_x self.y_range = max_y - min_y self.x_scale = (self.parent.width() - self.data_margin * 2) / ( 2.5**math.ceil(math.log(self.x_range))) self.y_scale = self.x_scale # (self.parent.height() - self.data_margin * 2) / (2.5 ** math.ceil(math.log(self.y_range))) self.axis_margin[0] = math.ceil(math.log(max(max_x, abs(min_x)))) + 3 * 14 # self.axis_margin[1] = math.ceil(math.log(max(max_y, abs(min_y)))) + 3 * 14 self.origin_offset = [(min_x + self.x_range / 2) * -self.x_scale, (min_y + self.y_range / 2) * self.y_scale] else: self.x_range = 10 self.y_range = 10 self.origin_offset = [0, 0] self.x_scale = 1 self.y_scale = 1 self.repaint() def handle_zoom_button(self): self.mouse_mode = 'zoom' def zoom_to_rect(self, pt1, pt2): w = pt2.x() - pt1.x() h = pt2.y() - pt1.y() cx = pt1.x() + w / 2 cy = pt1.y() + h / 2 self.zoom([cx, cy], self.parent.width() / w, self.parent.height() / h, [self.parent.width() / 2, self.parent.height() / 2]) def repaint(self, update_lines=True): for line in self.last_lines: line.set_pixmap_to_update() self.repaint_callback(update_lines, True) def wheelEvent(self, event): pos = event.pos() val = -event.angleDelta().y() + event.angleDelta().x() scroll_speed = 1.0 + abs(val) / 100 if val < 0: scroll_speed = 1 / scroll_speed # self.zoom([self.parent.width()/2, self.parent.height()/2], scroll_speed, scroll_speed) self.zoom([pos.x(), pos.y()], scroll_speed, scroll_speed) self.repaint() def zoom(self, center_point, x_scale_diff=1, y_scale_diff=1, new_coords=None): if new_coords is None: new_coords = center_point center_val = self.calc_val_point(center_point) self.x_scale *= x_scale_diff self.y_scale *= y_scale_diff self.origin_offset = [ -(center_val[0] * self.x_scale - new_coords[0] + self.parent.width() / 2), center_val[1] * self.y_scale + new_coords[1] - self.parent.height() / 2 ] def mousePressEvent(self, event): self.last_important_mouse_pos = event.pos() if self.mouse_mode is None: if QApplication.keyboardModifiers() & Qt.ShiftModifier: self.mouse_mode = 'zoom' else: self.quick_drag_offset = [0, 0] self.mouse_mode = 'drag' def mouseMoveEvent(self, event): self.current_mouse_pos = event.pos() if self.mouse_mode == 'drag' and self.last_important_mouse_pos is not None: self.quick_drag_offset[0] += event.pos().x( ) - self.last_important_mouse_pos.x() self.quick_drag_offset[1] += event.pos().y( ) - self.last_important_mouse_pos.y() self.origin_offset[0] += event.pos().x( ) - self.last_important_mouse_pos.x() self.origin_offset[1] += event.pos().y( ) - self.last_important_mouse_pos.y() self.last_important_mouse_pos = event.pos() # self.repaint() self.paint_lines(self.last_lines, quick=True) else: self.paint_lines(self.last_lines, False, False) def mouseReleaseEvent(self, event): if self.mouse_mode == 'zoom': self.zoom_to_rect(self.last_important_mouse_pos, event.pos()) self.last_important_mouse_pos = None self.mouse_mode = None self.repaint() def resizeEvent(self, event): size = self.parent.size() self.origin_offset[0] = self.origin_offset[0] * size.width( ) / self.last_size.width() self.origin_offset[1] = self.origin_offset[1] * size.height( ) / self.last_size.height() self.last_size = size self.parent_resizeEvent(event) self.repaint() # https://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/ def ccw(self, A, B, C): return (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]) def intersect(self, A, B, C, D): return self.ccw(A, C, D) != self.ccw(B, C, D) and self.ccw( A, B, C) != self.ccw(A, B, D) def draw_axis_pixmap(self): axis_pixmap = QPixmap(self.parent.size()) axis_pixmap.fill(QColor(255, 255, 255, 0)) qpainter = QPainter() qpainter.begin(axis_pixmap) origin = self.calc_gui_point([0, 0]) axis_origin = [ max(min(origin[0], self.parent.width() - self.axis_margin[0]), self.axis_margin[0]), max(min(origin[1], self.parent.height() - self.axis_margin[1]), self.axis_margin[1]) ] qpainter.setPen(self.grid_pen) x_tick_width = 10**( math.floor(math.log10(self.parent.width() / self.x_scale) + 0.3)) / 2 * self.x_scale y_tick_width = 10**( math.floor(math.log10(self.parent.height() / self.y_scale) + 0.3)) / 2 * self.y_scale for i in range( int( max(self.parent.height(), self.parent.width()) // x_tick_width + 1)): x = i * x_tick_width + origin[0] % x_tick_width y = i * y_tick_width + origin[1] % y_tick_width x_sub_ticks = 5 y_sub_ticks = 5 qpainter.setPen(self.sub_grid_pen) for j in range(-x_sub_ticks, 10, 10 // x_sub_ticks): sub_x = x + j * x_tick_width / x_sub_ticks qpainter.drawLine(sub_x, 0, sub_x, self.parent.height()) # X Grid for j in range(-y_sub_ticks, 10, 10 // y_sub_ticks): sub_y = y + j * y_tick_width / y_sub_ticks qpainter.drawLine(0, sub_y, self.parent.width(), sub_y) # Y Grid qpainter.setPen(self.grid_pen) qpainter.drawLine(x, 0, x, self.parent.height()) # X Grid x_label = self.calc_val_point([x, origin[1]])[0] qpainter.drawText( QRect(x + 5, axis_origin[1] + 5, self.axis_margin[0], 15), Qt.AlignLeft, str(round(x_label, 2))) qpainter.drawLine(0, y, self.parent.width(), y) # Y Grid y_label = self.calc_val_point([origin[0], y])[1] qpainter.drawText( QRect(axis_origin[0] - self.axis_margin[0], y, self.axis_margin[0], 15), Qt.AlignRight, str(round(y_label, 2))) if self.mouse_mode == 'zoom' and self.last_important_mouse_pos is not None and self.current_mouse_pos is not None: pt = self.last_important_mouse_pos pt2 = self.current_mouse_pos qpainter.drawRect(pt.x(), pt.y(), pt2.x() - pt.x(), pt2.y() - pt.y()) qpainter.end() return axis_pixmap def draw_tracker_pixmap(self, cursor_pos): tracker_pixmap = QPixmap(self.parent.size()) tracker_pixmap.fill(QColor(255, 255, 255, 0)) qpainter = QPainter() qpainter.begin(tracker_pixmap) origin = self.calc_gui_point([0, 0]) axis_origin = [ max(min(origin[0], self.parent.width() - self.axis_margin[0]), self.axis_margin[0]), max(min(origin[1], self.parent.height() - self.axis_margin[1]), self.axis_margin[1]) ] qpainter.setPen(self.axis_pen) pnt = self.calc_val_point([cursor_pos.x(), cursor_pos.y()]) x_label = str(round(pnt[0], 2)) y_label = str(round(pnt[1], 2)) str_rect = QRect(cursor_pos.x() + 5, axis_origin[1], qpainter.fontMetrics().width(x_label), 25) g_rect = QRect(str_rect.x() - 30, str_rect.y(), 30, str_rect.height()) gradient = QLinearGradient(QPoint(g_rect.right(), g_rect.center().y()), QPoint(g_rect.left(), g_rect.center().y())) gradient.setColorAt(0, QColor(255, 255, 255)) gradient.setColorAt(1, QColor(255, 255, 255, 0)) qpainter.fillRect(g_rect, gradient) g_rect = QRect(str_rect.right(), str_rect.y(), 30, str_rect.height()) gradient = QLinearGradient(QPoint(g_rect.left(), g_rect.center().y()), QPoint(g_rect.right(), g_rect.center().y())) gradient.setColorAt(0, QColor(255, 255, 255)) gradient.setColorAt(1, QColor(255, 255, 255, 0)) qpainter.fillRect(g_rect, gradient) qpainter.fillRect(str_rect, QColor(255, 255, 255)) qpainter.drawText(str_rect, Qt.AlignLeft | Qt.AlignCenter, x_label) qpainter.drawLine(cursor_pos.x(), axis_origin[1], cursor_pos.x(), axis_origin[1] + 10) label_width = qpainter.fontMetrics().width(y_label) str_rect = QRect(axis_origin[0] - label_width - 1, cursor_pos.y() + 1, label_width, 15) g_rect = QRect(str_rect.x(), str_rect.y() - 10, str_rect.width(), 10) gradient = QLinearGradient( QPoint(g_rect.center().x(), g_rect.bottom()), QPoint(g_rect.center().x(), g_rect.top())) gradient.setColorAt(0, QColor(255, 255, 255)) gradient.setColorAt(1, QColor(255, 255, 255, 0)) qpainter.fillRect(g_rect, gradient) g_rect = QRect(str_rect.x(), str_rect.bottom(), str_rect.width(), 10) gradient = QLinearGradient( QPoint(g_rect.center().x(), g_rect.top()), QPoint(g_rect.center().x(), g_rect.bottom())) gradient.setColorAt(0, QColor(255, 255, 255)) gradient.setColorAt(1, QColor(255, 255, 255, 0)) qpainter.fillRect(g_rect, gradient) qpainter.fillRect(str_rect, QColor(255, 255, 255)) qpainter.drawText(str_rect, Qt.AlignRight | Qt.AlignCenter, y_label) qpainter.drawLine(axis_origin[0], cursor_pos.y(), axis_origin[0] - 10, cursor_pos.y()) qpainter.end() return tracker_pixmap # @profilefunc def get_lines_pixmap(self, lines): pixmap = QPixmap(self.parent.size()) pixmap.fill(QColor(255, 255, 255, 0)) qp = QPainter() qp.begin(pixmap) for line in lines: qp.drawPixmap( QPoint(0, 0), line.get_pixmap(self.parent.size(), self.calc_gui_point)) qp.end() return pixmap def paint_lines(self, lines, update_lines=True, update_axis=True, update_tracker=True, quick=False): st = time() pixmap = QPixmap(self.parent.size()) pixmap.fill(QColor(255, 255, 255)) qp = QPainter() qp.begin(pixmap) self.last_lines = lines qp.setRenderHints(QPainter.SmoothPixmapTransform | QPainter.Antialiasing) if quick and self.last_lines_pixmap is not None: qp.fillRect(QRect(0, 0, self.parent.width(), self.parent.height()), QColor("#fafafa")) qp.drawPixmap(QPoint(*self.quick_drag_offset), self.last_lines_pixmap) else: # if update_lines or not self.last_lines_pixmap: self.last_lines_pixmap = self.get_lines_pixmap(lines) qp.drawPixmap(QPoint(0, 0), self.last_lines_pixmap) if update_axis or not self.last_axis_pixmap: self.last_axis_pixmap = self.draw_axis_pixmap() qp.drawPixmap(QPoint(0, 0), self.last_axis_pixmap) cursor_pos = self.parent.mapFromGlobal(QCursor.pos()) if cursor_pos.x() > 0 and cursor_pos.x() < self.parent.width( ) and cursor_pos.y() > 0 and cursor_pos.y() < self.parent.height(): self.last_tracker_pixmap = self.draw_tracker_pixmap(cursor_pos) qp.drawPixmap(QPoint(0, 0), self.last_tracker_pixmap) qp.end() self.parent.setPixmap(pixmap) def is_point_visible(self, pt): return (0 <= pt[0] <= self.parent.width()) and (0 <= pt[1] <= self.parent.height()) def is_segment_visible(self, pt, pt2, simple=True): return self.is_point_visible(pt) or self.is_point_visible(pt2) or \ (not simple and (self.intersect(pt, pt2, [0, 0], [self.parent.width(), 0]) or \ self.intersect(pt, pt2, [0, 0], [0, self.parent.height()]) or \ self.intersect(pt, pt2, [0, self.parent.height()], [self.parent.width(), self.parent.height()]) or \ self.intersect(pt, pt2, [self.parent.width(), 0], [self.parent.width(), self.parent.height()]))) def calc_gui_point(self, pnt): x = pnt[0] * self.x_scale + self.parent.width( ) / 2 + self.origin_offset[0] y = self.parent.height() / 2 - (pnt[1] * self.y_scale) + self.origin_offset[1] return x, y def calc_val_point(self, pnt): x = (pnt[0] - self.origin_offset[0] - self.parent.width() / 2) / self.x_scale y = (pnt[1] - self.origin_offset[1] - self.parent.height() / 2) / -self.y_scale return x, y
def _newPen(self, color): newPen = QPen() newColor = QColor(color) newPen.setColor(newColor) return newPen
class HorizonApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.initScene() def initScene(self): self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene(0, 0, 1033, 579) self.graphicsView.setScene(self.scene) self.scene.setBackgroundBrush(Qt.white) self.pen = QPen() self.pen.setWidth(1) self.pen.setColor(Qt.black) self.displayButton.clicked.connect(self.prepareForDrawing) def FloatHorizon(self, borders_x, x_step, borders_z, z_step, f, angles): global top, bottom # Инициализируем начальными значениями массивы горизонтов. top = [0] * WIDTH # Верхний. bottom = [HEIGHT] * WIDTH # Нижний. x_start = borders_x[0] x_end = borders_x[1] z_start = borders_z[0] z_end = borders_z[1] x_left, y_left = -1, -1 x_right, y_right = -1, -1 z = z_end while z >= z_start - z_step / 2: x_prev = x_start y_prev = f(x_start, z) x_prev, y_prev = transform(x_prev, y_prev, z, angles) flag_prev = Visible(x_prev, y_prev) # x_left, y_left = Side(x_prev, y_prev, x_left, y_left, self) x = x_start while x <= x_end + x_step / 2: y_curr = f(x, z) x_curr, y_curr = transform(x, y_curr, z, angles) # Проверка видимости текущей точки. flag_curr = Visible(x_curr, y_curr) # Равенство флагов означает, что обе точки находятся # Либо выше верхнего горизонта, либо ниже нижнего, # Либо обе невидимы. if flag_curr == flag_prev: # Если текущая вершина выше верхнего горизонта # Или ниже нижнего (Предыдущая такая же) if flag_curr != 0: # Значит отображаем отрезок от предыдущей до текущей. self.scene.addLine(x_prev, y_prev, x_curr, y_curr) Horizon(x_prev, y_prev, x_curr, y_curr) # flag_curr == 0 означает, что и flag_prev == 0, # А значит часть от flag_curr до flag_prev невидима. Ничего не делаем. else: # Если видимость изменилась, то # Вычисляем пересечение. if flag_curr == 0: if flag_prev == 1: # Сегмент "входит" в верхний горизонт. # Ищем пересечение с верхним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, top) else: # flag_prev == -1 (flag_prev нулю (0) не может быть равен, т.к. мы обработали это выше). # Сегмент "входит" в нижний горизонт. # Ищем пересечение с нижним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, bottom) # Отображаем сегмент, от предыдущий точки, до пересечения. self.scene.addLine(x_prev, y_prev, xi, yi) Horizon(x_prev, y_prev, xi, yi) else: if flag_curr == 1: if flag_prev == 0: # Сегмент "выходит" из верхнего горизонта. # Ищем пересечение с верхним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, top) # Отображаем сегмент от пересечения до текущей точки. self.scene.addLine(xi, yi, x_curr, y_curr) Horizon(xi, yi, x_curr, y_curr) else: # flag_prev == -1 # Сегмент начинается с точки, ниже нижнего горизонта # И заканчивается в точке выше верхнего горизонта. # Нужно искать 2 пересечения. # Первое пересечение с нижним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, bottom) # Отображаем сегмент от предыдущей то пересечения. self.scene.addLine(x_prev, y_prev, xi, yi) Horizon(x_prev, y_prev, xi, yi) # Второе пересечение с верхним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, top) # Отображаем сегмент от пересечения до текущей. self.scene.addLine(xi, yi, x_curr, y_curr) Horizon(xi, yi, x_curr, y_curr) else: # flag_curr == -1 if flag_prev == 0: # Сегмент "выходит" из нижнего горизонта. # Ищем пересечение с нижним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, bottom) self.scene.addLine(xi, yi, x_curr, y_curr) Horizon(xi, yi, x_curr, y_curr) else: # Сегмент начинается с точки, выше верхнего горизонта # И заканчивается в точке ниже нижнего горизонта. # Нужно искать 2 пересечения. # Первое пересечение с верхним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, top) # Отображаем сегмент от предыдущей до пересечения. self.scene.addLine(x_prev, y_prev, xi, yi) Horizon(x_prev, y_prev, xi, yi) # Ищем второе пересечение с нижним горизонтом. xi, yi = Intersection(x_prev, y_prev, x_curr, y_curr, bottom) # Отображаем сегмент от пересечения до текущей. self.scene.addLine(xi, yi, x_curr, y_curr) Horizon(xi, yi, x_curr, y_curr) x_prev, y_prev = x_curr, y_curr flag_prev = flag_curr x += x_step x_right, y_right = Side(x_prev, y_prev, x_right, y_right, self) z -= z_step def prepareForDrawing(self): self.scene.clear() bordersForX = [self.xFrom.value(), self.xTo.value()] stepForX = self.xStep.value() bordersForX = [self.zFrom.value(), self.zTo.value()] stepForZ = self.zStep.value() angles = [ self.rotateX.value(), self.rotateY.value(), self.rotateZ.value() ] function = checkFunc(self) self.FloatHorizon(bordersForX, stepForX, bordersForX, stepForZ, function, angles)
class Font(Node): BORDER_MODE_2 = [(-1, -1), (1, 1)] BORDER_MODE_4 = [(-1, -1), (1, -1), (-1, 1), (1, 1)] BORDER_MODE_8 = [(-1, -1), (0, 1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)] def __init__(self, event: dict, name='', font_size=11): super().__init__(event) self._font = QFont(name, font_size) self._font_size = font_size self._rect = Rect(event, h=font_size) self._text = '' self._flags = 0 self._w = 0 self._h = 0 self._cut = False self._border_pen = QPen(QColor(0, 0, 0)) self._border_mode = None @property def font_size(self): return self._font_size @property def rect(self): return self._rect @property def size(self): return self._w, self._h @property def draw_size(self): return self._rect.size def set_font_size(self, size, px=False): self._font_size = size if px: self._font_size = px_to_pt(px) def set_draw_size(self, w=None, h=None): self._cut = w is None and h is None if self._cut: self._rect.set_size(*self.size) else: self._rect.set_size(w, h) def set_text(self, text: str): px = pt_to_px(self._font_size) self._text = text self._w = max( [count_text_size(line) * px for line in text.splitlines()]) * 1.125 self._h = px * (text.count('\n') + 1) * 1.125 if not self._cut: self._rect.set_size(*self.size) def set_position(self, x=None, y=None): super().set_position(x, y) self._rect.set_position(x, y) def set_border_color(self, color: QColor): self._border_pen.setColor(color) def set_border_mode(self, mode): self._border_mode = mode def set_color(self, color: QColor): super().set_color(color) self._rect.set_color(color) def set_flags(self, flags): self._flags = flags def set_scale_available(self, b: bool): super().set_scale_available(b) self._rect.set_scale_available(b) def draw(self): super().draw() p = self.painter p.setFont(self._font) s = self.scale self._font.setPointSize(self._font_size * s) self.draw_border() if s == 1: p.drawText(self._rect.rect, 0, self._text) else: size = [int(i * s) for i in self._rect] p.drawText(*size, 0, self._text) def draw_border(self): p = self.painter s = self.scale pen = p.pen() p.setPen(self._border_pen) if self._border_mode is not None: p.setPen(self._border_pen) x, y = self.position for ox, oy in self._border_mode: size = [x + ox, y + oy, *self.rect.size] size = [int(i * s) for i in size] p.drawText(*size, 0, self._text) p.setPen(pen)
def draw(self): if len(self.line_xs) == 0: return to_plot_x = [] to_plot_y = [] for k in self.line_map.keys(): if self.line_active[k]: to_plot_x.append(self.line_xs[self.line_map[k]]) to_plot_y.append(self.line_ys[self.line_map[k]]) if len(to_plot_y) == 0: return if self.force_xmax is None: self.max_x = np.amax(to_plot_x) else: self.max_x = self.force_xmax if self.force_ymax is None: self.max_y = np.amax(to_plot_y) else: self.max_y = self.force_ymax x_ceil, x_step = self.get_ceil(self.max_x) y_ceil, y_step = self.get_ceil(self.max_y) self.x_ceil = x_ceil self.y_ceil = y_ceil xs = np.multiply(np.divide(self.line_xs, x_ceil), self.base_line_x) ys = np.multiply(np.divide(self.line_ys, y_ceil), self.base_line_y) if self.sub_sampling > 4: for i in range(ys.shape[0]): wf = np.clip(self.sub_sampling, 0, ys.shape[1] - 1) if wf % 2 == 0: wf -= 1 ys[i] = savgol_filter(ys[i], wf, 3) p = QPen() p.setWidth(0.1) to_plot = [] for k in self.line_map.keys(): if self.line_active[k]: to_plot.append(self.line_map[k]) for j in range(xs.shape[0]): if j not in to_plot: continue p.setColor(self.line_cols[j]) path = None for i in range(xs.shape[1]): x = xs[j][i] y = self.base_line_y - ys[j][i] if i == 0: path = QPainterPath(QPointF(x, y)) else: path.lineTo(QPointF(x, y)) if path is not None: path = self.scene().addPath(path, p) self.lines.append(path) p.setColor(QColor(255,255,255,200)) n_legend = len(list(self.line_map.keys())) legend_box = self.scene().addRect(QRectF(self.base_line_x + 50, 50, 200, 30 * n_legend), p) font = QFont() font.setPointSize(10) c = 1 for name in sorted(list(self.line_map.keys())): if not self.line_active[name]: continue y = 50 + ((c * 30) - 15) p.setColor(self.line_cols[self.line_map[name]]) lbl = self.scene().addText(name, font) lbl.setPos(self.base_line_x + 55, y - lbl.boundingRect().height() / 2) lbl.setDefaultTextColor(QColor(255,255,255,255)) self.scene().addLine(self.base_line_x + 55 + lbl.boundingRect().width() + 5, y, self.base_line_x + 245, y, p) c += 1
def drawGlyphPoints( painter, glyph, scale, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawBluesMarkers=True, onCurveColor=None, onCurveSmoothColor=None, offCurveColor=None, otherColor=None, backgroundColor=None, ): """ Draws a Glyph_ *glyph*’s points. .. _Glyph: http://ts-defcon.readthedocs.org/en/ufo3/objects/glyph.html """ if onCurveColor is None: onCurveColor = defaultColor("glyphOnCurvePoints") if onCurveSmoothColor is None: onCurveSmoothColor = defaultColor("glyphOnCurveSmoothPoints") if offCurveColor is None: offCurveColor = defaultColor("glyphOffCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") bluesMarkerColor = defaultColor("glyphBluesMarker") notchColor = defaultColor("glyphContourStroke").lighter(200) # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # blue zones markers if drawBluesMarkers and drawOnCurves: font = glyph.font blues = [] if font.info.postscriptBlueValues: blues += font.info.postscriptBlueValues if font.info.postscriptOtherBlues: blues += font.info.postscriptOtherBlues if blues: blues_ = set(blues) size = 13 * scale snapSize = 17 * scale painter.save() pen = painter.pen() pen.setColor(QColor(255, 255, 255, 125)) pen.setWidth(0) painter.setPen(pen) for point in outlineData["onCurvePoints"]: x, y = point["point"] # TODO: we could add a non-overlapping interval tree special # cased for borders for yMin, yMax in zip(blues[::2], blues[1::2]): if not (y >= yMin and y <= yMax): continue # if yMin > 0 and y == yMin or yMin <= 0 and y == yMax: if y in blues_: path = lozengePath(x, y, snapSize) else: path = ellipsePath(x, y, size) painter.fillPath(path, bluesMarkerColor) painter.drawPath(path) painter.restore() # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for x1, y1, x2, y2 in outlineData["bezierHandles"]: drawLine(painter, x1, y1, x2, y2) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: size = 6.5 * scale smoothSize = 8 * scale startSize = 7 * scale loneStartSize = 12 * scale painter.save() notchPath = QPainterPath() path = QPainterPath() smoothPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) # notch if "smoothAngle" in point: angle = point["smoothAngle"] t = Identity.rotate(angle) x1, y1 = t.transformPoint((-1.35 * scale, 0)) x2, y2 = -x1, -y1 notchPath.moveTo(x1 + x, y1 + y) notchPath.lineTo(x2 + x, y2 + y) # points if drawStartPoints and "startPointAngle" in point: angle = point["startPointAngle"] if angle is not None: pointPath = trianglePath(x, y, startSize, angle) else: pointPath = ellipsePath(x, y, loneStartSize) elif point["smooth"]: pointPath = ellipsePath(x, y, smoothSize) else: pointPath = rectanglePath(x, y, size) # store the path if point["smooth"]: smoothPath.addPath(pointPath) else: path.addPath(pointPath) # stroke pen = QPen(onCurveColor) pen.setWidthF(1.2 * scale) painter.setPen(pen) painter.drawPath(path) pen.setColor(onCurveSmoothColor) painter.setPen(pen) painter.drawPath(smoothPath) # notch pen.setColor(notchColor) pen.setWidth(0) painter.setPen(pen) painter.drawPath(notchPath) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # points offSize = 4.25 * scale path = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] pointPath = ellipsePath(x, y, offSize) path.addPath(pointPath) pen = QPen(offCurveColor) pen.setWidthF(2.5 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.restore() # coordinates if drawCoordinates: painter.save() painter.setPen(otherColor) font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 6 * scale x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
def paintEvent( self, e): #Fonction qui va "peindre" la fenetre, c'est l'affichage painter = QPainter(self) pen = QPen() #Un rectangle de la taille de la fenetre pour un fond noir couleurFond = QColor(0, 0, 0) painter.fillRect(0, 0, self.width(), self.height(), couleurFond) colorTour = QColor(0, 150, 255) pen = QPen() pen.setColor(colorTour) painter.setPen(pen) #conditions pour afficher le cercle décrivant la trajectoire des planètes if self.zoom <= 8: painter.drawEllipse(self.pos1x, self.pos1y, self.rayon1, self.rayon1) if self.zoom <= 7: painter.drawEllipse(self.pos2x, self.pos2y, self.rayon2, self.rayon2) if self.zoom <= 6: painter.drawEllipse(self.pos3x, self.pos3y, self.rayon3, self.rayon3) if self.zoom <= 5: painter.drawEllipse(self.pos4x, self.pos4y, self.rayon4, self.rayon4) if self.zoom <= 4: painter.drawEllipse(self.pos5x, self.pos5y, self.rayon5, self.rayon5) if self.zoom <= 3: painter.drawEllipse(self.pos6x, self.pos6y, self.rayon6, self.rayon6) if self.zoom <= 2: painter.drawEllipse( self.pos7x, self.pos7y, self.rayon7, self.rayon7) if self.zoom <= 1: painter.drawEllipse( self.pos8x, self.pos8y, self.rayon8, self.rayon8) #affichage du soleil au centre color = QColor(255, 255, 0) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse(self.width() / 2 - self.bd_s / 2, self.height() / 2 - self.bd_s / 2 + 15, self.bd_s, self.bd_s) #un enchainement de conditions ( if ) afin de pouvoir maitriser le zoom en supprimant l'affichage des planètes qui ne sont plus à l'écran if self.zoom <= 8: color = QColor(218, 65, 32) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon1 / 2) * math.cos(self.angle1), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon1 / 2) * math.sin(self.angle1), self.bd_p, self.bd_p) if self.zoom <= 7: color = QColor(0, 255, 255) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon2 / 2) * math.cos(self.angle2), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon2 / 2) * math.sin(self.angle2), self.bd_p, self.bd_p) if self.zoom <= 6: color = QColor(255, 228, 181) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon3 / 2) * math.cos(self.angle3), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon3 / 2) * math.sin(self.angle3), self.bd_p, self.bd_p) if self.zoom <= 5: color = QColor(222, 184, 135) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon4 / 2) * math.cos(self.angle4), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon4 / 2) * math.sin(self.angle4), self.bd_p, self.bd_p) if self.zoom <= 4: color = QColor(178, 34, 34) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon5 / 2) * math.cos(self.angle5), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon5 / 2) * math.sin(self.angle5), self.bd_p, self.bd_p) if self.zoom <= 3: color = QColor(0, 0, 255) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon6 / 2) * math.cos(self.angle6), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon6 / 2) * math.sin(self.angle6), self.bd_p, self.bd_p) if self.zoom <= 2: color = QColor(255, 140, 0) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon7 / 2) * math.cos(self.angle7), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon7 / 2) * math.sin(self.angle7), self.bd_p, self.bd_p) if self.zoom <= 1: color = QColor(100, 149, 237) pen.setColor(color) painter.setPen(pen) brush = QBrush() brush.setColor(color) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) painter.drawEllipse( self.width() / 2 - (self.bd_p / 2) + (self.rayon8 / 2) * math.cos(self.angle8), self.height() / 2 - (self.bd_p / 2) + 15 + (self.rayon8 / 2) * math.sin(self.angle8), self.bd_p, self.bd_p) #histoire de dates, pas encore utile ''' painter.setPen(pen) font = painter.font() font.setPointSize(self.width() / 50) painter.setFont(font) painter.drawText(self.width()/1.5, self.height() / 12, str(self.dateJour)) painter.drawText(self.width()/1.3 + self.width()/50 * 8, self.height() / 12, str(self.dateAnnée)) if self.dateMois == 10 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'JANVIER') if self.dateMois == 2 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'FEVRIER') if self.dateMois == 3 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'MARS') if self.dateMois == 4 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'AVRIL') if self.dateMois == 5 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'MAI') if self.dateMois == 6 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'JUIN') if self.dateMois == 7 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'JUILLET') if self.dateMois == 8 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'AOUT') if self.dateMois == 1 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'SEPTEMBRE') if self.dateMois == 10 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'OCTOBRE') if self.dateMois == 11 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'NOVEMBRE') if self.dateMois == 12 : painter.drawText(self.width()/1.4 + self.width()/50*2, self.height() / 12, 'DECEMBRE') ''' if -0.5 < self.angle3 / 2 * pi < 0.5: self.dateAnnée += 1
def __createChart(self): ##创建图表 chart = QChart() #创建 Chart ## chart.setTitle("简单函数曲线") chart.legend().setVisible(True) self.chartView.setChart(chart) #Chart添加到chartView pen=QPen() pen.setWidth(2) ##========LineSeries折线 和 ScatterSeries散点 seriesLine = QLineSeries() seriesLine.setName("LineSeries折线") seriesLine.setPointsVisible(False) #数据点不可见 pen.setColor(Qt.red) seriesLine.setPen(pen) seriesLine.hovered.connect(self.do_series_hovered) #信号 hovered seriesLine.clicked.connect(self.do_series_clicked) #信号 clicked chart.addSeries(seriesLine) #添加到chart seriesLinePoint = QScatterSeries() #散点序列 seriesLinePoint.setName("ScatterSeries散点") shape=QScatterSeries.MarkerShapeCircle #MarkerShapeRectangle seriesLinePoint.setMarkerShape(shape) #散点形状,只有2种 seriesLinePoint.setBorderColor(Qt.yellow) seriesLinePoint.setBrush(QBrush(Qt.red)) seriesLinePoint.setMarkerSize(10) #散点大小 seriesLinePoint.hovered.connect(self.do_series_hovered) #信号 hovered seriesLinePoint.clicked.connect(self.do_series_clicked) #信号 clicked chart.addSeries(seriesLinePoint) #添加到chart ##======== SplineSeries 曲线和 QScatterSeries 散点 seriesSpLine = QSplineSeries() seriesSpLine.setName("SplineSeries曲线") seriesSpLine.setPointsVisible(False) #数据点不可见 pen.setColor(Qt.blue) seriesSpLine.setPen(pen) seriesSpLine.hovered.connect(self.do_series_hovered) #信号 hovered seriesSpLine.clicked.connect(self.do_series_clicked) #信号 clicked seriesSpPoint = QScatterSeries() #散点序列 seriesSpPoint.setName("QScatterSeries") shape=QScatterSeries.MarkerShapeRectangle #MarkerShapeCircle seriesSpPoint.setMarkerShape(shape) #散点形状,只有2种 seriesSpPoint.setBorderColor(Qt.green) seriesSpPoint.setBrush(QBrush(Qt.blue)) seriesSpPoint.setMarkerSize(10) #散点大小 seriesSpPoint.hovered.connect(self.do_series_hovered) #信号 hovered seriesSpPoint.clicked.connect(self.do_series_clicked) #信号 clicked chart.addSeries(seriesSpLine) chart.addSeries(seriesSpPoint) ## 创建缺省坐标轴 chart.createDefaultAxes() #创建缺省坐标轴并与序列关联 chart.axisX().setTitleText("time(secs)") chart.axisX().setRange(0,10) chart.axisX().applyNiceNumbers() chart.axisY().setTitleText("value") chart.axisY().setRange(-2,2) chart.axisY().applyNiceNumbers() for marker in chart.legend().markers(): #QLegendMarker类型列表 marker.clicked.connect(self.do_LegendMarkerClicked)