class PlotLine(QGraphicsLineItem): def __init__(self, view, p1, p2): super().__init__() self.p1 = p1 self.p2 = p2 self.cls = p1.cls self.view = view self.highlighted = False self.lineWidth = 1 self.lineWidthHighl = 4 self._pen = None self._penHighl = None self.updateColor() self.updateLine() view.plotPaletteChanged.connect(self.updateColor) view.axisChanged.connect(self.updateLine) def updateColor(self): color = self.view.getClassColor(self.cls) self._pen = QPen(color) self._pen.setWidth(self.lineWidth) colorHighl = QColor(color) colorHighl.setAlpha(255) self._penHighl = QPen(colorHighl) self._penHighl.setWidth(self.lineWidthHighl) def updateLine(self): p1 = self.p1.mapToScene(self.p1.boundingRect().center()) p2 = self.p2.mapToScene(self.p2.boundingRect().center()) self.setLine(QLineF(p1, p2)) def paint(self, qp: QPainter, option: QStyleOptionGraphicsItem, widget: QWidget = None): self.setPen(self._pen if not self.highlighted else self._penHighl) super().paint(qp, option, widget)
def draw_indicator(indicator: int): pixmap = QPixmap(24, 24) painter = QPainter(pixmap) w, h = pixmap.width(), pixmap.height() painter.fillRect(0, 0, w, h, QBrush((QColor(0, 0, 200, 255)))) pen = QPen(QColor("white")) pen.setWidth(2) painter.setPen(pen) font = util.get_monospace_font() font.setBold(True) font.setPixelSize(16) painter.setFont(font) f = QFontMetrics(painter.font()) indicator_str = str(indicator) if indicator < 10 else "+" fw = f.width(indicator_str) fh = f.height() painter.drawText(math.ceil(w / 2 - fw / 2), math.ceil(h / 2 + fh / 4), indicator_str) painter.end() return QIcon(pixmap)
def debug(self, painter): #Paint path painter.setBrush(QBrush(QColor(0, 0, 0, 25))) pen = QPen(QColor(255, 0, 0, 100)) pen.setWidth(1) painter.setPen(pen) #Curve area path = QPainterPath() path.addPath(self.shape()) painter.drawPath(path) #Curve controll points painter.drawEllipse(self.curvePoint1, 2, 2) painter.drawEllipse(self.curvePoint2, 2, 2) #Draw area painter.setPen(QPen(QColor(0, 255, 0, 100))) painter.setBrush(QBrush(QColor(0, 0, 0, 15))) path2 = QPainterPath() rect = self.boundingRect() path2.addRect(rect) painter.drawPath(path2) #Middel point painter.setPen(QPen(QColor(0, 0, 255, 100))) painter.drawEllipse(self.midPoint, 2, 2)
def updateFilledCircle(self, s): size = s * self.zoom pixmap = QPixmap(self.width(), self.height()) pixmap.fill(Qt.transparent) #painter filled ellipse p = QPalette() painter = QPainter() painter.begin(pixmap) painter.setRenderHint(QPainter.Antialiasing) brush = QBrush(p.link().color()) painter.setBrush(brush) painter.setOpacity(0.4) painter.drawEllipse(QRect(old_div(self.width(),2) - old_div(size,2), old_div(self.height(),2) - old_div(size,2), size, size)) painter.end() #painter ellipse 2 painter2 = QPainter() painter2.begin(pixmap) painter2.setRenderHint(QPainter.Antialiasing) pen2 = QPen(Qt.green) pen2.setWidth(1) painter2.setPen(pen2) painter2.drawEllipse(QRect(old_div(self.width(),2) - old_div(size,2), old_div(self.height(),2) - old_div(size,2), size, size)) painter2.end() self.ellipseLabel.setPixmap(QPixmap(pixmap)) self.lastSize = s
def __init__(self, strand_item: PathStrandItemT, cap_type: str, # low, high, dual is_drawn5to3: bool): """The parent should be a StrandItem.""" super(EndpointItem, self).__init__(strand_item.virtualHelixItem()) self._strand_item = strand_item self._getActiveTool = strand_item._getActiveTool self.cap_type = cap_type self._low_drag_bound = None self._high_drag_bound = None self._mod_item = None self._isdrawn5to3 = is_drawn5to3 self._initCapSpecificState(is_drawn5to3) p = QPen() p.setCosmetic(True) self.setPen(p) # for easier mouseclick self._click_area = cA = QGraphicsRectItem(_DEFAULT_RECT, self) self._click_area.setAcceptHoverEvents(True) cA.hoverMoveEvent = self.hoverMoveEvent cA.mousePressEvent = self.mousePressEvent cA.mouseMoveEvent = self.mouseMoveEvent cA.setPen(_NO_PEN) self.setFlag(QGraphicsItem.ItemIsSelectable)
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 paintEvent(self, event): # Check whether this orb is enhanced if type(self.parent) == Board: enh = self.parent.enhanced[self.position] else: enh = False painter = QPainter(self) painter.drawPixmap(event.rect().adjusted(2,2,-2,-2), self.pixmap()) w = event.rect().width() if enh: path = QPainterPath() pen = QPen() pen.setWidth(1); pen.setBrush(Qt.white) brush = QBrush(Qt.yellow) font = QFont() font.setPointSize(20) font.setWeight(QFont.Black) path.addText(event.rect().x()+w-15,event.rect().y()+w-5,font,'+') painter.setPen(pen) painter.setBrush(brush) painter.setFont(font) painter.drawPath(path)
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 paintEvent(self, ev): color = self.palette().color(QPalette.Highlight) painter = QPainter(self) # Filled rectangle. painter.setClipRect(self.rect()) color.setAlpha(50) painter.fillRect(self.rect().adjusted(2,2,-2,-2), color) # Thin rectangle outside. color.setAlpha(150) painter.setPen(color) painter.drawRect(self.rect().adjusted(0,0,-1,-1)) # Pseudo-handles at the corners and sides color.setAlpha(100) pen = QPen(color) pen.setWidth(8) painter.setPen(pen) painter.setBackgroundMode(Qt.OpaqueMode) # Clip at 4 corners region = QRegion(QRect(0,0,20,20)) region += QRect(self.rect().width()-20, 0, 20, 20) region += QRect(self.rect().width()-20, self.rect().height()-20, 20, 20) region += QRect(0, self.rect().height()-20, 20, 20) # Clip middles region += QRect(0, self.rect().height() // 2 - 10, self.rect().width(), 20) region += QRect(self.rect().width() // 2 - 10, 0, 20, self.rect().height()) # Draw thicker rectangles, clipped at corners and sides. painter.setClipRegion(region) painter.drawRect(self.rect())
def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen)
def addWP(self, wp): if wp.command in [mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT, mavutil.mavlink.MAV_CMD_NAV_LOITER_TURNS, mavutil.mavlink.MAV_CMD_NAV_LOITER_TIME, mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM, mavutil.mavlink.MAV_CMD_NAV_LAND]: #point rad = self.__wp_diameter * 0.5 ellipse = QGraphicsEllipseItem(wp.y - rad, -wp.x - rad, self.__wp_diameter, self.__wp_diameter, self.__mission_layer) ellipse.setBrush(QBrush(QColor(255, 255, 255))) e_pen = QPen(QColor(255, 255, 255)) e_pen.setWidth(0) ellipse.setPen(e_pen) self.__mission_layer.addToGroup(ellipse) #label label = QGraphicsTextItem(str(wp.seq), self.__mission_layer) label.setZValue(2) label.setDefaultTextColor(Qt.white) label.setPos(wp.y + rad, -wp.x - rad) label.setScale(0.00002) #bit hacky -- really should scale based on #current zoom, but I'm in a hurry. self.__mission_layer.addToGroup(label) label.show()
def __init__(self, part_item, model_virtual_helix, viewroot): super(VirtualHelixItem, self).__init__(part_item.proxy()) self._part_item = part_item self._model_virtual_helix = model_virtual_helix self._viewroot = viewroot self._getActiveTool = part_item._getActiveTool self._controller = VirtualHelixItemController(self, model_virtual_helix) self._handle = VirtualHelixHandleItem(model_virtual_helix, part_item, viewroot) self._last_strand_set = None self._last_idx = None self._scaffoldBackground = None self.setFlag(QGraphicsItem.ItemUsesExtendedStyleOption) self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.setBrush(QBrush(Qt.NoBrush)) view = viewroot.scene().views()[0] view.levelOfDetailChangedSignal.connect(self.levelOfDetailChangedSlot) shouldShowDetails = view.shouldShowDetails() pen = QPen(styles.MINOR_GRID_STROKE, styles.MINOR_GRID_STROKE_WIDTH) pen.setCosmetic(shouldShowDetails) self.setPen(pen) self.refreshPath() self.setAcceptHoverEvents(True) # for pathtools self.setZValue(styles.ZPATHHELIX)
def drawGrid(self, painter, rect, gridColor): tileWidth = self.map().tileWidth() tileHeight = self.map().tileHeight() r = rect.toAlignedRect() r.adjust(-tileWidth / 2, -tileHeight / 2, tileWidth / 2, tileHeight / 2) startX = int(max(0.0, self.screenToTileCoords_(r.topLeft()).x())) startY = int(max(0.0, self.screenToTileCoords_(r.topRight()).y())) endX = int(min(self.map().width(), self.screenToTileCoords_(r.bottomRight()).x())) endY = int(min(self.map().height(), self.screenToTileCoords_(r.bottomLeft()).y())) gridColor.setAlpha(128) gridPen = QPen(gridColor) gridPen.setCosmetic(True) _x = QVector() _x.append(2) _x.append(2) gridPen.setDashPattern(_x) painter.setPen(gridPen) for y in range(startY, endY+1): start = self.tileToScreenCoords(startX, y) end = self.tileToScreenCoords(endX, y) painter.drawLine(start, end) for x in range(startX, endX+1): start = self.tileToScreenCoords(x, startY) end = self.tileToScreenCoords(x, endY) painter.drawLine(start, end)
def paintEvent(self, pe): super().paintEvent(pe) if (self.mRedrawMapImage): self.renderMapToImage() self.mRedrawMapImage = False if (self.mMapImage.isNull() or self.mImageRect.isEmpty()): return p = QPainter(self) p.setRenderHints(QPainter.SmoothPixmapTransform) backgroundColor = QColor(Qt.darkGray) if (self.mMapDocument and self.mMapDocument.map().backgroundColor().isValid()): backgroundColor = self.mMapDocument.map().backgroundColor() p.setBrush(backgroundColor) p.setPen(Qt.NoPen) p.drawRect(self.contentsRect()) p.drawImage(self.mImageRect, self.mMapImage) viewRect = self.viewportRect() p.setBrush(Qt.NoBrush) p.setPen(QColor(0, 0, 0, 128)) p.translate(1, 1) p.drawRect(viewRect) outLinePen = QPen(QColor(255, 0, 0), 2) outLinePen.setJoinStyle(Qt.MiterJoin) p.translate(-1, -1) p.setPen(outLinePen) p.drawRect(viewRect) p.end()
def __init__(self, name: str): super(LGPdfWriter, self).__init__() if not self.touch(name): raise PermissionError("Cannot open "+name) self.setOutputFileName(name) self.setOutputFormat(self.PdfFormat) self.setPageSize(self.A4) #self.setPageSizeMM(QSizeF(2100,2970)) self._rot = QPen(QColor(255,0,0)) self._blau = QPen(QColor(0,0,255)) self._grün = QPen(QColor(0,255,0)) self._schwarz = QPen(QColor(0,0,0)) self._weis = QPen(QColor(255, 255, 255)) self._fg = self._schwarz self._fg.setWidth(3) self._bg = QPen(QColor(0,0,0)) self._bg.setWidth(3) self._fgs = QPen(QColor(190, 190, 190)) self._fgs.setWidth(3) self._sg = QColor(180, 20, 51) self._painter = QPainter(self) self._painter.setBackground(QColor(255, 255, 255)) self._font = QFont("Arial", 20, QFont.Bold, True)
def add_color_scale(self): x_init = self.position[0] + self.margin + self.width y_init = self.position[1] + self.margin square_size = 20 text_title = QGraphicsSimpleTextItem("clearance") text_title.setPos(x_init, y_init - square_size) self.addToGroup(text_title) for i in range(10): x = x_init y = y_init + 9 * square_size - i * square_size rect = QGraphicsRectItem(x, y, square_size, square_size) pen = QPen() pen.setWidth(0.01) value = (float(i)/9 * (self.vertical_clearance_max - self.vertical_clearance_min)) + self.vertical_clearance_min color = self.color_interpolation.get_interpolation_from_value(value) brush = QBrush(color) rect.setPen(pen) rect.setBrush(brush) self.addToGroup(rect) if i == 0: text_start = QGraphicsSimpleTextItem("%.2f m" % float(self.vertical_clearance_min)) text_start.setPos(x + square_size + 5, y) self.addToGroup(text_start) if i == 9: text_end = QGraphicsSimpleTextItem("%.2f m" % float(self.vertical_clearance_max)) text_end.setPos(x + square_size + 5, y) self.addToGroup(text_end) else: value = self.vertical_clearance_min + (self.vertical_clearance_max-self.vertical_clearance_min) * i/9 text = QGraphicsSimpleTextItem("%.2f m" % value) text.setPos(x + square_size + 5, y) self.addToGroup(text)
def paint (self, painter, style, widget): if widget is not self.treeview.viewport(): pen = QPen(FlPalette.light) pen.setCosmetic(True) painter.setPen(pen) painter.setBrush(QBrush()) painter.drawRect(self.boundingRect())
def drawPixmapFor3d(self): self.pixmap3d = QPixmap(self.itemWidth, self.itemHeight) self.pixmap3d.fill(Qt.transparent) painter = QPainter() painter.begin(self.pixmap3d) painter.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(2) painter.setPen(pen) painter.setBrush(QBrush(QColor(220, 220, 220))) top = [QPoint(5, 10), QPoint(self.itemWidth - 10, 10), QPoint(self.itemWidth - 5, 5), QPoint(10, 5), QPoint(5, 10)] painter.drawConvexPolygon(*top) left = [QPoint(self.itemWidth - 10, 10), QPoint(self.itemWidth - 10, self.itemHeight - 5), QPoint(self.itemWidth - 5, self.itemHeight - 10), QPoint(self.itemWidth - 5, 5), QPoint(self.itemWidth - 10, 10)] painter.drawConvexPolygon(*left) painter.setBrush(QBrush()) painter.drawRect(QRect(5, 10, self.itemWidth - 15, self.itemHeight - 15)) painter.drawText(QRect(5, 10, self.itemWidth - 15, self.itemHeight - 15), Qt.AlignCenter, '3D') painter.end()
def __init__(self, map, *args): super().__init__(*args) self.map = map self.position = map.center self.providers = deque([ 'osm', 'stamen-terrain', 'stamen-toner-lite', 'stamen-toner', 'stamen-watercolor', 'ms-aerial', 'ms-hybrid', 'ms-road', 'bluemarble', ]) self.refresh_map = asyncio.Event() scene = QGraphicsScene() self.scene = scene self.setScene(scene) self.map_layer = QGraphicsPixmapItem() scene.addItem(self.map_layer) self.circle = QGraphicsEllipseItem(0, 0, 20, 20) pen = QPen(QColor(255, 0, 0, 128)) pen.setWidth(2) self.circle.setPen(pen) scene.addItem(self.circle) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
def paint(self, painter, option, widget=None): """QGraphicsRectItem virtual """ # TODO LH Is there a way to clip to overlapping # QAbstractGraphicsItems with a larger zorder # TODO LH Get pixmap without tight coupling to scene if not self.has_mouse(): painter.drawPixmap(self.boundingRect(), self.scene().pixmap, self.sceneBoundingRect()) with painter_state(painter): outline_colour, fill_colour = self.colours # Cosmetic pens "...draw strokes that have a constant width # regardless of any transformations applied to the QPainter they are # used with." pen = QPen(outline_colour, self.BOX_WIDTH, Qt.SolidLine) pen.setCosmetic(True) painter.setPen(pen) r = self.boundingRect() painter.drawRect(r) if fill_colour: painter.fillRect(r, fill_colour)
def updateColor(self): color = self.view.getClassColor(self.cls) self._pen = QPen(color) self._pen.setWidth(self.lineWidth) colorHighl = QColor(color) colorHighl.setAlpha(255) self._penHighl = QPen(colorHighl) self._penHighl.setWidth(self.lineWidthHighl)
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 paint (self, painter, option, widget): # print 'paint' # print self.po # draw background every time boundRect = self.boundingRect() rightEnd = boundRect.right() leftEnd = boundRect.left() # print 'rightEnd',rightEnd # print 'leftEnd',leftEnd gridNum = int(math.floor(rightEnd / self.gridGap)) # print 'gridNum',gridNum # get grid line 100 frame gap width/frame * 100 for i in range (0,gridNum+1): x = i*self.gridGap painter.drawLine(x, 0, x, 30) # draw x axis every time # if labeling, increase rectangle if (self.isLabeling) : # get current label's shapes #currentShape = self.labelShapes[self.currentLabelShapeIndex] #increase end value = current middle line labels = self.labelData fly_idx= labels['names'].index(self.currFly) labels['t1'][fly_idx][-1]=self.currentFrame self.labelData=labels #print self.labelData # draw all the existing shapes # for loop draw all shapes fly_to_draw= self.currFly labels=self.labelData if fly_to_draw in labels['names']: fly_idx= labels['names'].index(fly_to_draw) bouts= len(labels['labels'][fly_idx]) for i in xrange(bouts): color = self.colorMatch[labels['labels'][fly_idx][i]] self.currColor = color yPos = self.yMatch[labels['labels'][fly_idx][i]] painter.setBrush(QBrush(color)) pen=QPen(color) pen.setWidth(1) painter.setPen(pen) widthRect= (labels['t1'][fly_idx][i]-labels['t0'][fly_idx][i]+1) * self.widthPerFrame startPos= labels['t0'][fly_idx][i] * self.widthPerFrame #painter.drawRect(int x, int y, int width, int height) painter.drawRect(startPos,yPos,widthRect,10)
def _updatePensAndBrushes(self): color = QColor(_PENCIL_COLOR) penWidth = styles.PATH_STRAND_STROKE_WIDTH pen = QPen(color, penWidth) brush = QBrush(color) pen.setCapStyle(Qt.FlatCap) self.setPen(pen) self._low_cap.setBrush(brush) self._high_cap.setBrush(brush)
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 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 paintRects(self, painter, rects): """Override this method to implement different drawing behaviour.""" pen = QPen(self.color()) pen.setWidth(self.lineWidth) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing, True) rad = self.radius for r in rects: r.adjust(-rad, -rad, rad, rad) painter.drawRoundedRect(r, rad, rad)
def paint(self, painter, option, widget=None): if len(self.points) > 1: # init graphics pen = QPen(COLOR[self.layer]) pen.setWidth(0) painter.setPen(pen) # draw painter.drawPolyline(QPolygonF(self.points)) if PolygonBase.close_polygon: painter.drawLine(self.points[-1], self.points[0])
def _drawPlanetPic(self, painter: QPainter): if self._img_loaded: painter.drawImage(self._img.rect(), self._img, self._img.rect(), Qt.AutoColor) if self._planet.is_current: pen = QPen(QColor(0, 200, 0)) pen.setWidth(4) painter.setPen(pen) rc = self.rect() rc.adjust(0, 0, -1, -1) painter.drawRect(rc)
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
class ImageViewer(QGraphicsView, QObject): points_selection_sgn = pyqtSignal(list) key_press_sgn = pyqtSignal(QtGui.QKeyEvent) def __init__(self, parent=None): super(ImageViewer, self).__init__(parent) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self._scene = ImageViewerScene(self) self.setScene(self._scene) self._image = None self._image_original = None self._pixmap = None self._img_contrast = 1.0 self._img_brightness = 50.0 self._img_gamma = 1.0 self._create_grid() self._channels = [] self._current_tool = SELECTION_TOOL.POINTER self._dataset = None # create grid lines pen_color = QColor(255, 255, 255, 255) pen = QPen(pen_color) pen.setWidth(2) pen.setStyle(QtCore.Qt.DotLine) self.vline = QGraphicsLineItem() self.vline.setVisible(False) self.vline.setPen(pen) self.hline = QGraphicsLineItem() self.hline.setVisible(False) self.hline.setPen(pen) self._scene.addItem(self.vline) self._scene.addItem(self.hline) self._current_label = None # rectangle selection tool self._rectangle_tool_origin = QPoint() self._rectangle_tool_picker = QRubberBand(QRubberBand.Rectangle, self) # polygon selection tool app = QApplication.instance() color = app.palette().color(QPalette.Highlight) self._polygon_guide_line_pen = QPen(color) self._polygon_guide_line_pen.setWidth(3) self._polygon_guide_line_pen.setStyle(QtCore.Qt.DotLine) self._polygon_guide_line = QGraphicsLineItem() self._polygon_guide_line.setVisible(False) self._polygon_guide_line.setPen(self._polygon_guide_line_pen) self._scene.addItem(self._polygon_guide_line) self._current_polygon = None # circle self._current_ellipse = None # free selection tool self._current_free_path = None self._is_drawing = False self._last_point_drawn = QPoint() self._last_click_point = None self._free_Path_pen = QPen(color) self._free_Path_pen.setWidth(10) self._extreme_points = Queue(maxsize=4) @property def current_label(self): return self._current_label @current_label.setter def current_label(self, value): self._current_label = value if self._current_label: color = QColor(self._current_label.color) self._free_Path_pen.setColor(color) self._polygon_guide_line_pen.setColor(color) self._polygon_guide_line.setPen(self._polygon_guide_line_pen) @property def dataset(self): return self._dataset @dataset.setter def dataset(self, value): self._dataset = value @property def img_contrast(self): return self._img_contrast @img_contrast.setter def img_contrast(self, value): self._img_contrast = value @property def img_gamma(self): return self._img_gamma @img_gamma.setter def img_gamma(self, value): self._img_gamma = value @property def img_brightness(self): return self._img_brightness @img_brightness.setter def img_brightness(self, value): self._img_brightness = value @property def image(self): return self._image @image.setter def image(self, value): self._image = value self._image_original = value.copy() self.update_viewer() @property def pixmap(self) -> ImagePixmap: return self._pixmap @gui_exception def update_viewer(self, fit_image=True): rgb = cv2.cvtColor(self._image, cv2.COLOR_BGR2RGB) rgb = ImageUtilities.adjust_image(rgb, self._img_contrast, self._img_brightness) rgb = ImageUtilities.adjust_gamma(rgb, self._img_gamma) pil_image = Image.fromarray(rgb) qppixmap_image = pil_image.toqpixmap() x, y = -qppixmap_image.width() / 2, -qppixmap_image.height() / 2 if self._pixmap: self._pixmap.resetTransform() self._pixmap.setPixmap(qppixmap_image) self._pixmap.setOffset(x, y) else: self._pixmap = ImagePixmap() self._pixmap.setPixmap(qppixmap_image) self._pixmap.setOffset(x, y) self._scene.addItem(self._pixmap) self._pixmap.signals.hoverEnterEventSgn.connect( self.pixmap_hoverEnterEvent_slot) self._pixmap.signals.hoverLeaveEventSgn.connect( self.pixmap_hoverLeaveEvent_slot) self._pixmap.signals.hoverMoveEventSgn.connect( self.pixmap_hoverMoveEvent_slot) self._hide_guide_lines() if fit_image: self.fit_to_window() @gui_exception def reset_viewer(self): self._img_contrast = 1.0 self._img_brightness = 50.0 self._img_gamma = 1.0 self._image = self._image_original.copy() @gui_exception def equalize_histogram(self): self._image = ImageUtilities.histogram_equalization(self._image) @gui_exception def correct_lightness(self): self._image = ImageUtilities.correct_lightness(self._image) def clusterize(self, k): self._image = ImageUtilities.kmeans(self._image.copy(), k) @property def current_tool(self): return self._current_tool @current_tool.setter def current_tool(self, value): self._polygon_guide_line.hide() self._current_polygon = None self._current_free_path = None self._current_ellipse = None self._is_drawing = value == SELECTION_TOOL.FREE self._current_tool = value self.clear_extreme_points() if value == SELECTION_TOOL.POINTER: self.enable_items(True) else: self.enable_items(False) def fit_to_window(self): if not self._pixmap or not self._pixmap.pixmap(): return self.resetTransform() self.setTransform(QtGui.QTransform()) self.fitInView(self._pixmap, QtCore.Qt.KeepAspectRatio) def _create_grid(self, gridSize=15): app: QApplication = QApplication.instance() curr_theme = "dark" if app: curr_theme = app.property("theme") if curr_theme == "light": color1 = QtGui.QColor("white") color2 = QtGui.QColor(237, 237, 237) else: color1 = QtGui.QColor(20, 20, 20) color2 = QtGui.QColor(0, 0, 0) backgroundPixmap = QtGui.QPixmap(gridSize * 2, gridSize * 2) backgroundPixmap.fill(color1) painter = QtGui.QPainter(backgroundPixmap) painter.fillRect(0, 0, gridSize, gridSize, color2) painter.fillRect(gridSize, gridSize, gridSize, gridSize, color2) painter.end() self._scene.setBackgroundBrush(QtGui.QBrush(backgroundPixmap)) def wheelEvent(self, event: QWheelEvent): adj = (event.angleDelta().y() / 120) * 0.1 self.scale(1 + adj, 1 + adj) @gui_exception def keyPressEvent(self, event: QKeyEvent): if event.key() == QtCore.Qt.Key_Space: image_rect: QRectF = self._pixmap.sceneBoundingRect() if self.current_tool == SELECTION_TOOL.POLYGON and self._current_polygon: points = self._current_polygon.points self._polygon_guide_line.hide() self.setDragMode(QGraphicsView.ScrollHandDrag) if len(points) <= 2: self._current_polygon.delete_item() self.current_tool = SELECTION_TOOL.POINTER elif self.current_tool == SELECTION_TOOL.EXTREME_POINTS and \ self._extreme_points.full(): points = [] image_offset = QPointF(image_rect.width() / 2, image_rect.height() / 2) for pt in self._extreme_points.queue: pt: EditablePolygonPoint center = pt.sceneBoundingRect().center() x = math.floor(center.x() + image_offset.x()) y = math.floor(center.y() + image_offset.y()) points.append([x, y]) self.points_selection_sgn.emit(points) self.current_tool = SELECTION_TOOL.POINTER else: event.ignore() # guide lines events def _show_guide_lines(self): if self.hline and self.vline: self.hline.show() self.vline.show() def _hide_guide_lines(self): if self.hline and self.vline: self.hline.hide() self.vline.hide() def _update_guide_lines(self, x, y): bbox: QRect = self._pixmap.boundingRect() offset = QPointF(bbox.width() / 2, bbox.height() / 2) self.vline.setLine(x, -offset.y(), x, bbox.height() - offset.y()) self.vline.setZValue(1) self.hline.setLine(-offset.x(), y, bbox.width() - offset.x(), y) self.hline.setZValue(1) def pixmap_hoverMoveEvent_slot(self, evt: QGraphicsSceneHoverEvent, x, y): self._update_guide_lines(x, y) def pixmap_hoverEnterEvent_slot(self): self._show_guide_lines() def pixmap_hoverLeaveEvent_slot(self): self._hide_guide_lines() def delete_polygon_slot(self, polygon: EditablePolygon): self._current_polygon = None self.current_tool = SELECTION_TOOL.POINTER self._polygon_guide_line.hide() @gui_exception def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None: image_rect: QRectF = self._pixmap.boundingRect() mouse_pos = self.mapToScene(evt.pos()) if evt.buttons() == QtCore.Qt.LeftButton: if self.current_tool == SELECTION_TOOL.BOX: # create rectangle self.setDragMode(QGraphicsView.NoDrag) self._rectangle_tool_origin = evt.pos() geometry = QRect(self._rectangle_tool_origin, QSize()) self._rectangle_tool_picker.setGeometry(geometry) self._rectangle_tool_picker.show() elif self.current_tool == SELECTION_TOOL.POLYGON: if image_rect.contains(mouse_pos): if self._current_polygon is None: self._current_polygon = EditablePolygon() self._current_polygon.label = self._current_label self._current_polygon.tag = self._dataset self._current_polygon.signals.deleted.connect( self.delete_polygon_slot) self._scene.addItem(self._current_polygon) self._current_polygon.addPoint(mouse_pos) else: self._current_polygon.addPoint(mouse_pos) elif self.current_tool == SELECTION_TOOL.ELLIPSE: if image_rect.contains(mouse_pos): self.setDragMode(QGraphicsView.NoDrag) ellipse_rec = QtCore.QRectF(mouse_pos.x(), mouse_pos.y(), 0, 0) self._current_ellipse = EditableEllipse() self._current_ellipse.tag = self.dataset self._current_ellipse.label = self._current_label self._current_ellipse.setRect(ellipse_rec) self._scene.addItem(self._current_ellipse) elif self.current_tool == SELECTION_TOOL.FREE: # consider only the points into the image if image_rect.contains(mouse_pos): self.setDragMode(QGraphicsView.NoDrag) self._last_point_drawn = mouse_pos self._current_free_path = QGraphicsPathItem() self._current_free_path.setOpacity(0.6) self._current_free_path.setPen(self._free_Path_pen) painter = QPainterPath() painter.moveTo(self._last_point_drawn) self._current_free_path.setPath(painter) self._scene.addItem(self._current_free_path) elif self.current_tool == SELECTION_TOOL.EXTREME_POINTS: if image_rect.contains(mouse_pos): if not self._extreme_points.full(): def delete_point(idx): del self._extreme_points.queue[idx] idx = self._extreme_points.qsize() editable_pt = EditablePolygonPoint(idx) editable_pt.signals.deleted.connect(delete_point) editable_pt.setPos(mouse_pos) self._scene.addItem(editable_pt) self._extreme_points.put(editable_pt) else: self.setDragMode(QGraphicsView.ScrollHandDrag) super(ImageViewer, self).mousePressEvent(evt) @gui_exception def mouseMoveEvent(self, evt: QtGui.QMouseEvent) -> None: mouse_pos = self.mapToScene(evt.pos()) image_rect: QRectF = self._pixmap.boundingRect() if self.current_tool == SELECTION_TOOL.BOX: if not self._rectangle_tool_origin.isNull(): geometry = QRect(self._rectangle_tool_origin, evt.pos()).normalized() self._rectangle_tool_picker.setGeometry(geometry) elif self.current_tool == SELECTION_TOOL.POLYGON: if self._current_polygon and image_rect.contains(mouse_pos): if self._current_polygon.count > 0: last_point: QPointF = self._current_polygon.last_point self._polygon_guide_line.setZValue(1) self._polygon_guide_line.show() mouse_pos = self.mapToScene(evt.pos()) self._polygon_guide_line.setLine(last_point.x(), last_point.y(), mouse_pos.x(), mouse_pos.y()) else: self._polygon_guide_line.hide() elif self.current_tool == SELECTION_TOOL.ELLIPSE: if self._current_ellipse and image_rect.contains(mouse_pos): ellipse_rect = self._current_ellipse.rect() ellipse_pos = QPointF(ellipse_rect.x(), ellipse_rect.y()) distance = math.hypot(mouse_pos.x() - ellipse_pos.x(), mouse_pos.y() - ellipse_pos.y()) ellipse_rect.setWidth(distance) ellipse_rect.setHeight(distance) self._current_ellipse.setRect(ellipse_rect) elif self.current_tool == SELECTION_TOOL.FREE and evt.buttons( ) and QtCore.Qt.LeftButton: if self._current_free_path and image_rect.contains(mouse_pos): painter: QPainterPath = self._current_free_path.path() self._last_point_drawn = self.mapToScene(evt.pos()) painter.lineTo(self._last_point_drawn) self._current_free_path.setPath(painter) super(ImageViewer, self).mouseMoveEvent(evt) @gui_exception def mouseReleaseEvent(self, evt: QtGui.QMouseEvent) -> None: image_rect: QRectF = self._pixmap.boundingRect() if self.current_tool == SELECTION_TOOL.BOX: roi: QRect = self._rectangle_tool_picker.geometry() roi: QRectF = self.mapToScene(roi).boundingRect() self._rectangle_tool_picker.hide() if image_rect == roi.united(image_rect): rect = EditableBox(roi) rect.label = self.current_label rect.tag = self._dataset self._scene.addItem(rect) self.current_tool = SELECTION_TOOL.POINTER self.setDragMode(QGraphicsView.ScrollHandDrag) elif self.current_tool == SELECTION_TOOL.ELLIPSE and self._current_ellipse: roi: QRect = self._current_ellipse.boundingRect() if image_rect == roi.united(image_rect): self.current_tool = SELECTION_TOOL.POINTER self.setDragMode(QGraphicsView.ScrollHandDrag) else: self._current_ellipse.delete_item() elif self.current_tool == SELECTION_TOOL.FREE and self._current_free_path: # create polygon self._current_free_path: QGraphicsPathItem path_rect = self._current_free_path.boundingRect() if image_rect == path_rect.united(image_rect): path = self._current_free_path.path() path_polygon = EditablePolygon() path_polygon.tag = self.dataset path_polygon.label = self.current_label self._scene.addItem(path_polygon) for i in range(0, path.elementCount(), 10): x, y = path.elementAt(i).x, path.elementAt(i).y path_polygon.addPoint(QPointF(x, y)) self._scene.removeItem(self._current_free_path) self.current_tool = SELECTION_TOOL.POINTER self.setDragMode(QGraphicsView.ScrollHandDrag) super(ImageViewer, self).mouseReleaseEvent(evt) def remove_annotations(self): for item in self._scene.items(): if isinstance(item, EditableItem): item.delete_item() def remove_annotations_by_label(self, label_name): for item in self._scene.items(): if isinstance(item, EditableItem): if item.label and item.label.name == label_name: item.delete_item() def enable_items(self, value): for item in self._scene.items(): if isinstance(item, EditableItem): item.setEnabled(value) def clear_extreme_points(self): if self._extreme_points.qsize() > 0: for pt in self._extreme_points.queue: self._scene.removeItem(pt) self._extreme_points.queue.clear()
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 = np.array([[0, 0], [10, 0], [6, 4], [6, 2], [0, 2] ]) / (40) * port.width 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) port_items = port_shapes + [qtext] rad = port.orientation * np.pi / 180 x, y = port.endpoints[0] * 1 / 4 + port.endpoints[ 1] * 3 / 4 + np.array([np.cos(rad), np.sin(rad)]) * port.width / 8 # x,y = port.midpoint[0], port.midpoint[1] # x,y = x - qtext.boundingRect().width()/2, y - qtext.boundingRect().height()/2 qtext.setPos(QPointF(x, y)) qtext.setFlag(QGraphicsItem.ItemIgnoresTransformations) 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 paintEvent(self, event): # 由于是全透明背景窗口,重绘事件中绘制透明度为1的难以发现的边框,用于调整窗口大小 super(FramelessWindow, self).paintEvent(event) painter = QPainter(self) painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.MARGIN)) painter.drawRect(self.rect())
def set_penByState(self, state, qp): pen_color = QColor(pallet[state]) pen = QPen(pen_color, 1, Qt.SolidLine) qp.setPen(pen) qp.setBrush(pen_color)
def drawGrid(self, painter, exposed, gridColor): rect = exposed.toAlignedRect() if (rect.isNull()): return p = RenderParams(self.map()) # Determine the tile and pixel coordinates to start at startTile = self.screenToTileCoords_(rect.topLeft()).toPoint() startPos = self.tileToScreenCoords_(startTile).toPoint() ## Determine in which half of the tile the top-left corner of the area we # need to draw is. If we're in the upper half, we need to start one row # up due to those tiles being visible as well. How we go up one row # depends on whether we're in the left or right half of the tile. ## inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX if (inUpperHalf): startTile.setY(startTile.y() - 1) if (inLeftHalf): startTile.setX(startTile.x() - 1) startTile.setX(max(0, startTile.x())) startTile.setY(max(0, startTile.y())) startPos = self.tileToScreenCoords_(startTile).toPoint() oct = [ QPoint(0, p.tileHeight - p.sideOffsetY), QPoint(0, p.sideOffsetY), QPoint(p.sideOffsetX, 0), QPoint(p.tileWidth - p.sideOffsetX, 0), QPoint(p.tileWidth, p.sideOffsetY), QPoint(p.tileWidth, p.tileHeight - p.sideOffsetY), QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight), QPoint(p.sideOffsetX, p.tileHeight) ] lines = QVector() #lines.reserve(8) gridColor.setAlpha(128) gridPen = QPen(gridColor) gridPen.setCosmetic(True) _x = QVector() _x.append(2) _x.append(2) gridPen.setDashPattern(_x) painter.setPen(gridPen) if (p.staggerX): # Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerX(startTile.x())): startPos.setY(startPos.y() - p.rowHeight) while (startPos.x() <= rect.right() and startTile.x() < self.map().width()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) if (p.doStaggerX(startTile.x())): rowPos.setY(rowPos.y() + p.rowHeight) while (rowPos.y() <= rect.bottom() and rowTile.y() < self.map().height()): lines.append(QLineF(rowPos + oct[1], rowPos + oct[2])) lines.append(QLineF(rowPos + oct[2], rowPos + oct[3])) lines.append(QLineF(rowPos + oct[3], rowPos + oct[4])) isStaggered = p.doStaggerX(startTile.x()) lastRow = rowTile.y() == self.map().height() - 1 lastColumn = rowTile.x() == self.map().width() - 1 bottomLeft = rowTile.x() == 0 or (lastRow and isStaggered) bottomRight = lastColumn or (lastRow and isStaggered) if (bottomRight): lines.append(QLineF(rowPos + oct[5], rowPos + oct[6])) if (lastRow): lines.append(QLineF(rowPos + oct[6], rowPos + oct[7])) if (bottomLeft): lines.append(QLineF(rowPos + oct[7], rowPos + oct[0])) painter.drawLines(lines) lines.resize(0) rowPos.setY(rowPos.y() + p.tileHeight + p.sideLengthY) rowTile.setY(rowTile.y() + 1) startPos.setX(startPos.x() + p.columnWidth) startTile.setX(startTile.x() + 1) else: # Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerY(startTile.y())): startPos.setX(startPos.x() - p.columnWidth) while (startPos.y() <= rect.bottom() and startTile.y() < self.map().height()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) if (p.doStaggerY(startTile.y())): rowPos.setX(rowPos.x() + p.columnWidth) while (rowPos.x() <= rect.right() and rowTile.x() < self.map().width()): lines.append(QLineF(rowPos + oct[0], rowPos + oct[1])) lines.append(QLineF(rowPos + oct[1], rowPos + oct[2])) lines.append(QLineF(rowPos + oct[3], rowPos + oct[4])) isStaggered = p.doStaggerY(startTile.y()) lastRow = rowTile.y() == self.map().height() - 1 lastColumn = rowTile.x() == self.map().width() - 1 bottomLeft = lastRow or (rowTile.x() == 0 and not isStaggered) bottomRight = lastRow or (lastColumn and isStaggered) if (lastColumn): lines.append(QLineF(rowPos + oct[4], rowPos + oct[5])) if (bottomRight): lines.append(QLineF(rowPos + oct[5], rowPos + oct[6])) if (bottomLeft): lines.append(QLineF(rowPos + oct[7], rowPos + oct[0])) painter.drawLines(lines) lines.resize(0) rowPos.setX(rowPos.x() + p.tileWidth + p.sideLengthX) rowTile.setX(rowTile.x() + 1) startPos.setY(startPos.y() + p.rowHeight) startTile.setY(startTile.y() + 1)
def _updateFloatPen(self): pen_width = styles.PATH_STRAND_STROKE_WIDTH pen = QPen(_PENCIL_COLOR, pen_width) pen.setCapStyle(Qt.FlatCap) self.setPen(pen)
def add_sequencer_items(self): seq_group = QtWidgets.QGraphicsItemGroup() self.scene.addItem(seq_group) Blanches = ['Do', 'Re', 'Mi', 'Fa', 'Sol', 'La', 'Si'] #Notes blanches pen = QPen(QtGui.QColor("white")) for i in range(49): item = QtWidgets.QGraphicsRectItem(-2 * 1.5, 2 * i + 0.5, 2.5, 1, seq_group) item.setPen(pen) item.setToolTip(Blanches[i % 7]) #Notes noires pen = QPen(QtGui.QColor("black")) for i in range(7): item = QtWidgets.QGraphicsRectItem(-2 * 2, 2 * (7 * i + 1), 2.5, 0, seq_group) item.setPen(pen) item.setToolTip("Do#") item = QtWidgets.QGraphicsRectItem(-2 * 2, 2 * (7 * i + 2), 2.5, 0, seq_group) item.setPen(pen) item.setToolTip("Re#") item = QtWidgets.QGraphicsRectItem(-2 * 2, 2 * (7 * i + 4), 2.5, 0, seq_group) item.setPen(pen) item.setToolTip("Fa#") item = QtWidgets.QGraphicsRectItem(-2 * 2, 2 * (7 * i + 5), 2.5, 0, seq_group) item.setPen(pen) item.setToolTip("Sol#") item = QtWidgets.QGraphicsRectItem(-2 * 2, 2 * (7 * i + 6), 2.5, 0, seq_group) item.setPen(pen) item.setToolTip("La#") #Fin piano pen = QPen(QtGui.QColor("black"), 1 / 100) pen.setCapStyle(QtCore.Qt.SquareCap) path = QtGui.QPainterPath() path.moveTo(0, 0) path.lineTo(0, 49 * 2) item = QtWidgets.QGraphicsPathItem(path, seq_group) item.setPen(pen) #NoteLines pen = QPen(QtGui.QColor("black"), 1 / 100) pen.setCapStyle(QtCore.Qt.SquareCap) path = QtGui.QPainterPath() for i in range(49): path.moveTo(-4, 2 * i) path.lineTo(0, 2 * i) for i in range(7): path.moveTo(-4, 14 * i) path.lineTo(500, 14 * i) path.moveTo(0, 14 * i + 1.5) path.lineTo(500, 14 * i + 1.5) path.moveTo(0, 14 * i + 2.5) path.lineTo(500, 14 * i + 2.5) path.moveTo(0, 14 * i + 3.5) path.lineTo(500, 14 * i + 3.5) path.moveTo(0, 14 * i + 4.5) path.lineTo(500, 14 * i + 4.5) path.moveTo(-4, 14 * i + 6) path.lineTo(500, 14 * i + 6) path.moveTo(0, 14 * i + 7.5) path.lineTo(500, 14 * i + 7.5) path.moveTo(0, 14 * i + 8.5) path.lineTo(500, 14 * i + 8.5) path.moveTo(0, 14 * i + 9.5) path.lineTo(500, 14 * i + 9.5) path.moveTo(0, 14 * i + 10.5) path.lineTo(500, 14 * i + 10.5) path.moveTo(0, 14 * i + 11.5) path.lineTo(500, 14 * i + 11.5) path.moveTo(0, 14 * i + 12.5) path.lineTo(500, 14 * i + 12.5) item = QtWidgets.QGraphicsPathItem(path, seq_group) item.setPen(pen)
class DrawingBoardUIBusi(QMainWindow): # 单例模式 # _instance = None # # def __new__(cls, *args, **kw): # if not cls._instance: # cls._instance = super(DrawingBoardUIBusi, cls).__new__(cls, *args, **kw) # return cls._instance def __init__(self, meetingId=None, meetingNumber=None): super(DrawingBoardUIBusi, self).__init__() self.meetingNumber = meetingNumber # 会议编号 self.meetingId = meetingId # 会议号 self.init_parameters() # 初始化系统参数 self.setupUi() # 创建UI self.setWindowOpacity(1) # 设置透明度 self.init_serial_port() # 初始化串口通信 def init_serial_port(self): # 初始化串口通信,接收命令 self.serial = SerialHandler() if self.serial.ser.port != None: self.serial.port_open() self.t1 = threading.Thread(target=self.receive_data, daemon=True) # 多线程改为多进程 # self.t1 = multiprocessing.Process(target=self.receive_data) # self.t1.setDaemon(True) self.t1.start() print('串口通信多进程开启') def receive_data(self): # 一直接收串口命令,执行相应的指令 print("The receive_data threading is start") res_data = '' num = 0 while (self.serial.ser.isOpen()): time.sleep(1) # 查询不那么频繁 size = self.serial.ser.inWaiting() # 获取输入缓冲区中的字节数 if size: res_data = self.serial.ser.read_all() res_data_new = binascii.b2a_hex(res_data).decode() print('接收到的数据:%s' % (res_data_new)) print(res_data_new.find('01')) if res_data_new[4:6] == '01': # 按键1--清屏 self.clearScree() elif res_data_new[4:6] == '02': # 按键2--保存 self.savePicture(True) elif res_data_new[4:6] == '03': # 按键3--上一页 print('上一页') self.previousPage() elif res_data_new[4:6] == '04': # 按键4--下一页 print('下一页') self.nextPage() elif res_data_new[4:6] == '05': # 按键5--黑笔 self.changeColor(0) elif res_data_new[4:6] == '06': # 按键6--蓝笔 self.changeColor(1) elif res_data_new[4:6] == '07': # 按键7--红笔 self.changeColor(2) elif res_data_new[4:6] == '08': # 按键8--擦除 self.erase() # binascii.b2a_hex(res_data).decode() self.serial.ser.flushInput() # 刷新输入缓冲区 num += 1 print("接收:" + str(num)) def setupUi(self): ''' 创建UI, :return: ''' self.setObjectName('drawWindow') # 对象名 self.setWindowTitle('白板') # 设置标题 self.resize(self.resolution.width(), self.resolution.height()) self.setWindowIcon(QIcon("qrc\Icon.png")) # 设置图标 self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint) # 任务栏隐藏图标 # self.setWindowTitle('当前' + str(self.page) + '页') # 标题显示第几页 self.setWindowTitle('当前' + '页') # 标题显示第几页 # self.setWindowFlags( # Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowTitleHint | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setFixedSize(self.width(), self.height()) # 设置主窗口禁止调整大小 # 创建白板的功能键 btn_names = [ '清屏', '保存', '切换', '上一页', '下一页', '黑笔', '蓝笔', '红笔', '擦除', '功能', '恢复', '加载' ] # 各个按钮的位置 positions = [(self.resolution.width() - self.resolution.height() / len(btn_names), (y * self.resolution.height() / len(btn_names))) for y in range(0, len(btn_names))] # 每个功能按钮的高度 height = (self.resolution.height() / len(btn_names)) * 0.98 '''要重构这部分代码''' # 清屏 self.btn_clean = QPushButton(btn_names[0], self) self.btn_clean.resize(height, height) self.btn_clean.move(positions[0][0], positions[0][1]) self.btn_clean.clicked.connect(self.clearScree) self.btn_clean.setVisible(False) # self.btn_clean.setStyleSheet("background-color: rgba(0,125,0,0)") # 保存 self.btn_savePicture = QPushButton(btn_names[1], self) self.btn_savePicture.resize(height, height) self.btn_savePicture.move(positions[1][0], positions[1][1]) self.btn_savePicture.clicked.connect(lambda: self.savePicture(False)) self.btn_savePicture.setVisible(False) # 切换 self.btn_switch = QPushButton(btn_names[2], self) self.btn_switch.resize(height, height) self.btn_switch.move(positions[2][0], positions[2][1]) self.btn_switch.clicked.connect(self.switch) self.btn_switch.setVisible(False) # 上一页 self.btn_previousPage = QPushButton(btn_names[3], self) self.btn_previousPage.resize(height, height) self.btn_previousPage.move(positions[3][0], positions[3][1]) self.btn_previousPage.clicked.connect(self.previousPage) self.btn_previousPage.setVisible(False) # 下一页 self.btn_nextPage = QPushButton(btn_names[4], self) self.btn_nextPage.resize(height, height) self.btn_nextPage.move(positions[4][0], positions[4][1]) self.btn_nextPage.clicked.connect(self.nextPage) self.btn_nextPage.setVisible(False) # 黑笔 self.btn_changeColor1 = QPushButton(btn_names[5], self) self.btn_changeColor1.resize(height, height) self.btn_changeColor1.move(positions[5][0], positions[5][1]) self.btn_changeColor1.clicked.connect(lambda: self.changeColor(0)) self.btn_changeColor1.setEnabled(True) self.btn_changeColor1.setVisible(False) # 蓝笔 self.btn_changeColor2 = QPushButton(btn_names[6], self) self.btn_changeColor2.resize(height, height) self.btn_changeColor2.move(positions[6][0], positions[6][1]) self.btn_changeColor2.clicked.connect(lambda: self.changeColor(1)) self.btn_changeColor2.setEnabled(True) self.btn_changeColor2.setVisible(False) # 红笔 self.btn_changeColor3 = QPushButton(btn_names[7], self) self.btn_changeColor3.resize(height, height) self.btn_changeColor3.move(positions[7][0], positions[7][1]) self.btn_changeColor3.clicked.connect(lambda: self.changeColor(2)) self.btn_changeColor3.setEnabled(True) self.btn_changeColor3.setVisible(False) # 擦除 self.btn_erase = QPushButton(btn_names[8], self) self.btn_erase.resize(height, height) self.btn_erase.move(positions[8][0], positions[8][1]) self.btn_erase.clicked.connect(self.erase) self.btn_erase.setVisible(False) ''' # 功能 self.btn_startSharing = QPushButton(btn_names[9], self) self.btn_startSharing.resize(height, height) self.btn_startSharing.move(positions[9][0], positions[9][1]) self.btn_startSharing.clicked.connect(self.startSharing) # 恢复 self.btn_restorePicture = QPushButton(btn_names[10], self) self.btn_restorePicture.resize(height, height) self.btn_restorePicture.move(positions[10][0], positions[10][1]) self.btn_restorePicture.clicked.connect(self.restorePicture) # 加载 self.btn_loadPicture = QPushButton(btn_names[11], self) self.btn_loadPicture.resize(height, height) self.btn_loadPicture.move(positions[11][0], positions[11][1]) self.btn_loadPicture.clicked.connect(self.loadPicture) ''' def init_parameters(self): ''' 初始化系统参数,可读取系统配置文件 :return: ''' self.count = 0 self.resolution = QDesktopWidget().availableGeometry( ) # 获取显示器的分辨率-->(0, 0, 1366, 728) self.monitor = QDesktopWidget() # 获得显示器的物理尺寸 # self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint) # 任务栏隐藏图标 # 会议号 self.meetingID = 0 # 当前会议号 # 页数记录 self.page = 1 # 当前所在页页码 self.pages = 1 # 总页数 self.isWritting = False # 是否正在输入 self.isWritten = False # 记录当前页是否有新写入 ##########2018-6-12 添加########### self.httpRequest = HttpRequest() # http请求对象那 self.is_login = True # 用户是否登录 # self.shareThread = threading.Thread(target=self.meetingConnection, daemon=True) # 创建一个实时分享的线程 # self.shareThread.start() # 多线程改为多进程 self.shareThread = threading.Thread(target=self.self_check_net, daemon=True) # 创建一个实时分享的线程 self.shareThread.start() # print('# 创建一个实时分享的进程1') # self.shareProcess = multiprocessing.Process(target=self.self_check_net) # 创建一个实时分享的进程 # self.shareProcess.start() # print('# 创建一个实时分享的进程2') self.screenshotFullScreen = ScreenShotsWin() # 用于截全屏的对象 ##########2018-6-12 添加########### # 记录笔迹(坐标,颜色) self.penColor = 0 # 笔的初始颜色黑色 self.pos_xyc = [] # [((x, y), c)] c->0 1 2 3 self.pos_pages = {} # 存放所有页笔画路径{page : pos_xyc} # 设置不追踪鼠标 self.setMouseTracking(False) # 使用指定的画笔,宽度,钢笔样式,帽子样式和连接样式构造笔 self.pen = QPen(Qt.black, 4, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) # 画布pix self.pix = QPixmap(self.resolution.size()) self.pix.fill(Qt.white) self.pix = QPixmap(self.resolution.size()) self.pix.fill(Qt.white) # self.pix.save('原图.png') # 黑板擦 ''' 改用 eraseRect ,直接去掉笔画 void QPainter::eraseRect(const QRectF &rectangle) Erases the area inside the given rectangle. Equivalent to calling fillRect(rectangle, background()). ''' self.paintEase = QPainter(self) self.paintEase.setPen(QPen(Qt.black, Qt.DashLine)) self.paintEase.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # 是否擦除 self.eraseable = False # 起点终点 self.lastPoint = QPoint() self.endPoint = QPoint() self.icon = QIcon("icon\Icon.png") # 窗体图标 self.addSystemTray() # 设置系统托盘 def addSystemTray(self): ''' 系统托盘,显示、隐藏主窗体,退出程序 :return: ''' minimizeAction = QAction("隐藏", self, triggered=self.hide) # 隐藏菜单 maximizeAction = QAction("显示", self, triggered=self.show) # 显示菜单 restoreAction = QAction("恢复", self, triggered=self.showNormal) # 恢复菜单 quitAction = QAction("退出", self, triggered=self.close) # 退出菜单 self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(minimizeAction) self.trayIconMenu.addAction(maximizeAction) self.trayIconMenu.addAction(restoreAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(quitAction) self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setIcon(self.icon) # 设置系统托盘图标 self.setWindowIcon(self.icon) # 设置系统窗体图标 self.trayIcon.setContextMenu(self.trayIconMenu) # 添加右键菜单 self.trayIcon.activated.connect(self.trayClick) # 左键点击托盘 self.trayIcon.show() def trayClick(self, event): ''' 双击系统托盘显示主窗体 :param event: :return: ''' if event == QSystemTrayIcon.DoubleClick: # 双击 self.showNormal() else: pass def applyForMeetingNum(self): ''' 申请会议号 :return: ''' response = self.httpRequest.applyForMeetingNum() # result = json.loads(response.content) try: result = response.json()['data'] print(type(result)) logger.debug(result) self.meetingId, self.meetingNumber = result.split('&') # 截取会议编号 logger.debug(self.meetingId) logger.debug(self.meetingNumber) QMessageBox.information(self, '申请会议号成功', '会议号:' + self.meetingNumber, QMessageBox.Ok) except: logger.debug('网络衔接失败') QMessageBox.warning(self, '警告', '网络连接失败!请检查网络设备!', QMessageBox.Cancel) def meetingConnection(self): logger.debug('查询用户请求') while (True): if self.is_login and is_share: time.sleep(2) # 等待1s logger.debug('分享开启') try: response = self.httpRequest.meetingConnection( self.meetingId) result = response.json() code = result['code'] print(result, code) if code == '0': # 需再次建立会议连接 print('需再次建立会议连接') time.sleep(2) # 等待1s continue elif code == '1': # 有用户需要截屏 print('有用户需要截屏') t_upload = threading.Thread(target=self.uploadPic, daemon=True) t_upload.start() t_upload.join() time.sleep(5) # 等待1s elif code == '-1': # 请求过于频繁,当前已有连接处于等待状态 print('请求过于频繁,当前已有连接处于等待状态') time.sleep(5) # 等待1s continue else: print('“会议不存在,请重新分配会议号”') except: logger.debug('网络衔接失败') else: # logger.debug('分享关闭') pass def self_check_net(self): print('分享线程开始') while (True): print('循環') flag = self.count == 0 time.sleep(2) if flag: if self.count == 0: self.weather_con() def weather_con(self): print('+++++ 查询服务器请求 ++++++') if self.is_login and is_share and self.count <= 2: self.count += 1 response = self.httpRequest.meetingConnection(self.meetingId) print('response: %s' % response) if response != None: result = response.json() print(result) code = result['code'] self.count -= 1 print('result:', result) if code == '0': print('code: 0') self.weather_con() elif code == '1': print('code: 1') # t_upload = threading.Thread(target=self.uploadPic, daemon=True) # t_upload.start() print('截图多进程1') p_upload = multiprocessing.Process(target=self.uploadPic) p_upload.start() print('截图多进程1') # self.weather_con() elif code == '-1': print('code: -1') pass elif code == '-2': print('code: -2') self.applyForMeetingNum() def uploadPic(self): self.screenshotsFullScreen() # 截图 fileName = 'save/temp/' + str(self.page) + '.jpg' files = {'file': open(fileName, 'rb')} print('开始上传图片') respone = self.httpRequest.uploadPic(files=files, meetingId=self.meetingId, pageNum=self.page) print('上传图片成功') print(respone) def screenshotsFullScreen(self): ''' 截图全图 :return:全屏的截图pix.png ''' pix = self.screenshotFullScreen.screenshotsFullScreen() fileName = 'save/temp/' + str(self.page) + '.jpg' pix.save(fileName) print('截图并保存成功') def paintEvent(self, event): '''绘图事件''' # 绘制在屏幕上 painter_to_window = QPainter(self) painter_to_window.setRenderHint(QPainter.Antialiasing, True) # 反锯齿 painter_to_window.setRenderHint(QPainter.SmoothPixmapTransform, True) painter_to_window.drawPixmap(0, 0, self.pix) def mousePressEvent(self, event): # 鼠标左键按下 if event.button() == Qt.LeftButton: self.isWritten = True # 当前页有输入或改动 self.isWritting = True # 已开始抒写 self.lastPoint = event.pos() self.endPoint = self.lastPoint logger.debug('点击左键') g_hw_render.insert_first(event.pos().x(), event.pos().y()) def mouseMoveEvent(self, event): ''' 调用update()函数在这里相当于调用paintEvent()函数 ''' if event.buttons() and Qt.LeftButton: self.endPoint = event.pos() # 进行重新绘制 logger.debug('鼠标移动') g_hw_render.insert(event.pos().x(), event.pos().y()) self.draw() # 绘制 self.update() def mouseReleaseEvent(self, event): # 鼠标左键释放 if event.button() == Qt.LeftButton: self.endPoint = event.pos() # 进行重新绘制 g_hw_render.insert_last(event.pos().x(), event.pos().y()) self.draw() # 绘制 self.update() self.isWritting = False # 已停止抒写 logger.debug('左键释放') def draw(self): logger.debug('draw') painter = QPainter(self.pix) # pen = QPen(Qt.black, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) painter.setRenderHint(QPainter.Antialiasing, True) painter.setPen(self.pen) painter.begin(self.pix) self.drawPath(painter) painter.end() self.update() def drawPath(self, painter): m_cur_path = g_hw_render.get_m_cur_path() start_index = 0 if m_cur_path.len > 11: start_index = m_cur_path.len - 11 else: start_index = 0 for p in range(start_index, m_cur_path.len - 1): # print(i) # print("输出所有点和宽度(%d,%d)_%f" % (m_cur_path._point[p].p.x, m_cur_path._point[p].p.y, m_cur_path._point[p].w)) point1 = QPoint(m_cur_path._point[p].p.x, m_cur_path._point[p].p.y) point2 = QPoint(m_cur_path._point[p + 1].p.x, m_cur_path._point[p + 1].p.y) w = m_cur_path._point[p].w if self.eraseable == True: self.pen.setWidth(100) # 设置黑板擦宽度 else: # 改变笔的粗细 self.pen.setWidthF(w * 25) pass painter.setPen(self.pen) painter.drawLine(point1, point2) logger.debug('drawPath') def keyPressEvent(self, event): ''' 键盘事件 :param event: :return: ''' key = event.key() # ESC最小化白板 if key == Qt.Key_Escape: self.hide() elif key == Qt.Key_A and event.modifiers() == Qt.ControlModifier: self.applyForMeetingNum() # 申请会议号 elif key == Qt.Key_F5: # 开启分享 global is_share if not is_share: is_share = True self.setWindowTitle("白板 - 分享已开启@" + self.meetingNumber) elif is_share and self.shareThread.is_alive(): is_share = False self.setWindowTitle("白板 - 分享已关闭") def contextMenuEvent(self, event): ''' 白板中的右键菜单 :param event: :return: ''' qmenu = QMenu(self) qmenu.addAction('清屏', self.clearScree) savePictureAct = qmenu.addAction('保存') savePictureAct.triggered.connect(lambda: self.savePicture(False)) qmenu.addAction('切换', self.switch) qmenu.addSeparator() qmenu.addAction('上一页', self.previousPage) qmenu.addAction('下一页', self.nextPage) qmenu.addSeparator() self.changeColorBlack = qmenu.addAction('黑笔') self.changeColorBlack.triggered.connect(lambda: self.changeColor(0)) self.changeColorBlue = qmenu.addAction('蓝笔') self.changeColorBlue.triggered.connect(lambda: self.changeColor(1)) self.changeColorRed = qmenu.addAction('红笔') self.changeColorRed.triggered.connect(lambda: self.changeColor(2)) qmenu.addAction('擦除', self.erase) qmenu.addSeparator() # self.changeThickness = qmenu.addAction('笔的粗细', self.changeThickness()) # qmenu.addSeparator() # qmenu.addAction('功能', self.startSharing) # qmenu.addAction('恢复', self.restorePicture) # qmenu.addAction('加载', self.loadPicture) self.action = qmenu.exec_(self.mapToGlobal(event.pos())) def loadPicture(self): # 加载本地图片 pass def restorePicture(self): pass def startSharing(self): pass def changeThickness(self): pass def erase(self): if self.eraseable == False: self.eraseable = True self.pen.setColor(Qt.white) # 设置黑板擦的颜色为白色,与画板颜色一致 self.pen.setWidth(100) # 设置黑板擦宽度 # self.paint_to_pix.setPen(self.pen) # 更新paint_to_pix self.penColor = 3 else: self.eraseable = False self.changeColor(0) def changeColor(self, colorNum): ''' 换颜色 :param colorNum: 颜色号 :return: ''' # 关闭黑板擦 self.eraseable = False # 笔的颜色 colorDic = {0: Qt.black, 1: Qt.blue, 2: Qt.red} self.pen.setColor(colorDic[colorNum]) self.penColor = colorNum # self.pen.setWidth(4) # 设置固定宽度 def nextPage(self): ''' 切换下一页画布 :return: ''' print('下一页1') if self.isWritten: # 当前页有输入或改动则保存当前页 self.savePicture(True) # self.pos_pages[self.page] = self.pos_xyc # 记录当前页笔画路径 self.isWritten = False # 关闭改动标志 print('下一页2') if self.page == self.pages: # 开辟新一页,总页数加一 # self.pos_xyc = [] # 当前页路径清空 self.pages += 1 # 页总数加一 self.pix.fill(Qt.white) # 清空画布 else: # 当前页并非最后一页 print('下一页3') fileName = str(self.page + 1) readFileName = os.path.join(self.filePath, 'temp', fileName + '.jpg') QPixmapCache.clear() self.pix.load(readFileName) # self.pos_xyc = self.pos_pages[self.page + 1] print('下一页4') self.update() # 更新内容 print('下一页5') self.page = self.page + 1 # 当前页码加一 print('下一页6') # t_changName = threading.Thread(target=self.changeWinName, args=(self.page, self.pages,)) # t_changName.start() # self.setWindowTitle('当前' + str(self.page) + '/' + str(self.pages) + '页') # 更新标题栏显示的页码 print('下一页7') logger.debug('下翻页第%s页', self.page) def changeWinName(self, page, pages): self.setWindowTitle('当前' + str(page) + '/' + str(page) + '页') # 更新标题栏显示的页码 def previousPage(self): ''' 切换到上一页画布 :return: ''' if self.isWritten or (self.page == self.pages): # 当前页有输入或改动则保存当前页 self.savePicture(True) # self.pos_pages[self.page] = self.pos_xyc # 记录当前页笔画路径 self.isWritten = False # 关闭改动标志 if self.page > 1: # 当前页码非第一页 self.page -= 1 # 当前页码减一 fileName = str(self.page) readFileName = os.path.join(self.filePath, 'temp', fileName + '.jpg') QPixmapCache.clear() # 清空画布 self.pix.load(readFileName) # self.pos_xyc = self.pos_pages[self.page] else: # 当前页码为第一页 pass self.update() # 更新内容 print('下一页6') # self.setWindowTitle('当前' + str(self.page) + '/' + str(self.pages) + '页') # 更新标题栏显示的页码 # t_changName = threading.Thread(target=self.changeWinName, args=(self.page, self.pages,)) # t_changName.start() logger.debug('上翻页第%s页', self.page) def switch(self): '''切换''' self.showMinimized() def savePicture(self, flag=True, meetingID='201711'): ''' 将当前白板上的内容保存成图片 flag = True,为自动保存 flag = False为用户保存 ''' # 保存目录 './save/日期+会议号/' time = QDateTime.currentDateTime().toString("yyyy-MM-dd_") self.meetingID = meetingID self.filePath = os.path.join(os.getcwd(), 'save', time + self.meetingID) # 创建目录 if not os.path.exists(self.filePath): os.makedirs(self.filePath) os.makedirs(os.path.join(self.filePath, 'temp')) if flag: # 自动保存分为两部分:1.保存图片到本地 2.保存保存路径json文件到本地 # 1.保存图片到本地 # fileName = QDateTime.currentDateTime().toString('yyMMddhhmmss') fileName = str(self.page) # 以页码为图片名 logger.debug( 'filePath %s', os.path.join(self.filePath, 'temp', fileName + '.jpg')) self.pix.save( os.path.join(self.filePath, 'temp', fileName + '.jpg')) logger.debug('保存图片') # 2.保存保存路径json文件到本地 import json dict = { 'pox_xyc': self.pos_xyc, 'page': self.page, 'meetingID': self.meetingID } # logger.debug('dict: %s', dict) with open(os.path.join(self.filePath, 'temp', fileName + '.json'), 'w') as f: json.dump(dict, f) logger.debug('保存json文件') else: # 用户手动保存 fileName = QFileDialog.getSaveFileName(self, '保存图片', self.filePath, ".png;;.jpg") self.pix.save(fileName[0] + fileName[1]) def clearScree(self): '''清屏''' # self.pos_xyc.clear() self.update() self.pix.fill(Qt.white) def closeEvent(self, QCloseEvent): ''' 关闭白板时保存当前画板内容 :return: ''' print('关闭白板') qApp.quit() # 强制关闭
def paintEvent(self, e): #print("paint") self.qp = QPainter(self) #self.qp.setPen(QColor(245, 245, 245)) #if you need no black circuit triangle = QPolygonF([ QPointF(200, 200), QPointF(200 + self.width, 200), QPointF(200 + self.width / 2, 200 - self.roofHeight) ]) self.qp.setBrush(QBrush(self.roofColor, Qt.SolidPattern)) self.qp.drawPolygon(triangle) #roof self.qp.setBrush(QBrush(self.mainColor1, Qt.SolidPattern)) self.qp.drawRect(200, 200, self.width, self.height) #upper part self.qp.setBrush(QBrush(self.mainColor2, Qt.SolidPattern)) self.qp.drawRect(200, 200 + self.height, self.width, self.height) #lower part #details self.qp.setBrush(QBrush(self.doorColor, Qt.SolidPattern)) self.qp.drawRect(130 + self.width, 115 + 2 * self.height, 50, 80) #calculate door self.qp.setBrush(QBrush(self.lightColor, Qt.SolidPattern)) self.qp.drawRect(140 + self.width, 125 + 2 * self.height, 30, 40) #window on the door self.qp.setBrush(QBrush(QColor(173, 98, 23), Qt.SolidPattern)) self.qp.drawEllipse(173 + self.width, 160 + 2 * self.height, 4, 4) #door handle #variants of the window on the third floor self.qp.setBrush(QBrush(self.lightColor, Qt.SolidPattern)) if self.windowStyle == "Round window": diameter = 30 * (self.roofHeight / 50) #calculate proportion if diameter > 45: diameter = 45 #limit for normal design self.qp.drawEllipse(200 - diameter / 2 + self.width / 2, 200 - diameter / 2 - self.roofHeight * 0.45, diameter, diameter) self.qp.setPen(QPen(QColor(173, 98, 23), 3, Qt.SolidLine)) #window planks self.qp.drawLine(202 - diameter / 2 + self.width / 2, 200 - self.roofHeight * 0.45, 198 + diameter / 2 + self.width / 2, 200 - self.roofHeight * 0.45) self.qp.drawLine(200 + self.width / 2, 198 + diameter / 2 - self.roofHeight * 0.45, 200 + self.width / 2, 202 - diameter / 2 - self.roofHeight * 0.45) if self.windowStyle == "2-part window": left = QPolygonF([ QPointF(200 + self.width / 3, 195), QPointF(197 + self.width / 2, 195), QPointF(197 + self.width / 2, 210 - self.roofHeight / 1.04), QPointF(200 + self.width / 3, 210 - self.roofHeight / 1.5) ]) self.qp.drawPolygon(left) right = QPolygonF([ QPointF(200 + self.width * 2 / 3, 195), QPointF(203 + self.width / 2, 195), QPointF(203 + self.width / 2, 210 - self.roofHeight / 1.04), QPointF(200 + self.width * 2 / 3, 210 - self.roofHeight / 1.5) ]) self.qp.drawPolygon(right) #window on the first floor self.qp.setPen(QPen(Qt.black, 1, Qt.SolidLine)) self.qp.drawRect(210 + 2 / 5 * (self.width - 175), 110 + 2 * self.height - 1 / 5 * (self.height - 100), 75 + 2 / 5 * (self.width - 175), 65 + 1 / 5 * (self.height - 100)) xc = 210 + 2 / 5 * (self.width - 175) + (75 + 2 / 5 * (self.width - 175)) / 2 yc = 110 + 2 * self.height - 1 / 5 * (self.height - 100) + (65 + 1 / 5 * (self.height - 100)) / 2 xr = 208 + 2 / 5 * (self.width - 175) + 75 + 2 / 5 * (self.width - 175) yd = 108 + 2 * self.height - 1 / 5 * ( self.height - 100) + 65 + 1 / 5 * (self.height - 100) self.qp.setPen(QPen(QColor(173, 98, 23), 3, Qt.SolidLine)) self.qp.drawLine(212 + 2 / 5 * (self.width - 175), yc, xr, yc) self.qp.drawLine(xc, 112 + 2 * self.height - 1 / 5 * (self.height - 100), xc, yd) #windows on the second floor self.qp.setPen(QPen(Qt.black, 1, Qt.SolidLine)) yc = 110 + self.height - 1 / 5 * (self.height - 100) yd = 65 + 1 / 5 * ( self.height - 100 ) #use our previous variables to make arguments shorter if self.roomNumber == 1: self.qp.drawRect(200 + self.width * 0.2, yc, self.width * 0.6, yd) self.qp.setPen(QPen(QColor(173, 98, 23), 3, Qt.SolidLine)) self.qp.drawLine(200 + self.width * 0.4, yc + 2, 200 + self.width * 0.4, yc + yd - 2) self.qp.drawLine(200 + self.width * 0.6, yc + 2, 200 + self.width * 0.6, yc + yd - 2) if self.roomNumber == 2: self.qp.drawRect(200 + self.width * 0.1, yc, self.width * 0.35, yd) self.qp.drawRect(200 + self.width * 0.55, yc, self.width * 0.35, yd) self.qp.setPen(QPen(QColor(173, 98, 23), 3, Qt.SolidLine)) self.qp.drawLine(200 + self.width * 0.275, yc + 2, 200 + self.width * 0.275, yc + yd - 2) self.qp.drawLine(200 + self.width * 0.725, yc + 2, 200 + self.width * 0.725, yc + yd - 2) self.qp.end() self.update() #need to draw again our image
def init_parameters(self): ''' 初始化系统参数,可读取系统配置文件 :return: ''' self.count = 0 self.resolution = QDesktopWidget().availableGeometry( ) # 获取显示器的分辨率-->(0, 0, 1366, 728) self.monitor = QDesktopWidget() # 获得显示器的物理尺寸 # self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint) # 任务栏隐藏图标 # 会议号 self.meetingID = 0 # 当前会议号 # 页数记录 self.page = 1 # 当前所在页页码 self.pages = 1 # 总页数 self.isWritting = False # 是否正在输入 self.isWritten = False # 记录当前页是否有新写入 ##########2018-6-12 添加########### self.httpRequest = HttpRequest() # http请求对象那 self.is_login = True # 用户是否登录 # self.shareThread = threading.Thread(target=self.meetingConnection, daemon=True) # 创建一个实时分享的线程 # self.shareThread.start() # 多线程改为多进程 self.shareThread = threading.Thread(target=self.self_check_net, daemon=True) # 创建一个实时分享的线程 self.shareThread.start() # print('# 创建一个实时分享的进程1') # self.shareProcess = multiprocessing.Process(target=self.self_check_net) # 创建一个实时分享的进程 # self.shareProcess.start() # print('# 创建一个实时分享的进程2') self.screenshotFullScreen = ScreenShotsWin() # 用于截全屏的对象 ##########2018-6-12 添加########### # 记录笔迹(坐标,颜色) self.penColor = 0 # 笔的初始颜色黑色 self.pos_xyc = [] # [((x, y), c)] c->0 1 2 3 self.pos_pages = {} # 存放所有页笔画路径{page : pos_xyc} # 设置不追踪鼠标 self.setMouseTracking(False) # 使用指定的画笔,宽度,钢笔样式,帽子样式和连接样式构造笔 self.pen = QPen(Qt.black, 4, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) # 画布pix self.pix = QPixmap(self.resolution.size()) self.pix.fill(Qt.white) self.pix = QPixmap(self.resolution.size()) self.pix.fill(Qt.white) # self.pix.save('原图.png') # 黑板擦 ''' 改用 eraseRect ,直接去掉笔画 void QPainter::eraseRect(const QRectF &rectangle) Erases the area inside the given rectangle. Equivalent to calling fillRect(rectangle, background()). ''' self.paintEase = QPainter(self) self.paintEase.setPen(QPen(Qt.black, Qt.DashLine)) self.paintEase.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # 是否擦除 self.eraseable = False # 起点终点 self.lastPoint = QPoint() self.endPoint = QPoint() self.icon = QIcon("icon\Icon.png") # 窗体图标 self.addSystemTray() # 设置系统托盘
class main(QMainWindow, Ui_MainWindow): def __init__(self): QWidget.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.flip_angle = 0 self.spantime = 0 self.play = False self.check = False self.stop = True self.count = 0 self.x = 0 self.y = 0 self.layout() def edit_flipangle(self): self.flip_angle = int(self.ui.FA_Edit_4.text()) def edit_spantime(self): self.spantime = int(self.ui.ST_Edit_5.text()) def linkedZoom(self, event): self.viewer.zoom(event) self.viewer2.zoom(event) # self.viewer3.zoom(event) def layout(self): self.plotWindow1 = self.ui.graph_t1 self.plotWindow2 = self.ui.graph_t2 self.ui.browse.clicked.connect(self.button_browse) #strat up cycle # self.ui.Ernst_Angle.clicked.connect(self.Init_start_up) self.ui.image.mousePressEvent = self.getPos self.ui.Contrast_slider.valueChanged.connect(self.contrast_change) self.ui.comboBox.currentIndexChanged.connect(self.artifacts) self.ui.Brightness_slider.valueChanged.connect(self.brightness_change) self.ui.property_2.currentIndexChanged.connect(self.select_image) self.ui.Zooming_Box.currentIndexChanged.connect(self.select_Zooming) self.ui.Ernst_Angle.clicked.connect(self.earnest_angle) self.viewer = PhotoViewer(self.ui.graphicsView_phantom) self.viewer2 = PhotoViewer(self.ui.graphicsView_seq1) # self.viewer3 = PhotoViewer(self.ui.graphicsView_seq2) self.ui.Start_seq1.clicked.connect(self.sequences) self.Gy = 2 * math.pi self.Start_up = True self.current_seq = "" # self.viewer.wheelEvent = self.linkedZoom # self.viewer2.wheelEvent = self.linkedZoom def button_browse(self): # try: self.size = int(self.ui.size_2.currentText()) self.filename, _filter = QFileDialog.getOpenFileName( self, "open file", " ", "Image File(*.png *.jpg *.jpeg *.bmp)") if self.filename: imagePath = self.filename imagePath = cv2.imread(self.filename, 0) self.size_image = (len(imagePath)) if (self.size == self.size_image): self.plotWindow1.clear() self.plotWindow2.clear() self.ui.image.clear() imagePath = gray2qimage(imagePath) #b7wel el array le image self.Image_in_graphic_veiw(imagePath) self.show_image(imagePath) self.ui.image.setToolTip("Click to select the pixel") self.stop = True self.count = 0 self.check = False self.Start_up = True self.img_array = cv2.imread(self.filename, 0) ###???? self.T1 = np.zeros((self.size_image, self.size_image)) self.T2 = np.zeros((self.size_image, self.size_image)) self.PD = np.copy(self.img_array) ####??????? n = self.size_image if (n == 64): for i in range(n): for j in range(n): # print("b",b) if self.img_array[i, j] == 0: self.T1[i, j] = 250 self.T2[i, j] = 70 elif self.img_array[i, j] == 21: self.T1[i, j] = 400 self.T2[i, j] = 5 elif self.img_array[i, j] == 63: self.T1[i, j] = 900 self.T2[i, j] = 90 elif self.img_array[i, j] == 255: self.T1[i, j] = 4000 self.T2[i, j] = 2000 else: for i in range(n): for j in range(n): if (self.img_array[i, j] > 0 and self.img_array[i, j] < 20): self.T1[i, j] = 500 self.T2[i, j] = 100 elif (self.img_array[i, j] > 20 and self.img_array[i, j] < 180): self.T1[i, j] = 1000 self.T2[i, j] = 120 elif (self.img_array[i, j] > 180 and self.img_array[i, j] < 255): self.T1[i, j] = 1500 self.T2[i, j] = 150 else: print("size doesn't match") QMessageBox.warning(self, "Message", "size doesn't match") # except: # QMessageBox.warning(self,"Message","Chosse the size of pic") # # QApplication.processEvents() def select_image(self): if (self.ui.property_2.currentText() == "T1"): array = (self.T1 - np.amin(self.T1)) * 255 / (np.amax(self.T1) - np.amin(self.T1)) image_T1 = gray2qimage(array) ### byh7wel el array to image self.show_image(image_T1) elif (self.ui.property_2.currentText() == "T2"): array = (self.T2 - np.amin(self.T2)) * 255 / (np.amax(self.T2) - np.amin(self.T2)) image_T2 = gray2qimage(array) self.show_image(image_T2) elif (self.ui.property_2.currentText() == "Phantom"): image_phantom = gray2qimage(self.img_array) self.show_image(image_phantom) def select_Zooming(self): if (self.ui.Zooming_Box.currentText() == "With Link"): self.viewer.wheelEvent = self.linkedZoom self.viewer2.wheelEvent = self.linkedZoom # self.viewer3.wheelEvent = self.linkedZoom elif (self.ui.Zooming_Box.currentText() == "Without Link"): self.viewer.wheelEvent = self.viewer.zoom self.viewer2.wheelEvent = self.viewer2.zoom # self.viewer3.wheelEvent =self.viewer3.zoom def sequences(self): self.select_Preparetion() self.select_Acquisition() def select_Preparetion(self): row = self.size_image col = self.size_image if (self.ui.Preparetion_Box.currentText() == "T1 Prep (IR)"): self.t_null() self.IR() self.phantom = self.createPhantom(row, col) Tnull = self.tnull self.phantom = self.T1_preparation(self.phantom, row, col, Tnull, self.T1, self.T2) elif (self.ui.Preparetion_Box.currentText() == "T2 Prep"): self.T2_PREP() self.phantom = self.createPhantom(row, col) self.phantom = self.T2_preparation(self.time, self.T1, self.T2, row, col, self.phantom) elif (self.ui.Preparetion_Box.currentText() == "Tagging Prep"): self.Tagging() self.phantom = self.createPhantom(row, col) self.phantom = self.tagging(row, col, self.phantom) def select_Acquisition(self): row = self.size_image col = self.size_image TE = int(self.ui.TE_Edit.text()) TR = int(self.ui.TR_Edit.text()) if (self.ui.Acquisition_Box.currentText() == "GRE"): self.flipAngle() flip_angle = self.flipangle theta = np.radians(flip_angle) self.gre() image_reconstruction = self.GRE(theta, row, col, TE, TR, self.img_array.shape[0], self.img_array.shape[1], self.T2, self.T1, self.phantom, self.Gy, self.Start_up) elif (self.ui.Acquisition_Box.currentText() == "SSFP"): self.flipAngle() flip_angle = self.flipangle theta = np.radians(flip_angle) self.ssfp() image_reconstruction = self.SSFP(theta, row, col, TE, TR, self.img_array.shape[0], self.img_array.shape[1], self.T2, self.T1, self.phantom, self.Gy, self.Start_up) elif (self.ui.Acquisition_Box.currentText() == "SE"): self.SE() image_reconstruction = self.spin_Echo(row, col, TE, TR, self.img_array.shape[0], self.img_array.shape[1], self.T2, self.T1, self.phantom, self.Gy, self.Start_up) self.viewer2.setPhoto(QPixmap(image_reconstruction)) def Image_in_graphic_veiw(self, image): self.viewer.setPhoto(QPixmap(image)) def adjust_brightness(self, input_image, factor): image = Image.open(input_image).convert('L') enhancer_object = ImageEnhance.Brightness(image) out = enhancer_object.enhance(factor) out.save("hi2.png") self.show_image("hi2.png") def adjust_contrast(self, input_image, factor): image = Image.open(input_image).convert('L') enhancer_object = ImageEnhance.Contrast(image) out = enhancer_object.enhance(factor) out.save("hi.png") self.show_image("hi.png") def show_image(self, image): self.result = QPixmap(image) #piexel of image result = self.result.scaled( int(self.ui.image.height()), int(self.ui.image.width()), QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation) #scale 3la elabel self.ui.image.setPixmap(result) #label ya5od el sora w yezherha def contrast_change(self): self.contrast_value = self.ui.Contrast_slider.value() self.adjust_contrast(self.filename, self.contrast_value) def brightness_change(self): self.brightness_value = self.ui.Brightness_slider.value() self.adjust_brightness(self.filename, self.brightness_value) def getPos(self, event): if (self.count == 5): self.check = False print("done") else: print(int(self.ui.image.height())) self.x = math.floor((event.pos().x() * self.size) / self.ui.image.frameGeometry().width()) print(self.x) self.y = math.floor((event.pos().y() * self.size) / self.ui.image.frameGeometry().height()) print(self.y) try: # self.flip_angle=self.flipangle # self.time_spin=int(self.ui.spin_Edit.text()) self.TR = int(self.ui.TR_Edit.text()) self.TE = int(self.ui.TE_Edit.text()) self.check = True self.draw(self.T1, self.T2, self.x, self.y) except: QMessageBox.warning( self, "Message", "Enter the flip angle, spin time, TR and TE") def draw(self, t1, t2, x, y): arr1 = [] arr2 = [] while (self.check): # self.TR=int(self.ui.TR_Edit.text()) # self.TE=int(self.ui.TE_Edit.text()) for self.t in range(self.spantime): theta = np.radians(self.flip_angle) M0 = ([[0], [0], [1]]) Flip = ([[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [-np.sin(theta), 0, np.cos(theta)]]) Decay = ([[np.exp(-self.t / self.T2[self.x, self.y]), 0, 0], [0, np.exp(-self.t / self.T2[self.x, self.y]), 0], [0, 0, np.exp(-self.t / self.T1[self.x, self.y])]]) M_Recovery = ([[0], [0], [1 - np.exp(-self.t / self.T1[self.x, self.y])] ]) out1 = (np.dot(Decay, Flip)) out2 = np.dot(out1, M0) self.MX, self.MY, self.MZ = out2 + M_Recovery arr1.extend( self.MX) #decay time #extend >>merge between array arr2.extend(self.MZ) #recovery time if (self.count == 0): self.plotWindow1.plot(arr1, pen='r') self.plotWindow2.plot(arr2, pen='r') elif (self.count == 1): self.plotWindow1.plot(arr1, pen='b') self.plotWindow2.plot(arr2, pen='b') elif (self.count == 2): self.plotWindow1.plot(arr1, pen='g') self.plotWindow2.plot(arr2, pen='g') elif (self.count == 3): self.plotWindow1.plot(arr1, pen='r') self.plotWindow2.plot(arr2, pen='r') else: self.plotWindow1.plot(arr1, pen='b') self.plotWindow2.plot(arr2, pen='b') self.plotWindow1.plot([self.TE, self.TE], (1, 0), pen='g') self.plotWindow1.plot([self.TR, self.TR], (1, 0), pen='r') self.plotWindow2.plot([self.TR, self.TR], (1, 0), pen='r') self.plotWindow2.plot([self.TE, self.TE], (1, 0), pen='g') self.check = False ## da ely hy5rgny mn el loop bta3t el loop self.count = self.count + 1 QApplication.processEvents() self.frame() def flipAngle(self): self.flipangle, ok = QInputDialog.getInt(self, "integer input dialog", "enter a theta") def t_null(self): self.tnull, ok = QInputDialog.getInt(self, "integer input dialog", "enter T NULL") def frame(self): QApplication.processEvents() self.painterInstance = QPainter(self.result) #b3mel opject self.painterInstance.begin(self) self.penRectangle = QPen(QtCore.Qt.red) #yehdd el elon self.penRectangle.setWidth(1) self.penPoint = QPen(QtCore.Qt.blue) self.penPoint.setWidth(1) # self.painterInstance.setPen(self.penPoint) #apply el lon self.painterInstance.drawRect(self.x, self.y, 1, 1) self.painterInstance.setPen(self.penRectangle) self.painterInstance.drawRect(self.x - 5, self.y - 5, 10, 10) self.painterInstance.end() result = self.result.scaled( int(self.ui.image.height()), int(self.ui.image.width()), QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation) #scale 3la elabel self.ui.image.setPixmap(result) self.painterInstance.end() QApplication.processEvents() def recovery_equation(self, phantom, TR, T1): phantom[2][0] = np.exp(-TR / T1) * phantom[2][0] + (1 - np.exp(-TR / T1)) return phantom def earnest_angle(self): self.lb = QGraphicsView() self.lb = pg.PlotWidget() phantom = [[0], [0], [1]] step = 1 intenisty = np.zeros(int(180 / step)) j = 0 for theta in range(0, 180, step): for i in range(10): phantom = self.rotate(np.radians(theta), phantom) phantom = self.decay(phantom, 100, 50) phantom = self.recovery_equation(phantom, 100, 2000) x = phantom[0][0] y = phantom[1][0] intenisty[j] = math.sqrt((x * x) + (y * y)) j = j + 1 array = np.arange(0, 180, step) self.lb.plot(array, intenisty) self.lb.show() def T2_preparation(self, Tw, T1, T2, row, col, phantom): #Create_array_of_magnetic_field_in_z_direction [h, w] = np.shape(T1) Phantom = np.zeros([h, w, 3]) Phantom[:, :, 2] = 1 RF1 = np.array([[1, 0, 0], [0, math.cos(math.pi / 2), math.sin(math.pi / 2)], [0, -math.sin(math.pi / 2), math.cos(math.pi / 2)] ]) # Rotate around x-axis with angle 90 RF2 = np.array([[1, 0, 0], [0, math.cos(-math.pi / 2), math.sin(-math.pi / 2)], [0, -math.sin(-math.pi / 2), math.cos(-math.pi / 2)] ]) # Rotate around x-axis with angle 180 for i in range(h): for j in range(w): decayrecovery = np.array([[np.exp(-Tw / T2[i, j]), 0, 0], [0, np.exp(-Tw / T2[i, j]), 0], [0, 0, 1 - np.exp(-Tw / T1[i, j])]]) Phantom[i, j, :] = np.dot(RF1, Phantom[ i, j, :]) # Phantom after rotation around 90 around x-axis Phantom[i, j, :] = np.dot( decayrecovery, Phantom[i, j, :]) + np.array([ 0, 0, 1 - np.exp(-Tw / T1[i, j]) ]) # Phantom after decay at x-y plane (on y-axis) Phantom[i, j, :] = np.dot( RF2, Phantom[i, j, :] ) # Phantom after rotation around 90 then 180 around x-axis print("loading") print("done") return phantom def T1_preparation(self, phantom, row, col, Tnull, T1, T2): #Create_array_of_magnetic_field_in_z_direction [h, w] = np.shape(T1) Phantom = np.zeros([h, w, 3]) Phantom[:, :, 2] = 1 Ti = np.log(2) * Tnull RF1 = np.array([[1, 0, 0], [0, math.cos(math.pi), math.sin(math.pi)], [0, -math.sin(math.pi), math.cos(math.pi)] ]) # Rotate around x-axis with angle 180 for i in range(h): for j in range(w): IR = np.array([[np.exp(-Ti / T2[i, j]), 0, 0], [0, np.exp(-Ti / T2[i, j]), 0], [0, 0, 1 - np.exp(-Ti / T1[i, j])]]) Phantom[i, j, :] = np.dot(RF1, Phantom[ i, j, :]) # Phantom after rotation around 180 around x-axis Phantom[i, j, :] = np.dot(IR, Phantom[i, j, :]) + np.array([ 0, 0, 1 - np.exp(-Ti / T1[i, j]) ]) # Phantom after decay at x-y plane (on y-axis) print("loading") print("done") return phantom def RF_rotate(self, theta, phantom, row, col): for i in range(row): for j in range(col): phantom[i, j, :] = self.rotate(theta, phantom[i, j, :]) return phantom def rotate(self, theta, phantom): RF = ([[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [-np.sin(theta), 0, np.cos(theta)]]) phantom = np.dot(RF, phantom) return phantom def decay(self, phantom, TE, T2): dec = np.exp(-TE / T2) phantom = np.dot(dec, phantom) return phantom def rotate_decay(self, phantom, theta, TE, T2, row, col): for i in range(row): for j in range(col): phantom[i, j, :] = self.rotate(theta, phantom[i, j, :]) phantom[i, j, :] = self.decay(phantom[i, j, :], TE, T2[i, j]) return phantom def tagging(self, row, col, phantom): for i in range(row): for c in range(col): theta = (i * math.pi) / row sinangle = np.sin(theta) phantom[i, c, :] = phantom[i, c, :] * sinangle return phantom def recovery(self, phantom, row, col, TR, T1): for ph_rowtr in range(row): for ph_coltr in range(col): phantom[ph_rowtr, ph_coltr, 0] = 0 phantom[ph_rowtr, ph_coltr, 1] = 0 phantom[ph_rowtr, ph_coltr, 2] = ((phantom[ph_rowtr, ph_coltr, 2]) * np.exp(-TR / T1[ph_rowtr, ph_coltr])) + ( 1 - np.exp(-TR / T1[ph_rowtr, ph_coltr])) return phantom def createPhantom(self, row, col): phantom = np.zeros((row, col, 3)) for i in range(row): for j in range(col): phantom[i, j, 2] = 1 return phantom def startup_cycle(self, phantom, theta, TE, TR, T2, T1, row, col, n): for r in range(n): #rows phantom = self.rotate_decay(phantom, theta, TE, T2, row, col) phantom = self.recovery(phantom, row, col, TR, T1) return phantom def SSFP(self, theta, row, col, te, tr, image_shape0, image_shape1, T2, T1, phantom, Gy, Start_up): Kspace_ssfp = np.zeros((image_shape0, image_shape1), dtype=np.complex_) if (Start_up == True): phantom = Fast.startup_cycle(phantom, theta / 2, te, tr, T2, T1, row, col, 1) phantom = Fast.startup_cycle(phantom, theta, te, tr, T2, T1, row, col, 15) for r in range(Kspace_ssfp.shape[0]): #rows theta = -theta phantom = Fast.rotate_decay(phantom, theta, te, T2, row, col) for c in range(Kspace_ssfp.shape[1]): Gx_step = ((2 * math.pi) / row) * r Gy_step = (Gy / col) * c for ph_row in range(row): for ph_col in range(col): Toltal_theta = (Gx_step * ph_row) + (Gy_step * ph_col) Mag = math.sqrt(((phantom[ph_row, ph_col, 0]) * (phantom[ph_row, ph_col, 0])) + ((phantom[ph_row, ph_col, 1]) * (phantom[ph_row, ph_col, 1]))) Kspace_ssfp[r, c] = Kspace_ssfp[r, c] + ( Mag * np.exp(-1j * Toltal_theta)) QApplication.processEvents() QApplication.processEvents() print(theta) for ph_rowtr in range(row): for ph_coltr in range(col): self.phantom[ph_rowtr, ph_coltr, 0] = 0 self.phantom[ph_rowtr, ph_coltr, 1] = 0 self.phantom[ph_rowtr, ph_coltr, 2] = ( (phantom[ph_rowtr, ph_coltr, 2]) * np.exp(-tr / T1[ph_rowtr, ph_coltr])) + ( 1 - np.exp(-tr / T1[ph_rowtr, ph_coltr])) QApplication.processEvents() iff = np.fft.ifft2(Kspace_ssfp) #print(iff) inverse_array = np.abs(iff) inverse_array = (inverse_array - np.amin(inverse_array)) * 255 / ( np.amax(inverse_array) - np.amin(inverse_array)) inverse_img = gray2qimage(inverse_array) imgreconstruction = inverse_img return imgreconstruction #self.viewer2.setPhoto(QPixmap(imgreconstruction)) def Aliasing_artifact(self): self.Gy = np.radians(540) def spin_Echo(self, row, col, te, tr, image_shape0, image_shape1, T2, T1, phantom, Gy, Start_up): theta = np.radians(90) Kspace_SE = np.zeros( (self.img_array.shape[0], self.img_array.shape[1]), dtype=np.complex_) if (Start_up == True): phantom = self.startup_cycle(phantom, theta, te, tr, T2, T1, row, col, 15) for r in range(Kspace_SE.shape[0]): #rows phantom = self.rotate_decay(phantom, np.radians(90), te / 2, T2, row, col) phantom = self.recovery(phantom, row, col, te / 2, self.T1) phantom = self.rotate_decay(phantom, np.radians(180), te / 2, T2, row, col) for c in range(Kspace_SE.shape[1]): Gx_step = ((2 * math.pi) / row) * r Gy_step = (Gy / col) * c for ph_row in range(row): for ph_col in range(col): Toltal_theta = (Gx_step * ph_row) + (Gy_step * ph_col) Mag = math.sqrt(((phantom[ph_row, ph_col, 0]) * (phantom[ph_row, ph_col, 0])) + ((phantom[ph_row, ph_col, 1]) * (phantom[ph_row, ph_col, 1]))) Kspace_SE[r, c] = Kspace_SE[r, c] + ( Mag * np.exp(-1j * Toltal_theta)) QApplication.processEvents() QApplication.processEvents() phantom = self.recovery(phantom, row, col, tr, T1) QApplication.processEvents() iff = np.fft.ifft2(Kspace_SE) inverse_array = np.abs(iff) inverse_array = (inverse_array - np.amin(inverse_array)) * 255 / ( np.amax(inverse_array) - np.amin(inverse_array)) inverse_img = gray2qimage(inverse_array) imgreconstruction = inverse_img return imgreconstruction #self.viewer2.setPhoto(QPixmap(imgreconstruction)) def artifacts(self): if (self.ui.comboBox.currentText() == "Bluring"): self.Start_up = False self.sequences() if (self.ui.comboBox.currentText() == "Alaising"): self.Gy = np.radians(540) self.sequences() def GRE(self, theta, row, col, te, tr, image_shape0, image_shape1, T2, T1, phantom, Gy, Start_up): Kspace = np.zeros((image_shape0, image_shape1), dtype=np.complex_) if (Start_up == True): phantom = Fast.startup_cycle(phantom, theta, te, tr, T2, T1, row, col, 15) for r in range(Kspace.shape[0]): #rows phantom = Fast.rotate_decay(phantom, theta, te, T2, row, col) for c in range(Kspace.shape[1]): #columns Gx_step = ((2 * math.pi) / row) * r Gy_step = ((Gy) / col) * c for ph_row in range(row): for ph_col in range(col): Toltal_theta = (Gx_step * ph_row) + (Gy_step * ph_col) Mag = math.sqrt(((phantom[ph_row, ph_col, 0]) * (phantom[ph_row, ph_col, 0])) + ((phantom[ph_row, ph_col, 1]) * (phantom[ph_row, ph_col, 1]))) Kspace[r, c] = Kspace[r, c] + (Mag * np.exp(-1j * Toltal_theta)) QApplication.processEvents() QApplication.processEvents() phantom = Fast.recovery(phantom, row, col, tr, T1) QApplication.processEvents() iff = np.fft.ifft2(Kspace) inverse_array = np.abs(iff) inverse_array = (inverse_array - np.amin(inverse_array)) * 255 / ( np.amax(inverse_array) - np.amin(inverse_array)) inverse_img = gray2qimage(inverse_array) imgreconstruction = inverse_img return imgreconstruction #self.viewer2.setPhoto(QPixmap(imgreconstruction)) def IR(self): self.ui.GV_prep.clear() tx = np.arange(0, 200, .001) T3 = (np.sin(1.5 * (tx - 10)) / (tx - 10)) self.ui.GV_prep.plot(tx, T3, pen='r') #self.ui.lbl_prep.setText("Prepration:IR") def gre(self): #self.AQUA=self.GRE self.te = int(self.ui.TE_Edit.text()) self.tr = int(self.ui.TR_Edit.text()) self.f = self.flipangle te = round(self.te / 3) self.ui.GV_aqua.clear() tx = np.arange(0, self.tr) Rf = (np.sin(((self.f * 2) / 180) * (tx - te)) / (tx - te) + 12) Gz = self.RectangularGraph(self.tr, 10, (te), 1, te) Gy = self.RectangularGraph(self.tr, 8, (te * 2), 1, te) Gx = self.RectangularGraph(self.tr, 6, (te * 3), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 3), 1, te) self.ui.GV_aqua.plot(tx, Rf, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gz, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gy, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gx, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Readout, pen=[255, 0, 0]) def Tagging(self): self.ui.GV_aqua.clear() tx = np.arange(0, 15, .001) T3 = (0.5 * np.sin(2 * tx)) #RF 180 shifted 2 self.ui.GV_prep.plot(tx, T3, pen=[255, 0, 0]) def T2_PREP(self): self.ui.GV_prep.clear() self.time, ok = QInputDialog.getInt(self, "T_Dialog", "Enter the Required time") tx = np.arange(0, 70, .001) T1 = (np.sin((tx - 10)) / (tx - 10)) T2 = (np.sin(-(tx - self.time)) / (tx - self.time)) self.ui.GV_prep.plot(tx, T1, pen='r') self.ui.GV_prep.plot(tx, T2, pen='r') #self.ui.lbl_prep.setText("Prepration:T2_PREP") def SE(self): self.te = int(self.ui.TE_Edit.text()) self.tr = int(self.ui.TR_Edit.text()) self.f = np.radians(90) self.ui.GV_aqua.clear() tx = np.arange(0, self.tr) te = round(self.te / 3) Rf = (np.sin(((self.f * 2) / 180) * (tx - te)) / (tx - te) + 12) Rf2 = (2 * np.sin( ((self.f * 2) / 180) * (tx - (te * 2))) / (tx - (te * 2)) + 12) Gz = self.RectangularGraph(self.tr, 10, (te), 1, te) Gy = self.RectangularGraph(self.tr, 8, (te * 2), 1, te) Gx = self.RectangularGraph(self.tr, 6, (te * 3), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 3), 1, te) self.ui.GV_aqua.plot(tx, Rf, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Rf2, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gz, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gy, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gx, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Readout, pen=[255, 0, 0]) def ssfp(self): self.te = int(self.ui.TE_Edit.text()) self.tr = int(self.ui.TR_Edit.text()) self.f = self.flipangle te = round(self.te / 3) self.ui.GV_aqua.clear() tx = np.arange(0, self.tr) Rf = (np.sin( ((self.flip_angle * 2) / 180) * (tx - te)) / (tx - te) + 12) Gz = self.RectangularGraph(self.tr, 10, (te), 1, te) Gy = self.RectangularGraph(self.tr, 8, (te * 2), 1, te) Gx = self.RectangularGraph(self.tr, 6, (te * 3), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 3), 1, te) RGx = self.RectangularGraph(self.tr, 8, (te * 4), -1, te) RGy = self.RectangularGraph(self.tr, 6, (te * 4), -1, te) self.ui.GV_aqua.plot(tx, Rf, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gz, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gy, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gx, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Readout, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Rf, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gx, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Gy, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, Readout, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, RGx, pen=[255, 0, 0]) self.ui.GV_aqua.plot(tx, RGy, pen=[255, 0, 0]) def RectangularGraph(self, tR, shiftDown, shiftRight, step, width): z = [] for i in range(0, tR): if i < int(shiftRight): z.append(shiftDown) elif i >= int(shiftRight) and i < int(width + shiftRight): z.append(shiftDown + (step * 1)) else: z.append(shiftDown) return z
def __init__(self, parent=None, config_filename=os.path.join('data', 'kerbalpie.cfg'), debug_on=False): super(KerbalPie, self).__init__(parent) uic.loadUi(os.path.join('data', 'KerbalPie.ui'), self) # Set up KerbalPie application #----------------------------------------------------------------------- # parse configuration options self.config = self._parse_config(config_filename) # general message logging #----------------------------------------------------------------------- self._logger_thread = Logger( log_dir=self.config['logger_directory'], log_name=self.config['logger_filename'], debug_on=True) self._logger_thread.start() # serial interface #----------------------------------------------------------------------- # interface thread self._serial_thread = QtCore.QThread() self._serial_iface = KPSerialInterface( serial_port=self.config['serial_port'], serial_baudrate=self.config['serial_baudrate']) self._serial_iface.moveToThread(self._serial_thread) # flight controller #----------------------------------------------------------------------- # controller thread self._flight_thread = QtCore.QThread() self._flight_ctrl = KPFlightController( krpc_address=self.config['krpc_address'], krpc_rpc_port=self.config['krpc_rpc_port'], krpc_stream_port=self.config['krpc_stream_port'], krpc_name=self.config['krpc_client_name']) self._flight_ctrl.moveToThread(self._flight_thread) # GUI elements #----------------------------------------------------------------------- # serial interface thread connections self._serial_thread.started.connect(self._serial_iface.process) self._serial_iface.finished.connect(self._serial_thread.quit) self._serial_iface.finished.connect(self._serial_iface.deleteLater) self._serial_thread.finished.connect(self._serial_thread.deleteLater) # serial interface connections self.serial_iface_begin_connect.connect(self._serial_iface.connect) self.serial_iface_begin_disconnect.connect(self._serial_iface.disconnect) self._serial_iface.connected.connect(self.serial_connected) self._serial_iface.disconnected.connect(self.serial_disconnected) self.serial_connectionButton.clicked.connect(self.serial_connectionButton_clicked) self.serial_portEdit.textChanged.connect(self.serial_port_changed) self.serial_baudRateEdit.textChanged.connect(self.serial_baudrate_changed) # PID controller panels self.flightControl_tuningTabGroup = QTabWidget(parent=None) self.flightControl_pidControllerPanels = [] for ctrl in self._flight_ctrl.controllers: ctrl_panel = QPidControllerPanel(ctrl, parent=None) self.flightControl_tuningTabGroup.addTab(ctrl_panel, ctrl.name) self.flightControl_pidControllerPanels.append(ctrl_panel) self.flightControl_tuningGroup.layout().addWidget(self.flightControl_tuningTabGroup) # flight controller thread connections self._flight_thread.started.connect(self._flight_ctrl.process) self._flight_ctrl.finished.connect(self._flight_thread.quit) self._flight_ctrl.finished.connect(self._flight_ctrl.deleteLater) self._flight_thread.finished.connect(self._flight_thread.deleteLater) # flight controller connections self._flight_ctrl.telemetry_updated.connect(self.flight_telemetry_updated) self.krpc_client_begin_connect.connect(self._flight_ctrl.krpc_connect) self.krpc_client_begin_disconnect.connect(self._flight_ctrl.krpc_disconnect) self._flight_ctrl.krpc_connected.connect(self.krpc_client_connected) self._flight_ctrl.krpc_disconnected.connect(self.krpc_client_disconnected) self.krpc_connectionButton.clicked.connect(self.krpc_connectionButton_clicked) self.krpc_addressEdit.textChanged.connect(self.krpc_client_address_changed) self.krpc_rpcPortEdit.textChanged.connect(self.krpc_client_rpc_port_changed) self.krpc_streamPortEdit.textChanged.connect(self.krpc_client_stream_port_changed) self._serial_iface.rc_command.connect(self._flight_ctrl.rc_command_received) # start threads self._flight_thread.start() self._serial_thread.start() # flight data display #----------------------------------------------------------------------- # gui items self.flightPlot_selection.addItems([ "Vertical Speed", "Altitude" "Attitude" ]) self.flight_data_model = KPFlightDataModel(parent=self) self.flightData_tableView.setModel(self.flight_data_model) self.flightData_tableView.verticalHeader().setVisible(False) self.flightData_tableView.verticalHeader().sectionResizeMode(QHeaderView.Fixed) self.flightData_tableView.resizeColumnsToContents() self.flightData_tableView.resizeRowsToContents() self.flightData_tableView.setColumnWidth(2, 120) # flight data plotter #----------------------------------------------------------------------- pal = QPalette(self.palette()) pal.setColor(QPalette.Background, Qt.white) self.controllerPlotter = QPlot2DTime( timeSpan=30.0, yMin=-2.0, yMax=2.0, yOriginValue=0.0, xTickInterval=5.0, yTickInterval=0.5, labelFont=QFont("Segoe UI", 10), refreshRate=0.1) self.controllerPlotter.setPlotDrawMethod(0, 'line') self.flightPlot_plotGroup.layout().addWidget(self.controllerPlotter) self.flightPlot_selection.currentTextChanged.connect(self.flightPlot_selection_changed) # mission programs table #----------------------------------------------------------------------- self.mission_program_db = KPMissionProgramsDatabase(parent=self) self.mission_programs_model = KPMissionProgramsModel(mp_database=self.mission_program_db, parent=self) self.mission_programTableView.setModel(self.mission_programs_model) self.mission_programTableView.verticalHeader().setVisible(False) self.mission_programTableView.verticalHeader().sectionResizeMode(QHeaderView.Fixed) self.mission_programTableView.resizeColumnsToContents() self.mission_programTableView.resizeRowsToContents() self.mission_programTableView.setSelectionMode(QAbstractItemView.SingleSelection) self.mission_program_db.current_program_updated.connect(self.mission_programs_model.set_active_program) self.mission_program_db.current_program_updated.connect(self._flight_ctrl.set_active_program) self.mission_activateButton.clicked.connect(self.mission_activateButton_clicked) self.mission_program_db.set_current_program_num(0) self._flight_ctrl.request_mp_change.connect(self.flight_requested_mp_change) # automatically start KRPC connection QTimer.singleShot(200, self.krpc_connectionButton_clicked) # automatically start serial port connection QTimer.singleShot(300, self.serial_connectionButton_clicked) # debug #----------------------------------------------------------------------- self.radarPlotter = QPlot2D( xMin=-1.0, xMax=1.0, yMin=-1.0, yMax=1.0, xOriginValue=0.0, yOriginValue=0.0, xTickInterval=0.1, yTickInterval=0.1) radarLayout = QVBoxLayout() radarLayout.addWidget(self.radarPlotter) self.radarTab.setLayout(radarLayout) self._radarPlotColorBins = 60 radarPlotColor = QColor() for i in range(self._radarPlotColorBins): hue = map_value_to_scale(float(i), 0.0, float(self._radarPlotColorBins), 0.0, 0.2) radarPlotColor.setHsvF(hue, 1.0, 1.0) self.radarPlotter.setPlotPen(i, QPen(radarPlotColor, 15.0, Qt.SolidLine, Qt.RoundCap)) self.radarPlotter.setPlotPen(self._radarPlotColorBins, QPen(Qt.blue, 15.0, Qt.SolidLine, Qt.RoundCap))
class AnimatedText(QGraphicsObject): def __init__(self, text, parent=None): super().__init__(parent=parent) self.parent = parent self.actual_text = text self.shown_text = '' self.delay = 3 # Set up pens for drawing self.default_pen = QPen() self.default_pen.setColor(Qt.white) self.shown_length = 0 # Set up the length to be animated self.anim = QPropertyAnimation(self, b'shown_length') self.anim.setDuration(len(self.actual_text) * 50) # Animation speed self.anim.setStartValue(0) for t in range(1, 10): self.anim.setKeyValueAt( t / 10, (len(self.actual_text) + self.delay) * t / 10) self.anim.setEndValue(len(self.actual_text) + self.delay) self.visibleChanged.connect(self.show_text) def show_text(self): if self.isVisible(): self.toggle_anim(True) else: self.shown_length = 0 # Toggle the animation to be play forward or backward def toggle_anim(self, toggling): if toggling: self.anim.setDirection(QAbstractAnimation.Forward) else: self.anim.setDirection(QAbstractAnimation.Backward) self.anim.start() def boundingRect(self): return self.parent.boundingRect() def paint(self, painter, style, widget=None): painter.setPen(self.default_pen) painter.drawText(self.parent.boundingRect(), Qt.AlignCenter, self.shown_text) # Defining the length to be drawn as a pyqtProperty @pyqtProperty(int) def shown_length(self): return self._shown_length # Determine the length of the four lines to be drawn @shown_length.setter def shown_length(self, value): self._shown_length = value if value < self.delay: # All printed text should be garbage garbage = [ chr(num) for num in [random.choice(range(33, 127)) for _ in range(value)] ] self.shown_text = ''.join(garbage) else: # Printed text contain some actual text garbage = [ chr(num) for num in [ random.choice(range(33, 127)) for _ in range( min( len(self.actual_text) + self.delay - value, self.delay)) ] ] self.shown_text = self.actual_text[:value - self.delay] + ''.join(garbage) self.update()
class QMComboBox(QComboBox): image = QImage( 'Client/MyQt/Window/Main/icons/baseline_arrow_drop_down_black_18dp.png' ) default_pen = QPen(QColor(0, 0, 0)) hovered_pen = QPen(Color.primary) hovered_pen.setWidth(3) current_changed = pyqtSignal( 'PyQt_PyObject', 'PyQt_PyObject') # real signature (List[Lesson], T) label: str def formatter(self, item: T) -> str: if hasattr(self.type, 'formatter'): return self.type.formatter(item) raise NotImplementedError() def sorter(self, item: T) -> Any: if hasattr(self.type, 'sorter'): return self.type.sorter(item) raise NotImplementedError() @pyqtSlot(int, name='resignal') def resignal(self): if self.lessons is not None: self.current_changed.emit( Lesson.filter_lessons(self.current(), self.lessons), self.current()) @pyqtSlot('PyQt_PyObject', 'PyQt_PyObject', name='on_parent_change') def on_parent_change(self, lessons, parent_value): self.lessons = lessons if lessons is None or len(lessons) == 0: return data = sorted(self.type.of(lessons)) self.set_items(data) self.setCurrent(self.type.of(Lesson.closest_to_date(lessons))[0]) def __init__(self, type_: T = None, parent=None): super().__init__() self.setParent(parent) self.type = type_ self.lessons: List[Lesson] = list() self.currentIndexChanged.connect(self.resignal) self.items: List[T] = [] self.pending = None if issubclass(type_, Enum): self.addItems(type_) def setEngine(self, type_): self.type = type_ def addItems(self, iterable: List[T], p_str=None) -> None: for i, value in enumerate(iterable): self.items.append(value) self.setItemData(i, f"{type_name(value)}: {name(value)}", Qt.ToolTipRole) else: super().addItems([name(i) for i in iterable]) def current(self) -> _Displayable or None: try: return self.items[self.currentIndex()] except IndexError: return None def clear(self): super().clear() self.items = [] @pyqtSlot('PyQt_PyObject', name='setCurrent') def setCurrent(self, item: T): if len(self.items) == 0: return if isinstance(item, list): item = item[0] index = self.items.index(item) if index >= 0: self.setCurrentIndex(index) else: raise ValueError(f"{item} not in items") # def paintEvent(self, QPaintEvent): # p = QPainter(self) # # rect = QRectF(0, 0, self.width(), self.height()) # # # p.fillRect(rect, Color.secondary) # # p.setPen(self.default_pen if not self.underMouse() else self.hovered_pen) # p.drawLine(0, rect.height() - 3, rect.width(), rect.height() - 3) # # p.setPen(self.default_pen) # p.drawText(rect, Qt.AlignCenter, self.currentText()) # # p.drawImage(rect.width() - self.image.width(), self.height() // 2 - self.image.height() // 2, self.image) def set_items(self, items): self.blockSignals(True) self.clear() self.addItems(items) self.blockSignals(False) self.resignal() def loads(self, user): self.lessons = Lesson.of(user) self.on_parent_change(self.lessons, None) def __repr__(self): return f"QMComboBox of {self.type}"
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 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)
class Window(QMainWindow): def __init__(self): super().__init__() top = 400 left = 400 width = 1200 height = 500 self.maximum_undo = 20 self.obj_type = 'wall' self.obj_width = 10 self.pix_per_meter = 10 self.bgc = Qt.white self.shift_pressed = False icon = "icon.png" self.setGeometry(top, left, width, height) self.setWindowTitle("Map Designer") self.setWindowIcon(QIcon(icon)) self.setFixedSize(width, height) self.hidden_obstacle_layer = QImage(1000, 500, QImage.Format_RGB32) self.hidden_obstacle_layer.fill(self.bgc) self.backup_hidden_obstacle = [] self.backup_hidden_obstacle.append(self.hidden_obstacle_layer) self.temp_hidden_obstacle_layer = self.hidden_obstacle_layer self.hidden_railing_brush = QBrush(Qt.SolidPattern) self.hidden_railing_brush.setColor(Qt.red) self.hidden_wall_brush = QBrush(Qt.SolidPattern) self.hidden_wall_brush.setColor(Qt.black) self.hidden_pillar_brush = QBrush(Qt.SolidPattern) self.hidden_pillar_brush.setColor(Qt.green) self.hidden_counter_brush = QBrush(Qt.SolidPattern) self.hidden_counter_brush.setColor(Qt.blue) self.hidden_destination_layer = QImage(1000, 500, QImage.Format_RGB32) self.hidden_destination_layer.fill(self.bgc) self.backup_hidden_destination = [] self.backup_hidden_destination.append(self.hidden_destination_layer) self.temp_hidden_destination_layer = self.hidden_destination_layer self.hidden_exit_brush = QBrush(Qt.SolidPattern) self.hidden_exit_brush.setColor(Qt.red) self.hidden_entry_brush = QBrush(Qt.SolidPattern) self.hidden_entry_brush.setColor(Qt.black) self.hidden_passage_brush = QBrush(Qt.SolidPattern) self.hidden_passage_brush.setColor(Qt.green) self.hidden_waiting_brush = QBrush(Qt.SolidPattern) self.hidden_waiting_brush.setColor(Qt.blue) self.hidden_pen = QPen() self.hidden_pen.setColor(self.bgc) self.left_layout = QHBoxLayout() self.left_zone = QWidget(self) self.left_zone.setLayout(self.left_layout) self.image = QImage(1000, 500, QImage.Format_RGB32) self.image.fill(self.bgc) self.image_label = QLabel(self) self.image_label.setGeometry(0, 0, 1000, 500) self.image_label.setPixmap(QPixmap.fromImage(self.image)) self.left_layout.addWidget(self.image_label) self.left_layout.setSpacing(0) self.left_layout.setContentsMargins(0, 0, 0, 0) self.left_layout.setStretch(0, 0) self.left_layout.setGeometry(QRect(QPoint(0, 0), QPoint(1000, 500))) self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Horizontal) self.splitter.setContentsMargins(0, 0, 0, 0) self.splitter.setFixedSize(1200, 500) self.splitter.setHandleWidth(0) self.splitter.addWidget(self.left_zone) self.backup_image = [] self.backup_image.append(self.image) self.draw_record = [] self.temp_image = QImage(1000, 500, QImage.Format_RGB32) self.temp_image.fill(self.bgc) self.drawing = False self.lastPoint = QPoint() # mainMenu = self.menuBar() # mainMenu.setNativeMenuBar(False) # fileMenu = mainMenu.addMenu("File") # brushMenu = mainMenu.addMenu("Brush Size") # brushColor = mainMenu.addMenu("Brush Color") # # saveAction = QAction("Save", self) # saveAction.setShortcut("Ctrl+S") # fileMenu.addAction(saveAction) # # clearAction = QAction("Clear", self) # clearAction.setShortcut("Ctrl+C") # fileMenu.addAction(clearAction) # # px3Action = QAction("3px", self) # px3Action.setShortcut("Ctrl+3") # brushMenu.addAction(px3Action) # # px5Action = QAction("5px", self) # px5Action.setShortcut("Ctrl+5") # brushMenu.addAction(px5Action) # # px9Action = QAction("9px", self) # px9Action.setShortcut("Ctrl+9") # brushMenu.addAction(px5Action) # # blackAction = QAction("Black", self) # blackAction.setShortcut("Ctrl+B") # brushColor.addAction(blackAction) # # whiteAction = QAction("White", self) # whiteAction.setShortcut("Ctrl+W") # brushColor.addAction(whiteAction) # #按钮控件 # # self.btn_obstacle = QPushButton(self) # self.btn_obstacle.setGeometry(1020, 40, 20, 20) # self.btn_obstacle.setText("■") # self.btn_obstacle.setStyleSheet("QPushButton{color: black; padding-bottom: 2px;}" # "QPushButton:hover{background-color: darkgrey}") # # self.btn_dest = QPushButton(self) # self.btn_dest.setGeometry(1020, 80, 20, 20) # self.btn_dest.setText("■") # self.btn_dest.setStyleSheet("color: green; padding-bottom: 2px") #绘制选项 self.right_layout = QVBoxLayout() self.right_zone = QWidget(self) self.right_zone.setLayout(self.right_layout) self.splitter.addWidget(self.right_zone) #self.right_layout.addWidget(self.image_label) #0.坐标显示区 self.right_layout.addStretch() self.coordinates_label = QLabel(self) self.coordinates_label.setText("当前坐标(m): ") self.coordinates_label.setFont(QFont("Noto Sans CJK SC")) self.right_layout.addWidget(self.coordinates_label) self.coordinates_disp = QLabel(self) self.coordinates_disp.setText("坐标: x = 0.0, \ty = 0.0") self.coordinates_disp.setFont(QFont("Noto Sans CJK SC")) self.right_layout.addWidget(self.coordinates_disp) #1. 绘制障碍物标题 self.right_layout.addStretch() self.obstacle_label = QLabel(self) self.obstacle_label.setText("绘制障碍物: ") self.obstacle_label.setFont(QFont("Noto Sans CJK SC")) #self.obstacle_label.setGeometry(1010, 40, 100, 30) self.right_layout.addWidget(self.obstacle_label) self.obstacle_pen = QPen(Qt.SolidLine) self.obstacle_pen.setColor(Qt.black) #1.1 绘制护栏 #1.1.1 护栏选择框 self.select_railing = QRadioButton(self) self.select_railing.setText("护栏. ") self.select_railing.setFont(QFont("Noto Sans CJK SC")) self.select_railing.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_railing) #self.select_railing.setGeometry(1030, 65, 60, 30) #1.1.2 护栏笔刷 self.railing_brush = QBrush(Qt.BDiagPattern) self.railing_brush.setColor(Qt.darkGray) self.railing_width = 0.5 # 1.2.1 墙体选择框 self.wall_box = QHBoxLayout() self.select_wall = QRadioButton(self) self.select_wall.setText("墙体, ") self.select_wall.setFont(QFont("Noto Sans CJK SC")) self.select_wall.toggled.connect(self.drawTypeChange) #self.select_wall.setGeometry(1030, 90, 60, 30) self.wall_box.addWidget(self.select_wall) # 1.2.2 墙体笔刷 self.wall_brush = QBrush(Qt.Dense6Pattern) self.wall_brush.setColor(Qt.darkGray) self.wall_width = 1 #1.2.3 墙体宽度标签 self.wall_width_label = QLabel(self) self.wall_width_label.setText("宽度(m): ") self.wall_width_label.setFont(QFont("Noto Sans CJK SC")) #self.wall_width_label.setGeometry(1090, 90, 60, 30) self.wall_box.addWidget(self.wall_width_label) # 1.2.3 墙体宽度输入框 self.wall_width_input = QLineEdit(self) self.wall_width_input.setText("1") #self.wall_width_input.setGeometry(1140, 95, 30, 20) self.wall_width_input.setAlignment(Qt.AlignRight) self.wall_box.addWidget(self.wall_width_input) self.wall_width_input.textChanged.connect(self.widthChange) self.right_layout.addLayout(self.wall_box) # 1.3.1 立柱选择框 self.pillar_box = QHBoxLayout() self.select_pillar = QRadioButton(self) self.select_pillar.setText("立柱, ") self.select_pillar.setFont(QFont("Noto Sans CJK SC")) self.select_pillar.toggled.connect(self.drawTypeChange) #self.select_pillar.setGeometry(1030, 90, 60, 30) self.pillar_box.addWidget(self.select_pillar) # 1.3.2 立柱笔刷 self.pillar_brush = QBrush(Qt.Dense4Pattern) self.pillar_brush.setColor(Qt.darkGray) self.pillar_width = 1 # 1.3.3 立柱宽度标签 self.pillar_width_label = QLabel(self) self.pillar_width_label.setText("宽度(m): ") self.pillar_width_label.setFont(QFont("Noto Sans CJK SC")) # self.wall_width_label.setGeometry(1090, 90, 60, 30) self.pillar_box.addWidget(self.pillar_width_label) # 1.3.3 立柱宽度输入框 self.pillar_width_input = QLineEdit(self) self.pillar_width_input.setText("1") # self.wall_width_input.setGeometry(1140, 95, 30, 20) self.pillar_width_input.setAlignment(Qt.AlignRight) self.pillar_box.addWidget(self.pillar_width_input) self.pillar_width_input.textChanged.connect(self.widthChange) self.right_layout.addLayout(self.pillar_box) # 1.4.1 柜台选择框 #self.counter_box = QHBoxLayout() self.select_counter = QRadioButton(self) self.select_counter.setText("柜台. ") self.select_counter.setFont(QFont("Noto Sans CJK SC")) self.select_counter.toggled.connect(self.drawTypeChange) #self.select_counter.setGeometry(1030, 90, 60, 30) self.right_layout.addWidget(self.select_counter) #self.counter_box.addWidget(self.select_counter) # 1.4.2 柜台笔刷 self.counter_brush = QBrush(Qt.HorPattern) self.counter_brush.setColor(Qt.darkGray) self.counter_width = 1 # # 1.4.3 柜台宽度标签 # self.counter_width_label = QLabel(self) # self.counter_width_label.setText("宽度(m): ") # self.counter_width_label.setFont(QFont("Noto Sans CJK SC")) # # self.wall_width_label.setGeometry(1090, 90, 60, 30) # self.counter_box.addWidget(self.counter_width_label) # # 1.4.3 柜台宽度输入框 # self.counter_width_input = QLineEdit(self) # self.counter_width_input.setText("1") # # self.wall_width_input.setGeometry(1140, 95, 30, 20) # self.counter_width_input.setAlignment(Qt.AlignRight) # self.counter_box.addWidget(self.counter_width_input) # self.counter_width_input.textChanged.connect(self.widthChange) #self.right_layout.addLayout(self.counter_box) # 2. 绘制障碍物标题 self.right_layout.addStretch() self.destination_label = QLabel(self) self.destination_label.setText("绘制出入口及休息区: ") self.destination_label.setFont(QFont("Noto Sans CJK SC")) # self.obstacle_label.setGeometry(1010, 40, 100, 30) self.right_layout.addWidget(self.destination_label) self.destination_pen = QPen(Qt.DashDotDotLine) self.destination_pen.setColor(Qt.lightGray) # 2.1 绘制出口 # 2.1.1 出口选择框 self.select_exit = QRadioButton(self) self.select_exit.setText("出口. ") self.select_exit.setFont(QFont("Noto Sans CJK SC")) self.select_exit.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_exit) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.1.2 出口笔刷 self.exit_brush = QBrush(Qt.BDiagPattern) color = QColor(0, 255, 0, 130) self.exit_brush.setColor(color) self.exit_width = 2 # 2.2 绘制入口 # 2.2.1 入口选择框 self.select_entry = QRadioButton(self) self.select_entry.setText("入口. ") self.select_entry.setFont(QFont("Noto Sans CJK SC")) self.select_entry.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_entry) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.2.2 入口笔刷 self.entry_brush = QBrush(Qt.DiagCrossPattern) color = QColor(0, 255, 0, 130) self.entry_brush.setColor(color) self.entry_width = 2 # 2.3 绘制出入口 # 2.3.1 出入口选择框 self.select_passage = QRadioButton(self) self.select_passage.setText("出入口. ") self.select_passage.setFont(QFont("Noto Sans CJK SC")) self.select_passage.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_passage) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.3.2 出入口笔刷 self.passage_brush = QBrush(Qt.Dense6Pattern) color = QColor(0, 255, 0, 120) self.passage_brush.setColor(color) self.passage_width = 2 # 2.4 绘制休息区 # 2.4.1 休息区选择框 self.select_waiting = QRadioButton(self) self.select_waiting.setText("休息区. ") self.select_waiting.setFont(QFont("Noto Sans CJK SC")) self.select_waiting.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_waiting) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.4.2 休息区笔刷 self.waiting_brush = QBrush(Qt.SolidPattern) color = QColor(0, 255, 0, 25) self.waiting_brush.setColor(color) self.right_layout.addStretch() # 3. 保存图片按键 self.save_button = QPushButton(self) self.save_button.setText("保存地图") self.save_button.setFont(QFont("Noto Sans CJK SC")) self.save_button.clicked.connect(self.saveMap) self.right_layout.addWidget(self.save_button) self.right_layout.addStretch() self.right_layout.addStretch() self.right_layout.addStretch() self.brush = self.railing_brush self.pen = self.obstacle_pen self.draw_type = "railing" self.width = self.railing_width self.setCentralWidget(self.splitter) self.setCentralWidget(self.splitter) self.splitter.setMouseTracking(True) self.setMouseTracking(True) self.image_label.setMouseTracking(True) self.image_label.installEventFilter(self) self.select_railing.setChecked(True) self.update() def saveMap(self): timenow = datetime.datetime.now() timestamp = datetime.datetime.strftime(timenow, '%Y-%m-%d_%H_%M_%S') filename = "./Maps/map_" + timestamp print(filename) pixmap = QPixmap.fromImage(self.image) pixmap.save(filename + "_map.bmp") pixmap1 = QPixmap.fromImage(self.hidden_obstacle_layer) pixmap1.save(filename + "_obs.bmp") pixmap2 = QPixmap.fromImage(self.hidden_destination_layer) pixmap2.save(filename + "_des.bmp") def widthChange(self): self.wall_width = int(self.wall_width_input.text()) self.pillar_width = int(self.pillar_width_input.text()) def drawTypeChange(self): if self.select_railing.isChecked(): #print("railing") self.brush = self.railing_brush self.draw_type = "railing" self.width = self.railing_width self.pen = self.obstacle_pen elif self.select_wall.isChecked(): #print("wall") self.brush = self.wall_brush self.draw_type = "wall" self.width = self.wall_width self.pen = self.obstacle_pen elif self.select_pillar.isChecked(): #print("pillar") self.brush = self.pillar_brush self.draw_type = "pillar" self.width = self.pillar_width self.pen = self.obstacle_pen elif self.select_counter.isChecked(): #print("counter") self.brush = self.counter_brush self.draw_type = "counter" self.width = self.counter_width self.pen = self.obstacle_pen elif self.select_exit.isChecked(): # print("exit") self.brush = self.exit_brush self.draw_type = "exit" self.width = self.exit_width self.pen = self.destination_pen elif self.select_entry.isChecked(): # print("entry") self.brush = self.entry_brush self.draw_type = "entry" self.width = self.entry_width self.pen = self.destination_pen elif self.select_passage.isChecked(): # print("passage") self.brush = self.passage_brush self.draw_type = "passage" self.width = self.passage_width self.pen = self.destination_pen elif self.select_waiting.isChecked(): # print("waiting") self.brush = self.waiting_brush self.draw_type = "waiting" self.pen = self.destination_pen def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.startPoint = event.pos() self.lastPoint = event.pos() self.temp_image = self.image.copy() if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter": self.temp_hidden_obstacle_layer = self.hidden_obstacle_layer.copy( ) else: self.temp_hidden_destination_layer = self.hidden_destination_layer.copy( ) self.draw_record.insert(0, self.draw_type) if self.draw_record.__len__() > self.maximum_undo + 2: self.draw_record.pop() #print(self.startPoint) if self.draw_type == "pillar": self.image = self.temp_image.copy() painter = QPainter(self.image) painter.setPen(self.obstacle_pen) painter.setBrush(self.pillar_brush) start = QPoint( self.startPoint.x() - (self.pillar_width * self.pix_per_meter) / 2 - 1, self.startPoint.y() - (self.pillar_width * self.pix_per_meter) / 2 - 1) end = QPoint( self.startPoint.x() + (self.pillar_width * self.pix_per_meter) / 2 - 1, self.startPoint.y() + (self.pillar_width * self.pix_per_meter) / 2 - 1) rect = QRect(start, end) painter.drawEllipse(rect) self.backup_image.insert(0, self.image) if self.backup_image.__len__() > self.maximum_undo + 2: self.backup_image.pop() ## self.hidden_obstacle_layer = self.temp_hidden_obstacle_layer.copy( ) painter1 = QPainter(self.hidden_obstacle_layer) painter1.setPen(self.hidden_pen) painter1.setBrush(self.hidden_pillar_brush) painter1.drawEllipse(rect) self.backup_hidden_obstacle.insert(0, self.hidden_obstacle_layer) if self.backup_hidden_obstacle.__len__( ) > self.maximum_undo + 2: self.backup_hidden_obstacle.pop() self.drawing = False self.update() def eventFilter(self, Object, event): if event.type() == QEvent.MouseMove: x = event.x() y = event.y() if 0 <= x < 1000 and 0 <= y < 500: x = x / 10.0 y = y / 10.0 message = "坐标: x = " + str(float( '%.1f' % x)) + ", \ty = " + str(float('%.1f' % y)) self.coordinates_disp.setText(message) return QWidget.eventFilter(self, Object, event) def mouseMoveEvent(self, event): # x = event.x() # y = event.y() # #if 0 <= x < 1000 and 0 <= y < 500: # x = x / 10.0 # y = y / 10.0 # message = "坐标: x = " + str(float('%.1f' % x)) + ", y = " + str(float('%.1f' % y)) # self.coordinates_disp.setText(message) if (event.buttons() and Qt.LeftButton) and self.drawing: self.lastPoint = event.pos() self.image = self.temp_image.copy() painter = QPainter(self.image) painter.setBrush(self.brush) painter.setPen(self.pen) if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter": self.hidden_obstacle_layer = self.temp_hidden_obstacle_layer.copy( ) painter1 = QPainter(self.hidden_obstacle_layer) if self.draw_type == "railing": painter1.setBrush(self.hidden_railing_brush) elif self.draw_type == "wall": painter1.setBrush(self.hidden_wall_brush) elif self.draw_type == "pillar": painter1.setBrush(self.hidden_pillar_brush) elif self.draw_type == "counter": painter1.setBrush(self.hidden_counter_brush) painter1.setPen(self.hidden_pen) else: self.hidden_destination_layer = self.temp_hidden_destination_layer.copy( ) painter1 = QPainter(self.hidden_destination_layer) if self.draw_type == "exit": painter1.setBrush(self.hidden_exit_brush) elif self.draw_type == "entry": painter1.setBrush(self.hidden_entry_brush) elif self.draw_type == "passage": painter1.setBrush(self.hidden_passage_brush) elif self.draw_type == "waiting": painter1.setBrush(self.hidden_waiting_brush) painter1.setPen(self.hidden_pen) w = self.width * self.pix_per_meter startx = self.startPoint.x() starty = self.startPoint.y() endx = self.lastPoint.x() endy = self.lastPoint.y() if self.shift_pressed == False and self.draw_type != "waiting": degree, length = self.get_degree(self.startPoint, self.lastPoint) painter.translate(self.startPoint) painter.rotate(degree) painter1.translate(self.startPoint) painter1.rotate(degree) start = QPoint(0, 0) end = QPoint(length, w) # if self.draw_type == "counter": # if abs(starty - endy) >= abs(startx - endx): # print("no shift, ver pattern") # temp_brush = self.brush # temp_brush.setStyle(Qt.HorPattern) # painter.setBrush(temp_brush) # else: # print("no shift, hor pattern") # temp_brush = self.brush # temp_brush.setStyle(Qt.HorPattern) # painter.setBrush(temp_brush) painter.drawRect(QRect(start, end)) painter1.drawRect(QRect(start, end)) elif self.shift_pressed == True and self.draw_type != "waiting": if abs(starty - endy) >= abs(startx - endx): if self.draw_type == "counter": temp_brush = self.brush temp_brush.setStyle(Qt.VerPattern) painter.setBrush(temp_brush) if startx < endx: painter.drawRect( QRect(QPoint(startx, starty), QPoint(startx + w, endy))) painter1.drawRect( QRect(QPoint(startx, starty), QPoint(startx + w, endy))) else: painter.drawRect( QRect(QPoint(startx, starty), QPoint(startx - w - 2, endy))) painter1.drawRect( QRect(QPoint(startx, starty), QPoint(startx - w - 2, endy))) else: if self.draw_type == "counter": temp_brush = self.brush temp_brush.setStyle(Qt.HorPattern) painter.setBrush(temp_brush) if starty < endy: painter.drawRect( QRect(QPoint(startx, starty), QPoint(endx, starty + w))) painter1.drawRect( QRect(QPoint(startx, starty), QPoint(endx, starty + w))) else: painter.drawRect( QRect(QPoint(startx, starty), QPoint(endx, starty - w - 2))) painter1.drawRect( QRect(QPoint(startx, starty), QPoint(endx, starty - w - 2))) else: painter.drawRect(QRect(self.startPoint, self.lastPoint)) painter1.drawRect(QRect(self.startPoint, self.lastPoint)) def get_degree(self, start, end): startx = start.x() starty = start.y() endx = end.x() endy = end.y() if endx >= startx: if endx == startx: if endy > starty: degree = 90 else: degree = 270 else: degree = math.atan( (endy - starty + 0.0) / (endx - startx + 0.0)) degree = (degree / 3.14) * 180 else: degree = math.atan((endy - starty + 0.0) / (startx - endx + 0.0)) degree = (degree / 3.14) * 180 degree = 180 - degree length = math.sqrt((startx - endx) * (startx - endx) + (starty - endy) * (starty - endy)) return degree, length def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.draw_type != "pillar": self.drawing = False self.backup_image.insert(0, self.image) if self.backup_image.__len__() > self.maximum_undo + 2: self.backup_image.pop() if self.draw_type == "railing" or self.draw_type == "wall" or self.draw_type == "pillar" or self.draw_type == "counter": self.backup_hidden_obstacle.insert( 0, self.hidden_obstacle_layer) if self.backup_hidden_obstacle.__len__( ) > self.maximum_undo + 2: self.backup_hidden_obstacle.pop() else: self.backup_hidden_destination.insert( 0, self.hidden_destination_layer) if self.backup_hidden_destination.__len__( ) > self.maximum_undo + 2: self.backup_hidden_destination.pop() def keyPressEvent(self, event): if event.key() == Qt.Key_Z: self.undo() elif event.modifiers() == Qt.ShiftModifier: self.shift_pressed = True elif event.key() == Qt.Key_1: self.wall_width_input.setText("1") self.wall_width = 1 self.pillar_width_input.setText("1") self.pillar_width = 1 elif event.key() == Qt.Key_2: self.wall_width_input.setText("2") self.wall_width = 2 self.pillar_width_input.setText("2") self.pillar_width = 2 elif event.key() == Qt.Key_3: self.wall_width_input.setText("3") self.wall_width = 3 self.pillar_width_input.setText("3") self.pillar_width = 3 elif event.key() == Qt.Key_4: self.wall_width_input.setText("4") self.wall_width = 4 self.pillar_width_input.setText("4") self.pillar_width = 4 elif event.key() == Qt.Key_5: self.wall_width_input.setText("5") self.wall_width = 5 self.pillar_width_input.setText("5") self.pillar_width = 5 elif event.key() == Qt.Key_6: self.wall_width_input.setText("6") self.wall_width = 6 self.pillar_width_input.setText("6") self.pillar_width = 6 elif event.key() == Qt.Key_7: self.wall_width_input.setText("7") self.wall_width = 7 self.pillar_width_input.setText("7") self.pillar_width = 7 elif event.key() == Qt.Key_8: self.wall_width_input.setText("8") self.wall_width = 8 self.pillar_width_input.setText("8") self.pillar_width = 8 elif event.key() == Qt.Key_9: self.wall_width_input.setText("9") self.wall_width = 9 self.pillar_width_input.setText("9") self.pillar_width = 9 elif event.key() == Qt.Key_0: self.wall_width_input.setText("10") self.wall_width = 10 self.pillar_width_input.setText("10") self.pillar_width = 10 self.drawTypeChange() def undo(self): if self.backup_image.__len__() > 1: #print(self.backup_image.__len__()) self.image = self.backup_image[1] self.backup_image.pop(0) self.update() if self.draw_record[0] == "railing" or self.draw_record[ 0] == "wall" or self.draw_record[ 0] == "pillar" or self.draw_record[0] == "counter": if self.backup_hidden_obstacle.__len__() > 1: print(self.backup_hidden_obstacle.__len__()) self.hidden_obstacle_layer = self.backup_hidden_obstacle[1] self.backup_hidden_obstacle.pop(0) self.update() else: if self.backup_hidden_destination.__len__() > 1: print(self.backup_hidden_destination.__len__()) self.hidden_destination_layer = self.backup_hidden_destination[ 1] self.backup_hidden_destination.pop(0) self.update() self.draw_record.pop(0) def keyReleaseEvent(self, event): if event.key() == Qt.Key_Shift: self.shift_pressed = False def paintEvent(self, event): self.image_label.setPixmap(QPixmap.fromImage(self.image))
from math import floor from .abstractpathtool import AbstractPathTool from cadnano.gui.views.pathview import pathstyles as styles import cadnano.util as util from PyQt5.QtCore import Qt, QEvent, QPointF, QRectF from PyQt5.QtGui import QBrush, QColor, QFont, QFontMetrics, QPainterPath, QPen, QPolygonF from PyQt5.QtWidgets import QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsSimpleTextItem _BASE_WIDTH = styles.PATH_BASE_WIDTH _PENCIL_COLOR = styles.RED_STROKE _DEFAULT_RECT = QRectF(0, 0, _BASE_WIDTH, _BASE_WIDTH) _NO_PEN = QPen(Qt.NoPen) class PencilTool(AbstractPathTool): """ docstring for PencilTool """ def __init__(self, controller): super(PencilTool, self).__init__(controller) self._temp_xover = ForcedXoverItem(self, None, None) self._temp_strand_item = ForcedStrandItem(self, None) self._temp_strand_item.hide() self._move_idx = None self._is_floating_xover_begin = True self._is_drawing_strand = False
class GraphicsGUIFeedbackPopup(QGraphicsItem): """The graphical representation of the GUIFeedbackPopup tool. Attributes: text (str): The string to be displayed in the guifeedback by default. Default is None. parent (QWidget): The parent QWidget of the popup graphic. Todo: * Make the parameters of the guifeedback(height, width, etc) dynamic. * Maybe: Make guifeedback auto-resizing. """ def __init__(self, text: str = None, parent: QWidget = None): """Inits the components needed for the guifeedback popup graphic.""" super().__init__(parent) self.__height: int = 240 self.__width: int = 180 self.__edge_roundness: float = 10.0 self.__edge_padding: float = 20.0 self.__character_max_width: int = 18 # not used for now self.__text: str = text self.__text_horizontal_padding: float = 4.0 self.__text_vertical_padding: float = 4.0 self.__text_item: QGraphicsTextItem = QGraphicsTextItem(self) # icons self.__icons: QPixmap = QPixmap("icons/status_icons.png") self.__icon_offset: float = 0.0 # TODO: temp solution to guifeedback autosizing self.guifeedback_dimensions: ds.Point = ds.Point(180, 50) self.hide() self.show() # create components self.__calculate_text_dimensions() self.__set_colors() self.__set_guifeedback_text_item() def __calculate_text_dimensions(self): """(Not used yet) Designed to make popup size dynamic based on content. """ # TODO: make dynamic and not static set self.__width = self.guifeedback_dimensions.x self.__height = self.guifeedback_dimensions.y def __set_colors(self): """Rather than convolute the __init__, do the brush, pen and colors here. """ # text font and color self.__text_color = Qt.white self.__text_font = QFont("Monospace", 9) self.__text_font.setBold(False) # color to use for the outline self.__color = QColor("#7F000000") # outline pens self.__pen_default = QPen(self.__color) self.__pen_default.setWidthF(1.0) # background brushes self.__brush_background = QBrush(QColor("#D3212121")) def __set_guifeedback_text_item(self): """Rather than convolute the __init__, set the popup text here. """ self.__text_item.setDefaultTextColor(self.__text_color) self.__text_item.setFont(self.__text_font) self.__text_item.setPos(self.__text_horizontal_padding, 0) self.__text_item.setTextWidth(self.__width - (2 * self.__text_horizontal_padding)) self.__text_item.setPlainText(self.__text) @property def text(self): """str: The popup's current info text. Setter: Sets the new string as the popup's info text. """ return self.__text @text.setter def text(self, value): self.__text = value self.__calculate_text_dimensions() self.__text_item.setTextWidth(self.__width - (2 * self.__text_horizontal_padding)) self.__text_item.setPlainText(self.__text) @property def icon_offset(self): """float: Returns the selected icons offset value in the sprite sheet. Setter: Sets an offset for the desired icon in the spritesheet. """ return self.__icon_offset @icon_offset.setter def icon_offset(self, value): self.__icon_offset = value # Overloaded Methods # ------------------ # pylint: disable=invalid-name # Reasoning: PyQt boundingRect overloaded method requires the # camel case. def boundingRect(self): """Returns the bounding rectangle of the GraphicsGUIFeedbackPopup. Returns: QRect: The Qt bounding rectangle. """ return QRectF(0, 0, self.__width, self.__height).normalized() # pylint: disable=unused-argument # Reasoning: PyQt painter overloaded method requires it. # pylint: disable=invalid-name # Reasoning: PyQt painter overloaded method requires the camel case. def paint(self, painter, QStyleOptionGraphicsItem, widget=None): """Overloaded QWidget paint method. Draws the GUIFeedbackPopup on the scene. Args: painter: QWidget painter class. QStyleOptionGraphicsItem: ??? (not used). widget: The parent widget if there is one(not used). Todo: * Find out what QStyleOptionGraphicsItem is for. """ # content path_content = QPainterPath() path_content.setFillRule(Qt.WindingFill) path_content.addRoundedRect(0, 0, self.__width, self.__height, self.__edge_roundness, self.__edge_roundness) painter.setPen(Qt.NoPen) painter.setBrush(self.__brush_background) painter.drawPath(path_content.simplified()) # outline path_outline = QPainterPath() path_outline.addRoundedRect(0, 0, self.__width, self.__height, self.__edge_roundness, self.__edge_roundness) # 9pt = 9px # px max of 188 (188 - padding[8] = 180) painter.setBrush(Qt.NoBrush) painter.setPen(self.__pen_default) painter.drawPath(path_outline.simplified()) # paint icon painter.drawPixmap(QRectF(-12.5, -12.5, 24.0, 24.0), self.__icons, QRectF(self.__icon_offset, 0, 24.0, 24.0))
class OrbitView(GraphicsLayoutWidget): def __init__(self, orbit=None, axis="X", use_sector_ticks=True, parent=None, ymin=-1.0, ymax=1.0, name=None, label=None, units=None, draw_timer=None, magnet_list=None): super(OrbitView, self).__init__(parent=parent) axis = axis.lower() if axis not in ["x", "y", "tmit"]: raise Exception("Axis must be 'x', 'y', or 'tmit'") self.axis = axis self.use_sector_ticks = use_sector_ticks self.sector_ticks = [[], []] self.ci.layout.setSpacing(0.0) self.plotLabel = self.addLabel(text=name, row=0, col=0, rowspan=3, angle=-90) self.up_magnet_view = MagnetView(magnet_list=orbit, direction="up") self.up_magnet_view.hideAxis('left') self.up_magnet_view.hideAxis('bottom') self.ci.layout.setRowStretchFactor(0, 3) self.plotItem = self.addPlot(name=name, row=0, col=1) self.ci.layout.setRowStretchFactor(1, 0) self.down_magnet_view = MagnetView(magnet_list=orbit, direction="down") self.down_magnet_view.hideAxis('left') self.up_magnet_view.setXLink(self.plotItem) self.down_magnet_view.setXLink(self.plotItem) self.ci.layout.setRowStretchFactor(2, 0) self.show_magnet_buttons = False if axis != "tmit" and magnet_list is not None: self.show_magnet_views(True) self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate ) # Greatly improves drawing performance. self.plotItem.setMouseEnabled(y=False) #Customize the right-click menu. self.plotItem.setMenuEnabled(enableMenu=False, enableViewBoxMenu=None) reset_view_range = QAction("Reset View Range", self.plotItem.vb.menu) reset_view_range.triggered.connect(self.reset_range) self.plotItem.vb.scene().contextMenu = [] existing_menu_actions = self.plotItem.vb.menu.actions() self.plotItem.vb.menu.insertAction(existing_menu_actions[0], reset_view_range) for action in existing_menu_actions: if str(action.text()) == "View All": self.plotItem.vb.menu.removeAction(action) self.plotItem.showGrid(y=True) #self.plotItem.getAxis('left').setStyle(tickTextWidth=60) #self.plotItem.getAxis('left').setStyle(autoExpandTextSpace=False) #if label is not None: # self.plotItem.getAxis('left').enableAutoSIPrefix(enable=False) # self.plotItem.getAxis('left').setLabel(text=label, units=units) self.bpm_brush = QBrush(QColor(0, 255, 0)) self.energy_bpm_brush = QBrush(QColor(100, 200, 255)) self.ymin = ymin #Y axis goes from self.ymin to self.ymax by default. self.ymax = ymax self.yminlimit = 10.0 * ymin #This is the limit on the Y axis range. self.ymaxlimit = 10.0 * ymax #This is the upper limit on the Y axis range. self.plotItem.setLimits(minYRange=0.04, maxYRange=abs(self.ymaxlimit - self.yminlimit)) self.axis_pen = QPen(QBrush(QColor(255, 255, 255)), 0) self.axis_pen.setCapStyle(Qt.FlatCap) self.bpm_pen = QPen(self.bpm_brush, 2) self.bpm_pen.setCosmetic(True) self.bpm_pen.setCapStyle(Qt.FlatCap) self.no_beam_brush = QBrush(QColor(0, 255, 0, 45)) self.no_beam_pen = QPen(self.no_beam_brush, 2) self.no_beam_pen.setCosmetic(True) self.no_beam_pen.setCapStyle(Qt.FlatCap) self.energy_bpm_pen = QPen(self.energy_bpm_brush, 2) self.energy_bpm_pen.setCosmetic(True) self.energy_bpm_pen.setCapStyle(Qt.FlatCap) self.fit_brush = QBrush(QColor(255, 255, 255, 255)) self.fit_pen = QPen(self.fit_brush, 0) self.fit_pen.setCosmetic(True) self.fit_pen.setCapStyle(Qt.FlatCap) self.axis_line = QGraphicsLineItem(0.0, 0.0, 1.0, 0.0) self.axis_line.setPen(self.axis_pen) self.plotItem.addItem(self.axis_line, ignoreBounds=True) self.lines = {} self.orbit = None self.needs_initial_range = True self.set_draw_timer(draw_timer) self._display_fit = False self.fit_data_item = None self.fit_options = {} if orbit is not None: self.set_orbit(orbit) def make_right_click_menu(self): menu = QMenu(self) return menu def display_fit(self, enabled=True): if enabled and self.fit_data_item is None: self.fit_data_item = PlotDataItem(pen=self.fit_pen) self.plotItem.addItem(self.fit_data_item) elif not enabled: self.plotItem.removeItem(self.fit_data_item) self.fit_data_item = None self._display_fit = enabled def set_draw_timer(self, new_timer, start=False): try: self.draw_timer.timeout.disconnect(self.redraw_bpms) except: pass if new_timer is None: new_timer = QTimer(self) new_timer.setInterval(int(1000 / 60)) self.draw_timer = new_timer self.draw_timer.timeout.connect(self.redraw_bpms) if start: self.draw_timer.start() def set_orbit(self, orbit, reset_range=True): if self.orbit == orbit: return old_range = None old_zmax = None old_zmin = None if self.orbit is not None: old_range = self.plotItem.viewRect() old_zmax = self.orbit.zmax() old_zmin = self.orbit.zmin() self.clear_orbit() self.orbit = orbit extent = self.orbit.zmax() - self.orbit.zmin() self.plotItem.setLimits(xMin=self.orbit.zmin() - (0.02 * extent), xMax=self.orbit.zmax() + (0.02 * extent)) self.plotItem.enableAutoRange(enable=False) self.axis_line.setLine(self.orbit.zmin(), 0.0, self.orbit.zmax(), 0.0) for bpm in self.orbit: line = BPMLineItem(bpm) self.lines[bpm.name] = line self.set_pen_for_bpm(bpm) self.plotItem.addItem(self.lines[bpm.name]) if self.use_sector_ticks and (old_zmax != orbit.zmax() or old_zmin != orbit.zmin()): self.sector_ticks = [[], []] self.sector_ticks[0] = self.orbit.sector_locations() unit_nums = [name.split(":")[-1] for name in self.orbit.names()] self.sector_ticks[1] = zip(self.orbit.z_vals(), unit_nums) self.plotItem.getAxis('bottom').setTicks(self.sector_ticks) self.plotItem.getAxis('bottom').setStyle(textFillLimits=[(0, 0.72)]) self.plotItem.showGrid(x=True) if reset_range or self.needs_initial_range: self.reset_range() self.needs_initial_range = False else: self.plotItem.setRange(old_range, padding=0.0, update=False) self.draw_timer.start() def show_magnet_views(self, enabled): if enabled == self.show_magnet_buttons: return self.show_magnet_buttons = enabled if enabled: self.addItem(self.up_magnet_view, row=1, col=1) self.addItem(self.down_magnet_view, row=2, col=1) self.up_magnet_view.setXLink(self.plotItem) self.down_magnet_view.setXLink(self.plotItem) else: self.removeItem(self.up_magnet_view) self.removeItem(self.down_magnet_view) def set_magnet_list(self, magnet_list): self.up_magnet_view.set_magnets(magnet_list, reset_range=False) self.down_magnet_view.set_magnets(magnet_list, reset_range=False) @pyqtSlot(bool) def reset_range(self, checked=False): self.plotItem.enableAutoRange(axis=ViewBox.XAxis) self.plotItem.setYRange(self.ymin, self.ymax) def wheelEvent(self, event): if event.modifiers() == Qt.ShiftModifier: numPixels = event.pixelDelta() numDegrees = event.angleDelta() if not numPixels.isNull(): s = (1.005)**(numPixels.y()) else: s = (1.005)**(numDegrees.y() * (-1.0 / 8.0)) self.plotItem.vb.scaleBy(y=s) else: super(OrbitView, self).wheelEvent(event) def clear_orbit(self): self.draw_timer.stop() auto_range_x_enabled = self.plotItem.vb.state['autoRange'][0] auto_range_y_enabled = self.plotItem.vb.state['autoRange'][1] self.plotItem.enableAutoRange(enable=False) if self.orbit is None: return for bpm in self.orbit: self.plotItem.removeItem(self.lines[bpm.name]) self.plotItem.enableAutoRange(x=auto_range_x_enabled, y=auto_range_y_enabled) self.lines = {} @pyqtSlot() def redraw_bpms(self): for bpm in self.orbit: self.set_pen_for_bpm(bpm) self.lines[bpm.name].setLine(bpm.z, 0.0, bpm.z, bpm[self.axis]) self.update_fit() def set_pen_for_bpm(self, bpm): if bpm.severity(self.axis) != 0: self.lines[bpm.name].setPen(self.no_beam_pen) else: if bpm.is_energy_bpm: self.lines[bpm.name].setPen(self.energy_bpm_pen) else: self.lines[bpm.name].setPen(self.bpm_pen) def update_fit(self): if not self._display_fit: return if self.orbit.fit_data is None: if self.fit_data_item is not None: self.fit_data_item.hide() return fit_data = None if self.axis == 'x': fit_data = self.orbit.fit_data['xpos'] elif self.axis == 'y': fit_data = self.orbit.fit_data['ypos'] self.fit_data_item.show() self.fit_data_item.setData(x=self.orbit.fit_data['zs'], y=fit_data) @pyqtSlot() def stop(self): self.draw_timer.stop() @pyqtSlot() def start(self): if self.orbit is not None: self.draw_timer.start() def setXLink(self, view): return self.plotItem.setXLink(view.plotItem) def setYLink(self, view): return self.plotItem.setYLink(view.plotItem)
def drawLines(self, qp): pen = QPen(Qt.black, 2, Qt.SolidLine) qp.setPen(pen) qp.drawLine(20, 40, 250, 40) pen.setStyle(Qt.DashLine) qp.setPen(pen) qp.drawLine(20, 80, 250, 80) pen.setStyle(Qt.DashDotLine) qp.setPen(pen) qp.drawLine(20, 120, 250, 120) pen.setStyle(Qt.DotLine) qp.setPen(pen) qp.drawLine(20, 160, 250, 160) pen.setStyle(Qt.DashDotDotLine) qp.setPen(pen) qp.drawLine(20, 200, 250, 200) pen.setStyle(Qt.CustomDashLine) pen.setDashPattern([1, 4, 5, 4]) qp.setPen(pen) qp.drawLine(20, 240, 250, 240)
def __init__(self, orbit=None, axis="X", use_sector_ticks=True, parent=None, ymin=-1.0, ymax=1.0, name=None, label=None, units=None, draw_timer=None, magnet_list=None): super(OrbitView, self).__init__(parent=parent) axis = axis.lower() if axis not in ["x", "y", "tmit"]: raise Exception("Axis must be 'x', 'y', or 'tmit'") self.axis = axis self.use_sector_ticks = use_sector_ticks self.sector_ticks = [[], []] self.ci.layout.setSpacing(0.0) self.plotLabel = self.addLabel(text=name, row=0, col=0, rowspan=3, angle=-90) self.up_magnet_view = MagnetView(magnet_list=orbit, direction="up") self.up_magnet_view.hideAxis('left') self.up_magnet_view.hideAxis('bottom') self.ci.layout.setRowStretchFactor(0, 3) self.plotItem = self.addPlot(name=name, row=0, col=1) self.ci.layout.setRowStretchFactor(1, 0) self.down_magnet_view = MagnetView(magnet_list=orbit, direction="down") self.down_magnet_view.hideAxis('left') self.up_magnet_view.setXLink(self.plotItem) self.down_magnet_view.setXLink(self.plotItem) self.ci.layout.setRowStretchFactor(2, 0) self.show_magnet_buttons = False if axis != "tmit" and magnet_list is not None: self.show_magnet_views(True) self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate ) # Greatly improves drawing performance. self.plotItem.setMouseEnabled(y=False) #Customize the right-click menu. self.plotItem.setMenuEnabled(enableMenu=False, enableViewBoxMenu=None) reset_view_range = QAction("Reset View Range", self.plotItem.vb.menu) reset_view_range.triggered.connect(self.reset_range) self.plotItem.vb.scene().contextMenu = [] existing_menu_actions = self.plotItem.vb.menu.actions() self.plotItem.vb.menu.insertAction(existing_menu_actions[0], reset_view_range) for action in existing_menu_actions: if str(action.text()) == "View All": self.plotItem.vb.menu.removeAction(action) self.plotItem.showGrid(y=True) #self.plotItem.getAxis('left').setStyle(tickTextWidth=60) #self.plotItem.getAxis('left').setStyle(autoExpandTextSpace=False) #if label is not None: # self.plotItem.getAxis('left').enableAutoSIPrefix(enable=False) # self.plotItem.getAxis('left').setLabel(text=label, units=units) self.bpm_brush = QBrush(QColor(0, 255, 0)) self.energy_bpm_brush = QBrush(QColor(100, 200, 255)) self.ymin = ymin #Y axis goes from self.ymin to self.ymax by default. self.ymax = ymax self.yminlimit = 10.0 * ymin #This is the limit on the Y axis range. self.ymaxlimit = 10.0 * ymax #This is the upper limit on the Y axis range. self.plotItem.setLimits(minYRange=0.04, maxYRange=abs(self.ymaxlimit - self.yminlimit)) self.axis_pen = QPen(QBrush(QColor(255, 255, 255)), 0) self.axis_pen.setCapStyle(Qt.FlatCap) self.bpm_pen = QPen(self.bpm_brush, 2) self.bpm_pen.setCosmetic(True) self.bpm_pen.setCapStyle(Qt.FlatCap) self.no_beam_brush = QBrush(QColor(0, 255, 0, 45)) self.no_beam_pen = QPen(self.no_beam_brush, 2) self.no_beam_pen.setCosmetic(True) self.no_beam_pen.setCapStyle(Qt.FlatCap) self.energy_bpm_pen = QPen(self.energy_bpm_brush, 2) self.energy_bpm_pen.setCosmetic(True) self.energy_bpm_pen.setCapStyle(Qt.FlatCap) self.fit_brush = QBrush(QColor(255, 255, 255, 255)) self.fit_pen = QPen(self.fit_brush, 0) self.fit_pen.setCosmetic(True) self.fit_pen.setCapStyle(Qt.FlatCap) self.axis_line = QGraphicsLineItem(0.0, 0.0, 1.0, 0.0) self.axis_line.setPen(self.axis_pen) self.plotItem.addItem(self.axis_line, ignoreBounds=True) self.lines = {} self.orbit = None self.needs_initial_range = True self.set_draw_timer(draw_timer) self._display_fit = False self.fit_data_item = None self.fit_options = {} if orbit is not None: self.set_orbit(orbit)
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 paintEvent(self, event): super().paintEvent(event) rect = QRect(self.x0, self.y0, abs(self.x1 - self.x0), abs(self.y1 - self.y0)) painter = QPainter(self) painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) painter.drawRect(rect)
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)
def paintEvent(self, event, *args): """ Custom paint event """ event.accept() # Paint timeline preview on QWidget painter = QPainter(self) painter.setRenderHints( QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.TextAntialiasing, True) # Fill the whole widget with the solid color (background solid color) painter.fillRect(event.rect(), QColor("#191919")) # Create pens / colors clip_pen = QPen(QBrush(QColor("#53a0ed")), 1.5) clip_pen.setCosmetic(True) painter.setPen(clip_pen) selected_clip_pen = QPen(QBrush(QColor("Red")), 1.5) selected_clip_pen.setCosmetic(True) scroll_color = QColor("#4053a0ed") scroll_pen = QPen(QBrush(scroll_color), 2.0) scroll_pen.setCosmetic(True) marker_color = QColor("#4053a0ed") marker_pen = QPen(QBrush(marker_color), 1.0) marker_pen.setCosmetic(True) playhead_color = QColor(Qt.red) playhead_color.setAlphaF(0.5) playhead_pen = QPen(QBrush(playhead_color), 1.0) playhead_pen.setCosmetic(True) handle_color = QColor("#a653a0ed") handle_pen = QPen(QBrush(handle_color), 1.5) handle_pen.setCosmetic(True) # Get layer lookup layers = Track.filter() # Wait for timeline object and valid scrollbar positions if get_app().window.timeline and self.scrollbar_position[2] != 0.0: # Get max width of timeline project_duration = get_app().project.get("duration") pixels_per_second = event.rect().width() / project_duration project_pixel_width = max(0, project_duration * pixels_per_second) scroll_width = (self.scrollbar_position[1] - self.scrollbar_position[0]) * event.rect().width() # Get FPS info fps_num = get_app().project.get("fps").get("num", 24) fps_den = get_app().project.get("fps").get("den", 1) fps_float = float(fps_num / fps_den) # Determine scale factor vertical_factor = event.rect().height() / len(layers) # Loop through each clip painter.setPen(clip_pen) for clip_rect in self.clip_rects: painter.drawRect(clip_rect) painter.setPen(selected_clip_pen) for clip_rect in self.clip_rects_selected: painter.drawRect(clip_rect) painter.setPen(marker_pen) for marker_rect in self.marker_rects: painter.drawRect(marker_rect) painter.setPen(playhead_pen) playhead_x = ((self.current_frame / fps_float) * pixels_per_second) playhead_rect = QRectF(playhead_x, 0, 0.5, len(layers) * vertical_factor) painter.drawRect(playhead_rect) # Draw scroll bars (if available) if self.scrollbar_position: painter.setPen(scroll_pen) # scroll bar path scroll_x = self.scrollbar_position[0] * event.rect().width() self.scroll_bar_rect = QRectF(scroll_x, 0.0, scroll_width, event.rect().height()) scroll_path = QPainterPath() scroll_path.addRoundedRect(self.scroll_bar_rect, 6, 6) # draw scroll bar rect painter.fillPath(scroll_path, scroll_color) painter.drawPath(scroll_path) # draw handles painter.setPen(handle_pen) handle_width = 12.0 # left handle left_handle_x = (self.scrollbar_position[0] * event.rect().width()) - (handle_width / 2.0) self.left_handle_rect = QRectF(left_handle_x, event.rect().height() / 4.0, handle_width, event.rect().height() / 2.0) left_handle_path = QPainterPath() left_handle_path.addRoundedRect(self.left_handle_rect, handle_width, handle_width) painter.fillPath(left_handle_path, handle_color) # right handle right_handle_x = (self.scrollbar_position[1] * event.rect().width()) - (handle_width / 2.0) self.right_handle_rect = QRectF(right_handle_x, event.rect().height() / 4.0, handle_width, event.rect().height() / 2.0) right_handle_path = QPainterPath() right_handle_path.addRoundedRect(self.right_handle_rect, handle_width, handle_width) painter.fillPath(right_handle_path, handle_color) # Determine if play-head is inside scroll area if get_app().window.preview_thread.player.Mode( ) == openshot.PLAYBACK_PLAY and self.is_auto_center: if not self.scroll_bar_rect.contains(playhead_rect): get_app().window.TimelineCenter.emit() # End painter painter.end()
def paintEvent(self, event): self.topLabel.setText(self.text) qp = QPainter() qp.begin(self) qp.setPen(QPen(QBrush(Qt.black), 5)) qp.setFont(QFont('Times', 16)) if self.settingScreen == False: qp.drawLine( QLine(self.rod_Xcoord, self.rod_Ycoord, self.circle_Xcoord + 25, self.circle_Ycoord + 25)) qp.setBrush(QBrush(Qt.black, Qt.SolidPattern)) qp.drawEllipse(self.circle_Xcoord, self.circle_Ycoord, 50, 50) for item in buttonList: item.draw(qp) if self.settingScreen == False: if self.massScreen == True: qp.setPen(QPen(QBrush(Qt.blue), 2)) qp.setBrush(QBrush(Qt.blue)) qp.drawRect(75, W_HEIGHT - 70, 100, 10) qp.setPen(QPen(QBrush(Qt.black), 2)) qp.drawRect(75, W_HEIGHT - 70, 100, 10) drawNextMassY = W_HEIGHT - 70 for item in self.massArray: qp.setBrush(QBrush(Qt.gray)) if item == 1: height = 6 elif item == 10: height = 15 elif item == 20: height = 30 else: height = 45 qp.drawRect(85, drawNextMassY - (height), 80, height) drawNextMassY = drawNextMassY - (height) qp.drawText(90, W_HEIGHT - 30, 'Mass: ' + str(self.mass) + ' g') else: qp.setPen(QPen(QBrush(Qt.black), 3)) qp.drawText(150, 400, 'Period: ' + str(self.period) + ' s') if self.calc != None: qp.drawText(200, 150, str(self.calc)) if self.displayResults == True: qp.setPen(QPen(QBrush(Qt.black), 2)) if self.force == 0: qp.drawText(125, 250, 'Calculating...') else: if isinstance(self.force, str) == False: qp.drawText( 125, 250, 'Centripetal Force: ' + str(round(self.force, 2)) + ' N') qp.drawText(125, 300, 'Mass: ' + str(self.mass) + ' g') qp.drawText(125, 350, 'Period: ' + str(self.period) + ' s') else: qp.drawText(125, 250, 'Centripetal Force: ' + self.force) qp.drawText(125, 300, 'Mass: ' + str(self.mass) + ' g')
def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) pen = QPen() pen.setWidth(3) pen.setColor(Qt.red) pen.setStyle(Qt.SolidLine) pen.setCapStyle(Qt.FlatCap) pen.setJoinStyle(Qt.BevelJoin) painter.setPen(pen) brush = QBrush() brush.setColor(Qt.yellow) brush.setStyle(Qt.SolidPattern) painter.setBrush(brush) W = self.width() H = self.height() rect = QRect(W/4, H/4, W/2, H/2) painter.drawRect(rect)
def __init__(self, parent=None): super(ImageViewer, self).__init__(parent) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self._scene = ImageViewerScene(self) self.setScene(self._scene) self._image = None self._image_original = None self._pixmap = None self._img_contrast = 1.0 self._img_brightness = 50.0 self._img_gamma = 1.0 self._create_grid() self._channels = [] self._current_tool = SELECTION_TOOL.POINTER self._dataset = None # create grid lines pen_color = QColor(255, 255, 255, 255) pen = QPen(pen_color) pen.setWidth(2) pen.setStyle(QtCore.Qt.DotLine) self.vline = QGraphicsLineItem() self.vline.setVisible(False) self.vline.setPen(pen) self.hline = QGraphicsLineItem() self.hline.setVisible(False) self.hline.setPen(pen) self._scene.addItem(self.vline) self._scene.addItem(self.hline) self._current_label = None # rectangle selection tool self._rectangle_tool_origin = QPoint() self._rectangle_tool_picker = QRubberBand(QRubberBand.Rectangle, self) # polygon selection tool app = QApplication.instance() color = app.palette().color(QPalette.Highlight) self._polygon_guide_line_pen = QPen(color) self._polygon_guide_line_pen.setWidth(3) self._polygon_guide_line_pen.setStyle(QtCore.Qt.DotLine) self._polygon_guide_line = QGraphicsLineItem() self._polygon_guide_line.setVisible(False) self._polygon_guide_line.setPen(self._polygon_guide_line_pen) self._scene.addItem(self._polygon_guide_line) self._current_polygon = None # circle self._current_ellipse = None # free selection tool self._current_free_path = None self._is_drawing = False self._last_point_drawn = QPoint() self._last_click_point = None self._free_Path_pen = QPen(color) self._free_Path_pen.setWidth(10) self._extreme_points = Queue(maxsize=4)
def __init__(self): super().__init__() top = 400 left = 400 width = 1200 height = 500 self.maximum_undo = 20 self.obj_type = 'wall' self.obj_width = 10 self.pix_per_meter = 10 self.bgc = Qt.white self.shift_pressed = False icon = "icon.png" self.setGeometry(top, left, width, height) self.setWindowTitle("Map Designer") self.setWindowIcon(QIcon(icon)) self.setFixedSize(width, height) self.hidden_obstacle_layer = QImage(1000, 500, QImage.Format_RGB32) self.hidden_obstacle_layer.fill(self.bgc) self.backup_hidden_obstacle = [] self.backup_hidden_obstacle.append(self.hidden_obstacle_layer) self.temp_hidden_obstacle_layer = self.hidden_obstacle_layer self.hidden_railing_brush = QBrush(Qt.SolidPattern) self.hidden_railing_brush.setColor(Qt.red) self.hidden_wall_brush = QBrush(Qt.SolidPattern) self.hidden_wall_brush.setColor(Qt.black) self.hidden_pillar_brush = QBrush(Qt.SolidPattern) self.hidden_pillar_brush.setColor(Qt.green) self.hidden_counter_brush = QBrush(Qt.SolidPattern) self.hidden_counter_brush.setColor(Qt.blue) self.hidden_destination_layer = QImage(1000, 500, QImage.Format_RGB32) self.hidden_destination_layer.fill(self.bgc) self.backup_hidden_destination = [] self.backup_hidden_destination.append(self.hidden_destination_layer) self.temp_hidden_destination_layer = self.hidden_destination_layer self.hidden_exit_brush = QBrush(Qt.SolidPattern) self.hidden_exit_brush.setColor(Qt.red) self.hidden_entry_brush = QBrush(Qt.SolidPattern) self.hidden_entry_brush.setColor(Qt.black) self.hidden_passage_brush = QBrush(Qt.SolidPattern) self.hidden_passage_brush.setColor(Qt.green) self.hidden_waiting_brush = QBrush(Qt.SolidPattern) self.hidden_waiting_brush.setColor(Qt.blue) self.hidden_pen = QPen() self.hidden_pen.setColor(self.bgc) self.left_layout = QHBoxLayout() self.left_zone = QWidget(self) self.left_zone.setLayout(self.left_layout) self.image = QImage(1000, 500, QImage.Format_RGB32) self.image.fill(self.bgc) self.image_label = QLabel(self) self.image_label.setGeometry(0, 0, 1000, 500) self.image_label.setPixmap(QPixmap.fromImage(self.image)) self.left_layout.addWidget(self.image_label) self.left_layout.setSpacing(0) self.left_layout.setContentsMargins(0, 0, 0, 0) self.left_layout.setStretch(0, 0) self.left_layout.setGeometry(QRect(QPoint(0, 0), QPoint(1000, 500))) self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Horizontal) self.splitter.setContentsMargins(0, 0, 0, 0) self.splitter.setFixedSize(1200, 500) self.splitter.setHandleWidth(0) self.splitter.addWidget(self.left_zone) self.backup_image = [] self.backup_image.append(self.image) self.draw_record = [] self.temp_image = QImage(1000, 500, QImage.Format_RGB32) self.temp_image.fill(self.bgc) self.drawing = False self.lastPoint = QPoint() # mainMenu = self.menuBar() # mainMenu.setNativeMenuBar(False) # fileMenu = mainMenu.addMenu("File") # brushMenu = mainMenu.addMenu("Brush Size") # brushColor = mainMenu.addMenu("Brush Color") # # saveAction = QAction("Save", self) # saveAction.setShortcut("Ctrl+S") # fileMenu.addAction(saveAction) # # clearAction = QAction("Clear", self) # clearAction.setShortcut("Ctrl+C") # fileMenu.addAction(clearAction) # # px3Action = QAction("3px", self) # px3Action.setShortcut("Ctrl+3") # brushMenu.addAction(px3Action) # # px5Action = QAction("5px", self) # px5Action.setShortcut("Ctrl+5") # brushMenu.addAction(px5Action) # # px9Action = QAction("9px", self) # px9Action.setShortcut("Ctrl+9") # brushMenu.addAction(px5Action) # # blackAction = QAction("Black", self) # blackAction.setShortcut("Ctrl+B") # brushColor.addAction(blackAction) # # whiteAction = QAction("White", self) # whiteAction.setShortcut("Ctrl+W") # brushColor.addAction(whiteAction) # #按钮控件 # # self.btn_obstacle = QPushButton(self) # self.btn_obstacle.setGeometry(1020, 40, 20, 20) # self.btn_obstacle.setText("■") # self.btn_obstacle.setStyleSheet("QPushButton{color: black; padding-bottom: 2px;}" # "QPushButton:hover{background-color: darkgrey}") # # self.btn_dest = QPushButton(self) # self.btn_dest.setGeometry(1020, 80, 20, 20) # self.btn_dest.setText("■") # self.btn_dest.setStyleSheet("color: green; padding-bottom: 2px") #绘制选项 self.right_layout = QVBoxLayout() self.right_zone = QWidget(self) self.right_zone.setLayout(self.right_layout) self.splitter.addWidget(self.right_zone) #self.right_layout.addWidget(self.image_label) #0.坐标显示区 self.right_layout.addStretch() self.coordinates_label = QLabel(self) self.coordinates_label.setText("当前坐标(m): ") self.coordinates_label.setFont(QFont("Noto Sans CJK SC")) self.right_layout.addWidget(self.coordinates_label) self.coordinates_disp = QLabel(self) self.coordinates_disp.setText("坐标: x = 0.0, \ty = 0.0") self.coordinates_disp.setFont(QFont("Noto Sans CJK SC")) self.right_layout.addWidget(self.coordinates_disp) #1. 绘制障碍物标题 self.right_layout.addStretch() self.obstacle_label = QLabel(self) self.obstacle_label.setText("绘制障碍物: ") self.obstacle_label.setFont(QFont("Noto Sans CJK SC")) #self.obstacle_label.setGeometry(1010, 40, 100, 30) self.right_layout.addWidget(self.obstacle_label) self.obstacle_pen = QPen(Qt.SolidLine) self.obstacle_pen.setColor(Qt.black) #1.1 绘制护栏 #1.1.1 护栏选择框 self.select_railing = QRadioButton(self) self.select_railing.setText("护栏. ") self.select_railing.setFont(QFont("Noto Sans CJK SC")) self.select_railing.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_railing) #self.select_railing.setGeometry(1030, 65, 60, 30) #1.1.2 护栏笔刷 self.railing_brush = QBrush(Qt.BDiagPattern) self.railing_brush.setColor(Qt.darkGray) self.railing_width = 0.5 # 1.2.1 墙体选择框 self.wall_box = QHBoxLayout() self.select_wall = QRadioButton(self) self.select_wall.setText("墙体, ") self.select_wall.setFont(QFont("Noto Sans CJK SC")) self.select_wall.toggled.connect(self.drawTypeChange) #self.select_wall.setGeometry(1030, 90, 60, 30) self.wall_box.addWidget(self.select_wall) # 1.2.2 墙体笔刷 self.wall_brush = QBrush(Qt.Dense6Pattern) self.wall_brush.setColor(Qt.darkGray) self.wall_width = 1 #1.2.3 墙体宽度标签 self.wall_width_label = QLabel(self) self.wall_width_label.setText("宽度(m): ") self.wall_width_label.setFont(QFont("Noto Sans CJK SC")) #self.wall_width_label.setGeometry(1090, 90, 60, 30) self.wall_box.addWidget(self.wall_width_label) # 1.2.3 墙体宽度输入框 self.wall_width_input = QLineEdit(self) self.wall_width_input.setText("1") #self.wall_width_input.setGeometry(1140, 95, 30, 20) self.wall_width_input.setAlignment(Qt.AlignRight) self.wall_box.addWidget(self.wall_width_input) self.wall_width_input.textChanged.connect(self.widthChange) self.right_layout.addLayout(self.wall_box) # 1.3.1 立柱选择框 self.pillar_box = QHBoxLayout() self.select_pillar = QRadioButton(self) self.select_pillar.setText("立柱, ") self.select_pillar.setFont(QFont("Noto Sans CJK SC")) self.select_pillar.toggled.connect(self.drawTypeChange) #self.select_pillar.setGeometry(1030, 90, 60, 30) self.pillar_box.addWidget(self.select_pillar) # 1.3.2 立柱笔刷 self.pillar_brush = QBrush(Qt.Dense4Pattern) self.pillar_brush.setColor(Qt.darkGray) self.pillar_width = 1 # 1.3.3 立柱宽度标签 self.pillar_width_label = QLabel(self) self.pillar_width_label.setText("宽度(m): ") self.pillar_width_label.setFont(QFont("Noto Sans CJK SC")) # self.wall_width_label.setGeometry(1090, 90, 60, 30) self.pillar_box.addWidget(self.pillar_width_label) # 1.3.3 立柱宽度输入框 self.pillar_width_input = QLineEdit(self) self.pillar_width_input.setText("1") # self.wall_width_input.setGeometry(1140, 95, 30, 20) self.pillar_width_input.setAlignment(Qt.AlignRight) self.pillar_box.addWidget(self.pillar_width_input) self.pillar_width_input.textChanged.connect(self.widthChange) self.right_layout.addLayout(self.pillar_box) # 1.4.1 柜台选择框 #self.counter_box = QHBoxLayout() self.select_counter = QRadioButton(self) self.select_counter.setText("柜台. ") self.select_counter.setFont(QFont("Noto Sans CJK SC")) self.select_counter.toggled.connect(self.drawTypeChange) #self.select_counter.setGeometry(1030, 90, 60, 30) self.right_layout.addWidget(self.select_counter) #self.counter_box.addWidget(self.select_counter) # 1.4.2 柜台笔刷 self.counter_brush = QBrush(Qt.HorPattern) self.counter_brush.setColor(Qt.darkGray) self.counter_width = 1 # # 1.4.3 柜台宽度标签 # self.counter_width_label = QLabel(self) # self.counter_width_label.setText("宽度(m): ") # self.counter_width_label.setFont(QFont("Noto Sans CJK SC")) # # self.wall_width_label.setGeometry(1090, 90, 60, 30) # self.counter_box.addWidget(self.counter_width_label) # # 1.4.3 柜台宽度输入框 # self.counter_width_input = QLineEdit(self) # self.counter_width_input.setText("1") # # self.wall_width_input.setGeometry(1140, 95, 30, 20) # self.counter_width_input.setAlignment(Qt.AlignRight) # self.counter_box.addWidget(self.counter_width_input) # self.counter_width_input.textChanged.connect(self.widthChange) #self.right_layout.addLayout(self.counter_box) # 2. 绘制障碍物标题 self.right_layout.addStretch() self.destination_label = QLabel(self) self.destination_label.setText("绘制出入口及休息区: ") self.destination_label.setFont(QFont("Noto Sans CJK SC")) # self.obstacle_label.setGeometry(1010, 40, 100, 30) self.right_layout.addWidget(self.destination_label) self.destination_pen = QPen(Qt.DashDotDotLine) self.destination_pen.setColor(Qt.lightGray) # 2.1 绘制出口 # 2.1.1 出口选择框 self.select_exit = QRadioButton(self) self.select_exit.setText("出口. ") self.select_exit.setFont(QFont("Noto Sans CJK SC")) self.select_exit.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_exit) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.1.2 出口笔刷 self.exit_brush = QBrush(Qt.BDiagPattern) color = QColor(0, 255, 0, 130) self.exit_brush.setColor(color) self.exit_width = 2 # 2.2 绘制入口 # 2.2.1 入口选择框 self.select_entry = QRadioButton(self) self.select_entry.setText("入口. ") self.select_entry.setFont(QFont("Noto Sans CJK SC")) self.select_entry.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_entry) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.2.2 入口笔刷 self.entry_brush = QBrush(Qt.DiagCrossPattern) color = QColor(0, 255, 0, 130) self.entry_brush.setColor(color) self.entry_width = 2 # 2.3 绘制出入口 # 2.3.1 出入口选择框 self.select_passage = QRadioButton(self) self.select_passage.setText("出入口. ") self.select_passage.setFont(QFont("Noto Sans CJK SC")) self.select_passage.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_passage) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.3.2 出入口笔刷 self.passage_brush = QBrush(Qt.Dense6Pattern) color = QColor(0, 255, 0, 120) self.passage_brush.setColor(color) self.passage_width = 2 # 2.4 绘制休息区 # 2.4.1 休息区选择框 self.select_waiting = QRadioButton(self) self.select_waiting.setText("休息区. ") self.select_waiting.setFont(QFont("Noto Sans CJK SC")) self.select_waiting.toggled.connect(self.drawTypeChange) self.right_layout.addWidget(self.select_waiting) # self.select_railing.setGeometry(1030, 65, 60, 30) # 2.4.2 休息区笔刷 self.waiting_brush = QBrush(Qt.SolidPattern) color = QColor(0, 255, 0, 25) self.waiting_brush.setColor(color) self.right_layout.addStretch() # 3. 保存图片按键 self.save_button = QPushButton(self) self.save_button.setText("保存地图") self.save_button.setFont(QFont("Noto Sans CJK SC")) self.save_button.clicked.connect(self.saveMap) self.right_layout.addWidget(self.save_button) self.right_layout.addStretch() self.right_layout.addStretch() self.right_layout.addStretch() self.brush = self.railing_brush self.pen = self.obstacle_pen self.draw_type = "railing" self.width = self.railing_width self.setCentralWidget(self.splitter) self.setCentralWidget(self.splitter) self.splitter.setMouseTracking(True) self.setMouseTracking(True) self.image_label.setMouseTracking(True) self.image_label.installEventFilter(self) self.select_railing.setChecked(True) self.update()
def draw_circles(self, qp): qp.setBrush(QColor(0, 0, 0, 0)) for color, data in self.circles: pen = QPen(QColor(*color), 5) qp.setPen(pen) qp.drawEllipse(*data)