def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(3, min(rect.width() // 10, 8)) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 * disc_width) gap = 60 # degrees gradient = QConicalGradient(drawing_rect.center(), angle - gap // 2) gradient.setColorAt((360 - gap // 2) / 360.0, light) gradient.setColorAt(0, dark) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - gap) * 16)
def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(4, rect.width() // 10) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width) try: angle_for_width = math.degrees(math.atan2(1.3 * disc_width, drawing_rect.width())) except ZeroDivisionError: angle_for_width = 5 gradient = QConicalGradient(drawing_rect.center(), angle - angle_for_width) gradient.setColorAt(1, light) gradient.setColorAt(0, dark) painter.setPen(QPen(light, disc_width)) painter.drawArc(drawing_rect, 0, 360 * 16) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - 2 * angle_for_width) * 16)
def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(4, rect.width() // 10) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width) try: angle_for_width = math.degrees(math.atan2(1.3 * disc_width, drawing_rect.width())) except ZeroDivisionError: angle_for_width = 5 gradient = QConicalGradient(drawing_rect.center(), angle - angle_for_width) gradient.setColorAt(1, light) gradient.setColorAt(0, dark) painter.setPen(QPen(light, disc_width)) painter.drawArc(drawing_rect, 0, 360 * 16) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - 2 * angle_for_width) * 16)
def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(3, min(rect.width() // 10, 8)) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width) gap = 60 # degrees gradient = QConicalGradient(drawing_rect.center(), angle - gap // 2) gradient.setColorAt((360 - gap//2)/360.0, light) gradient.setColorAt(0, dark) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - gap) * 16)
def draw(self, event, qp): # self.angle += 0.04 # self._set_current_angle_in_radians(self.angle) #-------------------------------------------------------------------- # Draw X axis #-------------------------------------------------------------------- pen = QPen(QColor(120, 120, 120)) pen.setWidth(2) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) qp.drawLine(0, self.x_axis_y_coordinate, self.width() - self.x_axis_offset_from_right, self.x_axis_y_coordinate) #-------------------------------------------------------------------- # Draw rectangle that will have the vector's shadow #-------------------------------------------------------------------- pen = QPen(QColor(100, 100, 100)) pen.setWidth(2) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) qp.setOpacity(0.2) qp.drawRect( self.width() - self.x_axis_offset_from_right - self.pen_width // 2 - 2, self.x_axis_y_coordinate - self.amplitude - self.pen_width // 2 - 2, self.pen_width + 2, self.amplitude * 2 + self.pen_width + 2) qp.setOpacity(1) #-------------------------------------------------------------------- # Draw vector shadow, if enabled #-------------------------------------------------------------------- if self.draw_shadow: pen = QPen(QColor(220, 20, 20)) pen.setWidth(2) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) qp.setBrush(QColor(220, 20, 20)) qp.setOpacity(1) qp.drawRect( self.width() - self.x_axis_offset_from_right - self.pen_width // 2, self.x_axis_y_coordinate - self.current_height, self.pen_width, self.current_height) qp.setOpacity(1) #-------------------------------------------------------------------- # Draw rotating vector, if enabled #-------------------------------------------------------------------- if self.draw_rotating_vector: vector_origin = Point() vector_origin.x = self.width( ) - self.x_axis_offset_from_right + 20 + self.amplitude vector_origin.y = self.x_axis_y_coordinate vector_width = self.amplitude * math.cos( self.current_angle_in_radians) vector_height = self.amplitude * math.sin( self.current_angle_in_radians) vector_tip = Point() vector_tip.x = vector_origin.x + vector_width vector_tip.y = vector_origin.y - vector_height #---------------------------------------------------- # Draw vector axis and tracing circle pen = QPen(QColor(120, 120, 120)) pen.setWidth(2) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) qp.setBrush(QColor(220, 20, 20)) qp.setOpacity(0.1) qp.drawEllipse(vector_origin.x - self.amplitude, vector_origin.y - self.amplitude, 2 * self.amplitude, 2 * self.amplitude) qp.setOpacity(0.3) # vector's x axis qp.drawLine(vector_origin.x - self.amplitude - 10, vector_origin.y, vector_origin.x + self.amplitude + 10, vector_origin.y) # vector's y axis qp.drawLine(vector_origin.x, vector_origin.y - self.amplitude - 10, vector_origin.x, vector_origin.y + self.amplitude + 10) qp.setOpacity(1) #---------------------------------------------------- # Draw vector itself. pen = QPen(QColor(220, 20, 20)) pen.setWidth(self.pen_width) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) qp.setBrush(QColor(220, 20, 20)) qp.setOpacity(1) qp.drawLine(vector_origin.x, vector_origin.y, vector_tip.x, vector_tip.y) qp.setOpacity(1) #---------------------------------------------------- # Draw vector tip projection pen = QPen(QColor(20, 20, 20)) pen.setWidth(self.pen_width) pen.setStyle(Qt.DotLine) qp.setPen(pen) qp.setOpacity(0.2) qp.drawLine(vector_tip.x, vector_tip.y, self.width() - self.x_axis_offset_from_right, self.x_axis_y_coordinate - vector_height) qp.setOpacity(1) #-------------------------------------------------------------------- # Draw background #-------------------------------------------------------------------- font = QFont() font.setPixelSize(30) pen = QPen(QColor(100, 100, 100)) qp.setPen(pen) qp.setBrush(Qt.green) qp.setFont(font) qp.setOpacity(0.2) for p in self.bkTextPoints + self.timeTextPoints: # qp.rotate(45) qp.drawText(p.x, p.y, p.text) # qp.drawEllipse(p.x, p.y, 50, 30) # qp.rotate(-45) #-------------------------------------------------- # If time isn't paused, shift all background objects left if not self.time_paused: p.x -= self.time_x_increment if p.x <= -150: p.x = 2000 qp.setOpacity(1) #-------------------------------------------------------------------- # Draw points #-------------------------------------------------------------------- # pen = QPen(QColor(120, 60, 60)) pen = QPen(QColor(220, 20, 20)) pen.setWidth(self.pen_width) pen.setCapStyle(Qt.RoundCap) qp.setPen(pen) # qp.setBrush(QBrush(Qt.black)) if not self.time_paused: # Copy height of each point to the point on its left (older point) for i in reversed(range(len(self.ordinates) - 1)): self.ordinates[i + 1] = self.ordinates[i] #print("Using current height of " + str(self.current_height)) self.ordinates[ 0] = -self.current_height # set height of "current" (rightmost) sample for i in range(len(self.ordinates) - 1): qp.drawLine( self.width() - self.x_axis_offset_from_right - i * self.time_x_increment, self.ordinates[i] + self.x_axis_y_coordinate, self.width() - self.x_axis_offset_from_right - (i + 1) * self.time_x_increment, self.ordinates[i + 1] + self.x_axis_y_coordinate)
class PaintBoard(QLabel): signal_right_mouse = pyqtSignal(int) signal_draw = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.__parent = parent self.__board = QPixmap(QSize(440, 440)) self.__board.fill(Qt.transparent) self.__board_old = self.__board.copy() self.__board_old_old = self.__board.copy() self.__board_before_dots = self.__board.copy() self.__thickness = 10 # 默认画笔粗细为10px self.__penColor = QColor(0, 0, 0, 128) self.__painter = QPainter() self.__pen = QPen(self.__penColor, self.__thickness) self.__pen_seg = QPen(QColor(0, 0, 0, 128)) self.__brush = QBrush(QColor(0, 0, 0, 128)) self.__pen.setCapStyle(Qt.RoundCap) #self.__painter.setPen(self.__pen) self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 self.__points = [] # dots模式的点集 self.__mouse_pressed = False self.__can_undo = False self.__has_seg = False self.__mode = 1 self.__ERASE = 0 self.__LINE = 1 self.__RECT = 2 self.__CIRCLE = 3 self.__DOTS = 4 self.__transparent = False self.__trans_board = self.__board.copy() self.__trans_board.fill(Qt.transparent) @staticmethod def dist(p1, p2): return math.hypot(p1.x() - p2.x(), p1.y() - p2.y()) # Each time paintEvent is called it clean the space where it is going to draw. # So it does not save memory of the previous drawings, # A simple solution is to first paint a QPixmap to store what you have painted. # And then paint the widget with that QPixmap. def set_trans(self, trans): self.__transparent = trans self.update() def is_trans(self): return self.__transparent def paintEvent(self, paint_event): # 把board绘制到界面上 self.__painter.begin(self) if not self.__transparent: self.__painter.drawPixmap(0, 0, self.__board) else: self.__painter.drawPixmap(0, 0, self.__trans_board) #结果图关闭mask self.__painter.end() def mousePressEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: self.__mouse_pressed = True self.__board_old_old = self.__board_old.copy() self.__board_old = self.__board.copy() self.__currentPos = mouse_event.pos() self.__lastPos = self.__currentPos if self.__mode == self.__DOTS: if len(self.__points) == 0: self.__board_before_dots = self.__board.copy() self.__parent.childAt(740, 0).setEnabled(False) self.__parent.childAt(840, 0).setEnabled(False) self.__parent.childAt(370, 0).setEnabled(False) self.__parent.childAt(300, 610).setEnabled(False) if len(self.__points) > 0: print( self.dist( self.__points[0], QPoint(self.__currentPos.x(), self.__currentPos.y()))) if len(self.__points) > 2 and \ self.dist(self.__points[0], QPoint(self.__currentPos.x(), self.__currentPos.y())) < 5: self.__board = self.__board_before_dots.copy() self.__painter.begin(self.__board) if self.__ERASE: self.__painter.setCompositionMode( QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) self.__painter.drawPolygon(QPolygon(self.__points)) self.signal_draw.emit() self.__painter.end() self.__points.clear() self.__parent.childAt(740, 0).setEnabled(True) self.__parent.childAt(840, 0).setEnabled(True) self.__parent.childAt(370, 0).setEnabled(True) self.__parent.childAt(300, 610).setEnabled(True) self.update() else: self.__points.append( QPoint(self.__currentPos.x(), self.__currentPos.y())) if not (self.__mode == self.__DOTS and len(self.__points) == 1): self.__can_undo = True self.__parent.childAt(70, 610).setEnabled(True) else: self.__can_undo = False self.__parent.childAt(70, 610).setEnabled(False) def mouseMoveEvent(self, mouse_event): # 把线绘制到board上 self.__currentPos = mouse_event.pos() if self.__mode != self.__LINE: if len(self.__points) > 0: self.__board = self.__board_old.copy() elif not self.__mode == self.__DOTS: if self.__mouse_pressed: self.__board = self.__board_old.copy() self.__painter.begin(self.__board) self.__painter.setPen(self.__pen) if self.__ERASE: self.__painter.setCompositionMode(QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode(QPainter.CompositionMode_Source) if self.__mode == self.__LINE: if self.__mouse_pressed: self.__painter.drawLine(self.__lastPos, self.__currentPos) self.signal_draw.emit() elif self.__mode == self.__RECT: self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) if self.__mouse_pressed: self.__painter.drawRect( self.__lastPos.x(), self.__lastPos.y(), (self.__currentPos.x() - self.__lastPos.x()), (self.__currentPos.y() - self.__lastPos.y())) self.signal_draw.emit() elif self.__mode == self.__CIRCLE: self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) if self.__mouse_pressed: self.__painter.drawEllipse( self.__lastPos.x(), self.__lastPos.y(), (self.__currentPos.x() - self.__lastPos.x()), (self.__currentPos.y() - self.__lastPos.y())) self.signal_draw.emit() elif self.__mode == self.__DOTS: if len(self.__points) > 0: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.setPen(QPen(self.__pen_seg.color(), 1)) self.__painter.drawLine(self.__points[-1], self.__currentPos) self.signal_draw.emit() self.__painter.end() if self.__mode == self.__LINE: self.__lastPos = self.__currentPos self.update() # 触发paintEvent def mouseDoubleClickEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: if not self.__mode == self.__DOTS: if self.__has_seg: x = mouse_event.pos().x() y = mouse_event.pos().y() value = self.segment[y][x] # 注意这里x和y要反过来 self.__painter.begin(self.__board) self.paint_segment(value, x, y) self.__painter.end() self.signal_draw.emit() self.update() # 触发paintEvent def mouseReleaseEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: self.__mouse_pressed = False if mouse_event.button() == Qt.RightButton: self.signal_right_mouse.emit(1 - self.__ERASE) return def undo(self): if self.__can_undo: if self.__mode != self.__DOTS: self.__board = self.__board_old.copy() else: if len(self.__points) == 0: self.__board = self.__board_before_dots.copy() else: self.__points.pop() self.__board = self.__board_old_old.copy() self.__board_old = self.__board_old_old.copy() self.signal_draw.emit() self.update() self.__can_undo = False self.__parent.childAt(70, 610).setEnabled(False) def update_segment(self, seg): self.segment = seg self.__parent.childAt(1040, 0).setEnabled(False) self.__has_seg = True def set_board(self, x, y): self.__board = self.__board.scaled(x, y) def update_board(self, board): self.__board = board self.update() def paint_segment(self, value, x, y): has_painted = np.zeros(self.segment.shape, dtype=np.uint8) point_stack = [(x, y)] while len(point_stack) > 0: point = point_stack.pop() x = point[0] y = point[1] self.__painter.setPen(self.__pen_seg) if self.__ERASE: self.__painter.setCompositionMode( QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.drawPoint(x, y) has_painted[y][x] = 1 if x + 1 < self.segment.shape[1] and has_painted[y][ x + 1] == 0 and value == self.segment[y][x + 1]: point_stack.append((x + 1, y)) if x - 1 >= 0 and has_painted[y][ x - 1] == 0 and value == self.segment[y][x - 1]: point_stack.append((x - 1, y)) if y + 1 < self.segment.shape[0] and has_painted[ y + 1][x] == 0 and value == self.segment[y + 1][x]: point_stack.append((x, y + 1)) if y - 1 >= 0 and has_painted[ y - 1][x] == 0 and value == self.segment[y - 1][x]: point_stack.append((x, y - 1)) def Thanos(self, label): if len(label) == 0: return False image = self.__board.copy() image.fill(Qt.transparent) pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] for l in label: mask[self.segment == l] = 255 expand_mask(mask, 5) #Image.fromarray(np.uint8(mask)).save('mask_10.jpg') return mask def set_seg(self): self.__has_seg = False def set_pen(self, value): self.__pen.setWidth(value) def pen_black(self): self.__pen.setColor(QColor(0, 0, 0, 128)) def pen_white(self): self.__pen.setColor(QColor(255, 255, 255, 128)) def geo_black(self): self.__pen_seg.setColor(QColor(0, 0, 0, 128)) self.__brush = QBrush(QColor(0, 0, 0, 128)) def geo_white(self): self.__pen_seg.setColor(QColor(255, 255, 255, 128)) self.__brush = QBrush(QColor(255, 255, 255, 128)) def switch_mode(self): self.__ERASE = 1 - self.__ERASE def set_mode(self, mode): self.__ERASE = mode def tool_pen(self): self.__mode = self.__LINE def tool_rect(self): self.__mode = self.__RECT def tool_circle(self): self.__mode = self.__CIRCLE def tool_dots(self): self.__mode = self.__DOTS def clear_board(self): self.__board.fill(Qt.transparent) self.__board_old = self.__board.copy() self.__board_before_dots = self.__board.copy() self.__board_old_old = self.__board.copy() self.__parent.childAt(70, 610).setEnabled(False) self.signal_draw.emit() self.update() def save(self): # save_path = QFileDialog.getSaveFileName(self, 'Save Your Paint', '.\\', '*.jpg') save_path = 'D:/test.png', '*.png' print(save_path) if save_path[0] == "": print("Save cancel") return image = self.__board pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] print(mask) # qimage2numpy(pixels) # Pixels can only be accessed through QPainter functions or by converting the QPixmap to a QImage. image.save(save_path[0]) def get_mask(self): image = self.__board pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] # 取alpha通道,就是不透明度 mask[mask > 0] = 255 return mask def get_board(self): return self.__board.copy() def test(self): # self.pix = QPixmap("road.jpg") self.__painter.begin(self.__board) for i in range(301): for j in range(301): self.__painter.drawPoint(i, j) self.__painter.end() self.update()