def paintEvent(self, event): ''' @param: event QPaintEvent ''' if not self._use_background: return painter = QPainter(self) rect = self._side_widget.rect().adjusted(0, 0, 1, 0) rect = self.style().visualRect(self.layoutDirection(), self.geometry(), rect) styleHelper.verticalGradient(painter, rect, rect) if not self._background_pixmap.isNull(): pixmap_rect = QRect(self._background_pixmap.rect()) pixmap_rect.moveTo(rect.topLeft()) while pixmap_rect.top() < rect.bottom(): source_rect = QRect(pixmap_rect.intersected(rect)) source_rect.moveTo(0, 0) painter.drawPixmap(pixmap_rect.topLeft(), self._background_pixmap, source_rect) pixmap_rect.moveTop(pixmap_rect.bottom() - 10) painter.setPen(styleHelper.borderColor()) painter.drawLine(rect.topRight(), rect.bottomRight()) # QColor light = styleHelper.sidebarHighlight() painter.setPen(light) painter.drawLine(rect.bottomLeft(), rect.bottomRight())
class PaintBoard(QWidget): def __init__(self, parent=None): super().__init__(parent) self.__InitData() self.__InitView() def __InitData(self): self.__size = QSize(280, 280) self.__board = QPixmap(self.__size) self.__board.fill(Qt.black) self.__isEmpty = True self.__lastPose = QPoint(0, 0) self.__currentPose = QPoint(0, 0) self.__painter = QPainter() self.__thickness = 20 self.__penColor = QColor('white') def __InitView(self): self.setFixedSize(self.__size) def paintEvent(self, paintEvent): self.__painter.begin(self) self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() def mousePressEvent(self, mouseEvent): self.__currentPose = mouseEvent.pos() self.__lastPose = self.__currentPose def mouseMoveEvent(self, mouseEvent): self.__currentPose = mouseEvent.pos() self.__painter.begin(self.__board) self.__painter.setPen(QPen(self.__penColor, self.__thickness)) self.__painter.drawLine(self.__lastPose, self.__currentPose) self.__painter.end() self.__lastPose = self.__currentPose self.update() def mouseReleaseEvent(self, mouseEvent): self.__isEmpty = False def clear(self): self.__board.fill(Qt.black) self.update() self.__isEmpty = True def isEmpty(self): return self.__isEmpty def getImage(self): image = self.__board.toImage() return image
def paint_line_numbers(self, ev): painter = QPainter(self.line_number_area) painter.fillRect( ev.rect(), self.line_number_palette.color(QPalette.ColorRole.Base)) block = self.firstVisibleBlock() num = block.blockNumber() top = int( self.blockBoundingGeometry(block).translated( self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) painter.setPen(self.line_number_palette.color(QPalette.ColorRole.Text)) change_starts = {x[0] for x in self.changes} while block.isValid() and top <= ev.rect().bottom(): r = ev.rect() if block.isVisible() and bottom >= r.top(): text = unicode_type(self.line_number_map.get(num, '')) is_start = text != '-' and num in change_starts if is_start: painter.save() f = QFont(self.font()) f.setBold(True) painter.setFont(f) painter.setPen( self.line_number_palette.color( QPalette.ColorRole.BrightText)) if text == '-': painter.drawLine(r.left() + 2, (top + bottom) // 2, r.right() - 2, (top + bottom) // 2) else: if self.right: painter.drawText(r.left() + 3, top, r.right(), self.fontMetrics().height(), Qt.AlignmentFlag.AlignLeft, text) else: painter.drawText(r.left() + 2, top, r.right() - 5, self.fontMetrics().height(), Qt.AlignmentFlag.AlignRight, text) if is_start: painter.restore() block = block.next() top = bottom bottom = top + int(self.blockBoundingRect(block).height()) num += 1
def paintEvent(self, ev): p = QPainter(self) p.setClipRect(ev.rect()) palette = self.palette() p.setPen(palette.color(QPalette.WindowText)) if not self.is_first: p.drawLine(0, 0, self.width(), 0) try: for row in self.rows: for cell in row: p.save() try: cell.draw(p, self.width(), palette) finally: p.restore() finally: p.end()
def paintEvent(self, ev): offset = QPoint(0, 0) p = QPainter(self) p.setClipRect(ev.rect()) bottom = self.rect().bottom() if self.results: for i, (prefix, full, text) in enumerate(self.results): size = prefix.size() if offset.y() + size.height() > bottom: break self.max_result = i offset.setX(0) if i in (self.current_result, self.mouse_hover_result): p.save() if i != self.current_result: p.setPen(Qt.PenStyle.DotLine) p.drawLine(offset, QPoint(self.width(), offset.y())) p.restore() offset.setY(offset.y() + self.MARGIN // 2) p.drawStaticText(offset, prefix) offset.setX(self.maxwidth + 5) p.drawStaticText(offset, self.divider) offset.setX(offset.x() + self.divider.size().width()) p.drawStaticText(offset, full) offset.setY(offset.y() + size.height() + self.MARGIN // 2) if i in (self.current_result, self.mouse_hover_result): offset.setX(0) p.save() if i != self.current_result: p.setPen(Qt.PenStyle.DotLine) p.drawLine(offset, QPoint(self.width(), offset.y())) p.restore() else: p.drawText(self.rect(), Qt.AlignmentFlag.AlignCenter, _('No results found')) p.end()
def paintEvent(self, ev): offset = QPoint(0, 0) p = QPainter(self) p.setClipRect(ev.rect()) bottom = self.rect().bottom() if self.results: for i, (prefix, full, text) in enumerate(self.results): size = prefix.size() if offset.y() + size.height() > bottom: break self.max_result = i offset.setX(0) if i in (self.current_result, self.mouse_hover_result): p.save() if i != self.current_result: p.setPen(Qt.DotLine) p.drawLine(offset, QPoint(self.width(), offset.y())) p.restore() offset.setY(offset.y() + self.MARGIN // 2) p.drawStaticText(offset, prefix) offset.setX(self.maxwidth + 5) p.drawStaticText(offset, self.divider) offset.setX(offset.x() + self.divider.size().width()) p.drawStaticText(offset, full) offset.setY(offset.y() + size.height() + self.MARGIN // 2) if i in (self.current_result, self.mouse_hover_result): offset.setX(0) p.save() if i != self.current_result: p.setPen(Qt.DotLine) p.drawLine(offset, QPoint(self.width(), offset.y())) p.restore() else: p.drawText(self.rect(), Qt.AlignCenter, _('No results found')) p.end()
def paint_line_numbers(self, ev): painter = QPainter(self.line_number_area) painter.fillRect(ev.rect(), self.line_number_palette.color(QPalette.Base)) block = self.firstVisibleBlock() num = block.blockNumber() top = int(self.blockBoundingGeometry(block).translated(self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) painter.setPen(self.line_number_palette.color(QPalette.Text)) change_starts = {x[0] for x in self.changes} while block.isValid() and top <= ev.rect().bottom(): r = ev.rect() if block.isVisible() and bottom >= r.top(): text = unicode(self.line_number_map.get(num, '')) is_start = text != '-' and num in change_starts if is_start: painter.save() f = QFont(self.font()) f.setBold(True) painter.setFont(f) painter.setPen(self.line_number_palette.color(QPalette.BrightText)) if text == '-': painter.drawLine(r.left() + 2, (top + bottom)//2, r.right() - 2, (top + bottom)//2) else: if self.right: painter.drawText(r.left() + 3, top, r.right(), self.fontMetrics().height(), Qt.AlignLeft, text) else: painter.drawText(r.left() + 2, top, r.right() - 5, self.fontMetrics().height(), Qt.AlignRight, text) if is_start: painter.restore() block = block.next() top = bottom bottom = top + int(self.blockBoundingRect(block).height()) num += 1
def paintEvent(self, event): w = self.viewport().rect().width() painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) floor = event.rect().bottom() ceiling = event.rect().top() fv = self.firstVisibleBlock().blockNumber() origin = self.contentOffset() doc = self.document() lines = [] for num, text in self.headers: top, bot = num, num + 3 if bot < fv: continue y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break painter.setFont(self.heading_font) br = painter.drawText(3, y_top, w, y_bot - y_top - 5, Qt.TextSingleLine, text) painter.setPen(QPen(self.palette().text(), 2)) painter.drawLine(0, br.bottom()+3, w, br.bottom()+3) for top, bot, kind in self.changes: if bot < fv: continue y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break if y_top != y_bot: painter.fillRect(0, y_top, w, y_bot - y_top, self.diff_backgrounds[kind]) lines.append((y_top, y_bot, kind)) if top in self.images: img, maxw = self.images[top][:2] if bot > top + 1 and not img.isNull(): y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top+1)).translated(origin).y() + 3 y_bot -= 3 scaled, imgw, imgh = fit_image(int(img.width()/img.devicePixelRatio()), int(img.height()/img.devicePixelRatio()), w - 3, y_bot - y_top) painter.drawPixmap(QRect(3, y_top, imgw, imgh), img) painter.end() PlainTextEdit.paintEvent(self, event) painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) for top, bottom, kind in sorted(lines, key=lambda t_b_k:{'replace':0}.get(t_b_k[2], 1)): painter.setPen(QPen(self.diff_foregrounds[kind], 1)) painter.drawLine(0, top, w, top) painter.drawLine(0, bottom - 1, w, bottom - 1)
def paintEvent(self, event): w = self.viewport().rect().width() painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) floor = event.rect().bottom() ceiling = event.rect().top() fv = self.firstVisibleBlock().blockNumber() origin = self.contentOffset() doc = self.document() lines = [] for num, text in self.headers: top, bot = num, num + 3 if bot < fv: continue y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break painter.setFont(self.heading_font) br = painter.drawText(3, y_top, w, y_bot - y_top - 5, Qt.TextSingleLine, text) painter.setPen(QPen(self.palette().text(), 2)) painter.drawLine(0, br.bottom()+3, w, br.bottom()+3) for top, bot, kind in self.changes: if bot < fv: continue y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry(doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break if y_top != y_bot: painter.fillRect(0, y_top, w, y_bot - y_top, self.diff_backgrounds[kind]) lines.append((y_top, y_bot, kind)) if top in self.images: img, maxw = self.images[top][:2] if bot > top + 1 and not img.isNull(): y_top = self.blockBoundingGeometry(doc.findBlockByNumber(top+1)).translated(origin).y() + 3 y_bot -= 3 scaled, imgw, imgh = fit_image(img.width(), img.height(), w - 3, y_bot - y_top) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) painter.drawPixmap(QRect(3, y_top, imgw, imgh), img) painter.end() PlainTextEdit.paintEvent(self, event) painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) for top, bottom, kind in sorted(lines, key=lambda (t, b, k):{'replace':0}.get(k, 1)): painter.setPen(QPen(self.diff_foregrounds[kind], 1)) painter.drawLine(0, top, w, top) painter.drawLine(0, bottom - 1, w, bottom - 1)
class PaintBoard(QWidget): def __init__(self, Parent=None): ''' Constructor ''' super().__init__(Parent) self.__InitData() #先初始化数据,再初始化界面 self.__InitView() def __InitView(self): self.setFixedSize(self.__size) def __InitData(self): self.__size = QSize(1600,1200) self.__board = QPixmap(self.__size) #新建QPixmap作为画板,宽350px,高250px self.__board.fill(Qt.white) #用白色填充画板 self.__IsEmpty = True #默认为空画板 self.EraserMode = False #默认为禁用橡皮擦模式 self.__lastPos = QPoint(0,0) self.__currentPos = QPoint(0,0) self.__painter = QPainter() self.__thickness = 10 #默认画笔粗细为10px self.__penColor = QColor("black") #设置默认画笔颜色为黑色 self.__colorList = QColor.colorNames() #获取颜色列表 def Clear(self): #清空画板 self.__board.fill(Qt.white) self.update() self.__IsEmpty = True def ChangePenColor(self, color="black"): #改变画笔颜色 self.__penColor = QColor(color) def ChangePenThickness(self, thickness=10): #改变画笔粗细 self.__thickness = thickness def IsEmpty(self): #返回画板是否为空 return self.__IsEmpty def GetContentAsQImage(self): #获取画板内容(返回QImage) image = self.__board.toImage() return image def paintEvent(self, paintEvent): self.__painter.begin(self) self.__painter.drawPixmap(0,0,self.__board) self.__painter.end() def mousePressEvent(self, mouseEvent): self.__currentPos = mouseEvent.pos() self.__lastPos = self.__currentPos def mouseMoveEvent(self, mouseEvent): self.__currentPos = mouseEvent.pos() self.__painter.begin(self.__board) if self.EraserMode == False: #非橡皮擦模式 self.__painter.setPen(QPen(self.__penColor,self.__thickness)) #设置画笔颜色,粗细 else: #橡皮擦模式下画笔为纯白色,粗细为10 self.__painter.setPen(QPen(Qt.white,10)) self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() #更新显示 def mouseReleaseEvent(self, mouseEvent): self.__IsEmpty = False #画板不再为空
class PaintBoard(QWidget): def __init__(self, Parent=None): super().__init__(Parent) self.__init_data() self.__init_view() def __init_data(self): """ initial the canvas, painter :return: """ self.__size = QSize(420, 420) # create a new canvas by QPixmap, size for self.__size self.__canvas = QPixmap(self.__size) # set the background of the board as white, for better visual effect self.__canvas.fill(Qt.white) # default for none self.__IsEmpty = True # default for no eraser self.EraserMode = False # initial the last mouse position self.__lastPos = QPoint(0, 0) # initial the current mouse position self.__currentPos = QPoint(0, 0) # new a painter for drawing self.__painter = QPainter() # default pen size for 10px self.__thickness = 30 # default pen color for black self.__penColor = QColor("black") # get the color list from library self.colorList = QColor.colorNames() def __init_view(self): """ set the initial size of the canvas :return: """ self.setFixedSize(self.__size) def clear(self): """ clear the canvas :return: """ self.__canvas.fill(Qt.white) self.update() self.__IsEmpty = True def pen_color(self, color="black"): """ set the color of the pen :param color: :return: """ self.__penColor = QColor(color) def pen_size(self, thick=40): """ set the size of the pen :param thick: :return: """ self.__thickness = thick def is_empty(self): """ return the canvas is empty or not :return: """ return self.__IsEmpty def get_current_image(self): """ fet the current content of the canvas, return as an image :return: """ current_image = self.__canvas.toImage() return current_image def paintEvent(self, paintEvent): """ the painter works between begin() and end() - begin(param): parameter--canvas - drawPixmap: paint QPixmap object 0, 0 start :param paintEvent: :return: """ self.__painter.begin(self) self.__painter.drawPixmap(0, 0, self.__canvas) self.__painter.end() def mousePressEvent(self, mouseEvent): """ capture the mouse when pressed :param mouseEvent: :return: """ self.__currentPos = mouseEvent.pos() self.__lastPos = self.__currentPos def mouseMoveEvent(self, mouseEvent): """ when the mouse moves, update the position :param mouseEvent: :return: """ self.__currentPos = mouseEvent.pos() self.__painter.begin(self.__canvas) if self.EraserMode == False: self.__painter.setPen(QPen(self.__penColor, self.__thickness)) else: self.__painter.setPen((QPen(Qt.white, 40))) self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() def mouseReleaseEvent(self, QMouseEvent): """ set the canvas for not empty :param QMouseEvent: :return: """ self.__IsEmpty = False
def drawWidget(self, painter: Qt.QPainter) -> None: from copy import deepcopy from vspreview.utils import strfdelta # calculations if self.need_full_repaint: labels_notches = Notches() label_notch_bottom = (self.rect_f.top() + self.font_height + self.notch_label_interval + self.notch_height + 5) label_notch_top = label_notch_bottom - self.notch_height label_notch_x = self.rect_f.left() if self.mode == self.Mode.TIME: notch_interval_t = self.calculate_notch_interval_t( self.notch_interval_target_x) label_format = self.generate_label_format( notch_interval_t, self.end_t) label_notch_t = Time() while (label_notch_x < self.rect_f.right() and label_notch_t <= self.end_t): line = Qt.QLineF(label_notch_x, label_notch_bottom, label_notch_x, label_notch_top) labels_notches.add( Notch(deepcopy(label_notch_t), line=line)) label_notch_t += notch_interval_t label_notch_x = self.t_to_x(label_notch_t) elif self.mode == self.Mode.FRAME: notch_interval_f = self.calculate_notch_interval_f( self.notch_interval_target_x) label_notch_f = Frame(0) while (label_notch_x < self.rect_f.right() and label_notch_f <= self.end_f): line = Qt.QLineF(label_notch_x, label_notch_bottom, label_notch_x, label_notch_top) labels_notches.add( Notch(deepcopy(label_notch_f), line=line)) label_notch_f += notch_interval_f label_notch_x = self.f_to_x(label_notch_f) self.scroll_rect = Qt.QRectF( self.rect_f.left(), label_notch_bottom + self.notch_scroll_interval, self.rect_f.width(), self.scroll_height) for toolbar, notches in self.toolbars_notches.items(): if not toolbar.is_notches_visible(): continue for notch in notches: if isinstance(notch.data, Frame): x = self.f_to_x(notch.data) elif isinstance(notch.data, Time): x = self.t_to_x(notch.data) y = self.scroll_rect.top() notch.line = Qt.QLineF(x, y, x, y + self.scroll_rect.height() - 1) cursor_line = Qt.QLineF( self.cursor_x, self.scroll_rect.top(), self.cursor_x, self.scroll_rect.top() + self.scroll_rect.height() - 1) # drawing if self.need_full_repaint: painter.fillRect(self.rect_f, self.palette().color(Qt.QPalette.Window)) painter.setPen( Qt.QPen(self.palette().color(Qt.QPalette.WindowText))) painter.setRenderHint(Qt.QPainter.Antialiasing, False) painter.drawLines([notch.line for notch in labels_notches]) painter.setRenderHint(Qt.QPainter.Antialiasing) for i, notch in enumerate(labels_notches): line = notch.line anchor_rect = Qt.QRectF(line.x2(), line.y2() - self.notch_label_interval, 0, 0) if self.mode == self.Mode.TIME: time = cast(Time, notch.data) label = strfdelta(time, label_format) if self.mode == self.Mode.FRAME: label = str(notch.data) if i == 0: rect = painter.boundingRect( anchor_rect, Qt.Qt.AlignBottom + Qt.Qt.AlignLeft, label) if self.mode == self.Mode.TIME: rect.moveLeft(-2.5) elif i == (len(labels_notches) - 1): rect = painter.boundingRect( anchor_rect, Qt.Qt.AlignBottom + Qt.Qt.AlignHCenter, label) if rect.right() > self.rect_f.right(): rect = painter.boundingRect( anchor_rect, Qt.Qt.AlignBottom + Qt.Qt.AlignRight, label) else: rect = painter.boundingRect( anchor_rect, Qt.Qt.AlignBottom + Qt.Qt.AlignHCenter, label) painter.drawText(rect, label) painter.setRenderHint(Qt.QPainter.Antialiasing, False) painter.fillRect(self.scroll_rect, Qt.Qt.gray) for toolbar, notches in self.toolbars_notches.items(): if not toolbar.is_notches_visible(): continue for notch in notches: painter.setPen(notch.color) painter.drawLine(notch.line) painter.setPen(Qt.Qt.black) painter.drawLine(cursor_line) self.need_full_repaint = False
class PaintBoard(QWidget): def __init__(self, Parent=None): super().__init__(Parent) self.__InitData() #先初始化数据,再初始化界面 self.__InitView() def __InitData(self): self.__size = QSize(1024, 512) #新建QPixmap作为画板,尺寸为__size self.__board = QPixmap(self.__size) self.__board.fill(Qt.white) #用白色填充画板 self.__IsEmpty = True #默认为空画板 self.EraserMode = False #默认为禁用橡皮擦模式 self.__lastPos = QPoint(0, 0) #上一次鼠标位置 self.__currentPos = QPoint(0, 0) #当前的鼠标位置 self.__painter = QPainter() #新建绘图工具 self.__thickness = 6 #默认画笔粗细为6px self.__eraser = 20 def __InitView(self): #设置界面的尺寸为__size self.setFixedSize(self.__size) def Clear(self): #清空画板 self.__board.fill(Qt.white) self.update() self.__IsEmpty = True def ChangePenThickness(self, eraser=20): #改变橡皮画笔粗细,默认20px self.__eraser = eraser def IsEmpty(self): #返回画板是否为空 return self.__IsEmpty def GetContentAsQImage(self): #获取画板内容(返回QImage) image = self.__board.toImage() return image def paintEvent(self, paintEvent): #绘图事件 #绘图时必须使用QPainter的实例,此处为__painter #绘图在begin()函数与end()函数间进行 #begin(param)的参数要指定绘图设备,即把图画在哪里 #drawPixmap用于绘制QPixmap类型的对象 self.__painter.begin(self) # 0,0为绘图的左上角起点的坐标,__board即要绘制的图 self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() def mousePressEvent(self, mouseEvent): #鼠标按下时,获取鼠标的当前位置保存为上一次位置 self.__currentPos = mouseEvent.pos() self.__lastPos = self.__currentPos def mouseMoveEvent(self, mouseEvent): #鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线 self.__currentPos = mouseEvent.pos() self.__painter.begin(self.__board) if self.EraserMode == False: #非橡皮擦模式 self.__painter.setPen( QPen(Qt.red, 6, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) #设置画笔颜色,粗细 else: #橡皮擦模式下画笔为纯白色 self.__painter.setPen( QPen(Qt.white, self.__eraser, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) #画线 self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() #更新显示 def mouseReleaseEvent(self, mouseEvent): self.__IsEmpty = False #画板不再为空
def decoration_for_style(palette, style, icon_size, device_pixel_ratio, is_dark): style_key = (is_dark, icon_size, device_pixel_ratio, tuple((k, style[k]) for k in sorted(style))) sentinel = object() ans = decoration_cache.get(style_key, sentinel) if ans is not sentinel: return ans ans = None kind = style.get('kind') if kind == 'color': key = 'dark' if is_dark else 'light' val = style.get(key) if val is None: which = style.get('which') val = (builtin_colors_dark if is_dark else builtin_colors_light).get(which) if val is None: val = style.get('background-color') if val is not None: ans = QColor(val) elif kind == 'decoration': which = style.get('which') if which is not None: q = builtin_decorations.get(which) if q is not None: style = q sz = int(math.ceil(icon_size * device_pixel_ratio)) canvas = QImage(sz, sz, QImage.Format.Format_ARGB32) canvas.fill(Qt.GlobalColor.transparent) canvas.setDevicePixelRatio(device_pixel_ratio) p = QPainter(canvas) p.setRenderHint(QPainter.RenderHint.Antialiasing, True) p.setPen(palette.color(QPalette.ColorRole.WindowText)) irect = QRect(0, 0, icon_size, icon_size) adjust = -2 text_rect = p.drawText( irect.adjusted(0, adjust, 0, adjust), Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop, 'a') p.drawRect(irect) fm = p.fontMetrics() pen = p.pen() if 'text-decoration-color' in style: pen.setColor(QColor(style['text-decoration-color'])) lstyle = style.get('text-decoration-style') or 'solid' q = { 'dotted': Qt.PenStyle.DotLine, 'dashed': Qt.PenStyle.DashLine, }.get(lstyle) if q is not None: pen.setStyle(q) lw = fm.lineWidth() if lstyle == 'double': lw * 2 pen.setWidth(fm.lineWidth()) q = style.get('text-decoration-line') or 'underline' pos = text_rect.bottom() height = irect.bottom() - pos if q == 'overline': pos = height elif q == 'line-through': pos = text_rect.center().y() - adjust - lw // 2 p.setPen(pen) if lstyle == 'wavy': p.drawPath(wavy_path(icon_size, height, pos)) else: p.drawLine(0, pos, irect.right(), pos) p.end() ans = QPixmap.fromImage(canvas) elif 'background-color' in style: ans = QColor(style['background-color']) decoration_cache[style_key] = ans return ans
class MyMainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MyMainWindow, self).__init__(parent) self.setupUi(self) self.setMouseTracking(True) self.imglist = [] self.ImgFolder = '' self.CurImg = '' #新建QPixmap作为画板,尺寸为__size self.__board = QPixmap() self.__board.fill(Qt.white) #用白色填充画板 self.__IsEmpty = True # 默认为空画板 self.EraserMode = False # 默认为禁用橡皮擦模式 self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 self.__painter = QPainter() # 新建绘图工具 self.__thickness = 10 # 默认画笔粗细为10px self.__penColor = QColor("black") # 设置默认画笔颜色为黑色 self.__colorList = QColor.colorNames() # 获取颜色列表 # 按键信号与回调函数连接 self.OpenDir.clicked.connect(self.OpenDirBntClicked) self.NextImg.clicked.connect(self.NextImBntClicked) self.LastImg.clicked.connect(self.PreImBntClicked) self.SaveImg.clicked.connect(self.on_btn_Save_Clicked) self.PenThicknessSpinBox.valueChanged.connect(self.on_PenThicknessChange) # self.NextImg.clicked.connect(self.NextImBntClicked) #########选择图片文件夹######### def OpenDirBntClicked(self): self.ImgFolder = QtWidgets.QFileDialog.getExistingDirectory(None, "select folder", DefaultImFolder) # 这个语句有些邪门 if self.ImgFolder != '': ImNameSet = os.listdir(self.ImgFolder) self.imglist = glob.glob(self.ImgFolder + '/*.jpg') print(self.imglist) print(ImNameSet) ImNameSet.sort() # ImPath = os.path.join(ImFolder, ImNameSet[0]) ImPath = os.path.join(self.ImgFolder, ImNameSet[1]) # pix = QtGui.QPixmap(ImPath) # self.ImgShowLabel.setPixmap(pix) # 画板 # self.__board = QtGui.QPixmap(r'C:\Users\49942\Pictures\Saved Pictures\t2.jpg') self.__board = QtGui.QPixmap(self.imglist[0]) self.__board = self.__board.scaled(500,500) # self.__IsEmpty = True # 默认为空画板 # self.EraserMode = False # 默认为禁用橡皮擦模式 # # self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 # self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 # # self.__painter = QPainter() # 新建绘图工具 # # self.__thickness = 5 # 默认画笔粗细为10px # self.__penColor = QColor("black") # 设置默认画笔颜色为黑色 # self.__colorList = QColor.colorNames() # 获取颜色列表 # 界面标题 self.ImNameSet = ImNameSet self.CurImId = 0 _, SelectFolderName = os.path.split(self.ImgFolder) CopyImFolderName = 'From{}CopyIm_{}-{}-{}-{}'.format(SelectFolderName, Month, Day, Hour, Minute) self.CopyImFolder = os.path.join(CurFolder, CopyImFolderName) _translate = QtCore.QCoreApplication.translate CurWinTitle = "检测工具 " + \ " " + \ SelectFolderName + '\\' + ImNameSet[0] self.setWindowTitle(_translate("MainWindow", '审查工具 '+self.imglist[0])) else: print('请重新选择文件夹') #########显示下一张图片 ######### def NextImBntClicked(self): ImFolder = self.ImgFolder # ImNameSet = self.ImNameSet CurImId = self.CurImId ImNum = len(self.imglist) if CurImId < ImNum - 1: # 不可循环看图 ImPath = os.path.join(ImFolder, self.imglist[CurImId + 1]) self.__board = QtGui.QPixmap(self.imglist[CurImId + 1]) self.__board = self.__board.scaled(500, 500) self.update() # self.ImgShowLabel.setPixmap(pix) self.CurImId = CurImId + 1 _, SelectFolderName = os.path.split(ImFolder) _translate = QtCore.QCoreApplication.translate CurWinTitle = "审查图片 " + \ " " + \ SelectFolderName + '\\' self.setWindowTitle(_translate("MainWindow", self.imglist[CurImId + 1])) #########显示前一张图片 ######### def PreImBntClicked(self): ImFolder = self.ImgFolder ImNameSet = self.ImNameSet CurImId = self.CurImId ImNum = len(self.imglist) if CurImId > 0: # 第一张图片没有前一张 ImPath = os.path.join(ImFolder, ImNameSet[CurImId - 1]) self.__board = QtGui.QPixmap(self.imglist[CurImId - 1]) self.__board = self.__board.scaled(500,500) self.update() # self.ImgShowLabel.setPixmap(pix) self.CurImId = CurImId - 1 _, SelectFolderName = os.path.split(ImFolder) _translate = QtCore.QCoreApplication.translate CurWinTitle = "看图工具1.0 " + \ " " + \ SelectFolderName + '\\' self.setWindowTitle(_translate("MainWindow", self.imglist[CurImId - 1])) if self.CurImId < 0: self.CurImId = 0 def Clear(self): # 清空画板 self.__board.fill(Qt.white) self.update() self.__IsEmpty = True def ChangePenColor(self, color="black"): # 改变画笔颜色 self.__penColor = QColor(color) def ChangePenThickness(self, thickness=10): # 改变画笔粗细 self.__thickness = thickness def IsEmpty(self): # 返回画板是否为空 return self.__IsEmpty def GetContentAsQImage(self): # 获取画板内容(返回QImage) image = self.__board.toImage() return image def paintEvent(self, paintEvent): # 绘图事件 # 绘图时必须使用QPainter的实例,此处为__painter # 绘图在begin()函数与end()函数间进行 # begin(param)的参数要指定绘图设备,即把图画在哪里 # drawPixmap用于绘制QPixmap类型的对象 self.__painter.begin(self) # 0,0为绘图的左上角起点的坐标,__board即要绘制的图 self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() def mousePressEvent(self, mouseEvent): # 鼠标按下时,获取鼠标的当前位置保存为上一次位置 self.__currentPos = mouseEvent.pos() self.__lastPos = self.__currentPos def mouseMoveEvent(self, mouseEvent): # 鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线 self.__currentPos = mouseEvent.pos() if mouseEvent.buttons() == QtCore.Qt.LeftButton: self.__painter.begin(self.__board) if self.EraserMode == False: # 非橡皮擦模式 self.__painter.setPen(QPen(self.__penColor, self.__thickness)) # 设置画笔颜色,粗细 else: # 橡皮擦模式下画笔为纯白色,粗细为10 self.__painter.setPen(QPen(Qt.white, 10)) # 画线 self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() # 更新显示 self.mouseEventpos = mouseEvent.pos() # pos = self.mapToGlobal(mouseEvent.pos()) #相對位置轉絕對 # print(pos) pos = QCursor.pos() hwnd = win32gui.WindowFromPoint((pos.x(), pos.y())) print('x,y', pos.x(), pos.y()) print(*win32gui.GetWindowRect(hwnd)) # self.frameWidget.setRect(*win32gui.GetWindowRect(hwnd)) # 截图 screen = QApplication.primaryScreen() # 获取主显示屏对象(QScreen对象) if screen is not None: image = screen.grabWindow(0, pos.x() - 60, pos.y() - 60, 120, 120) if not image.isNull(): self.EnlargeImg.setPixmap(image.scaled(240, 240)) # self.EnlargeImg.update() def mouseReleaseEvent(self, mouseEvent): self.__IsEmpty = False # 画板不再为空 # def leaveEvent(self, event): # # super(Label, self).leaveEvent(event) # # 得到鼠标在屏幕中的位置 # print('鼠标离开') # print(event) # pos = QCursor.pos() # print(pos) # hwnd = win32gui.WindowFromPoint((pos.x(), pos.y())) # print('x,y', pos.x(), pos.y()) # print(*win32gui.GetWindowRect(hwnd)) # # self.frameWidget.setRect(*win32gui.GetWindowRect(hwnd)) # # 截图 # screen = QApplication.primaryScreen() # 获取主显示屏对象(QScreen对象) # if screen is not None: # image = screen.grabWindow(0, pos.x() - 60, pos.y() - 60, 120, 120) # if not image.isNull(): # self.EnlargeImg.setPixmap(image.scaled(240, 240)) # # self.EnlargeImg.update() def on_PenColorChange(self): color_index = self.__comboBox_penColor.currentIndex() color_str = self.__colorList[color_index] self.__paintBoard.ChangePenColor(color_str) def on_PenThicknessChange(self): penThickness = self.__spinBox_penThickness.value() self.__paintBoard.ChangePenThickness(penThickness) def on_btn_Save_Clicked(self): # savePath = QFileDialog.getSaveFileName(self, 'Save Your Paint', '.\\', '*.png') # print(savePath) curImg = self.imglist[self.CurImId] ImgName = os.path.split(curImg)[-1] savePath = os.path.join(r'C:\Users\49942\Pictures', ImgName) print('保存') print(savePath) if savePath == "": print("Save cancel") return image = self.__board.toImage() image.save(savePath) def on_cbtn_Eraser_clicked(self): if self.__cbtn_Eraser.isChecked(): self.__paintBoard.EraserMode = True # 进入橡皮擦模式 else: self.__paintBoard.EraserMode = False # 退出橡皮擦模式 def Quit(self): self.close()
class MainWindow(QMainWindow, Ui_mainWidget): # 为了实现窗口的显示和业务逻辑分离,新建另一个调用窗口的文件 def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.board = QPixmap(865, 485) self.board.fill(Qt.white) self.is_empty = True # 空画板 self.last_pos = QPoint(0, 0) self.current_pos = QPoint(0, 0) self.painter = QPainter() self.painter.setRenderHint(QPainter.Antialiasing) # 反锯齿 self.clearButton.clicked.connect(self.clear) self.uploadButton.clicked.connect(self.upload) self.runButton.clicked.connect(self.run) # 在此处识别,调用算法中的识别函数 def run(self): algorithm = self.algorithmCombo.currentText() target = self.targetCombo.currentText() print(algorithm, target) # 先保存图片然后找到该图片识别 image = self.board.toImage() # 这里可以改图片存储路径 image_save_path = 'images/testImage.jpg' image.save(image_save_path) # 为了方便,识别时直接去存储路径下获取图片 img_path = image_save_path # 由于尚未尝试用除NN外的算法去同时识别数字+字母,所以当选择其他算法时需要输出提示信息 try: # 需要更名选择不同的model,可能会不存在,先load下来看是否报错 model_path = model_path_dic[algorithm][target_sub[target]] if algorithm == "SVM" or algorithm == "KNN": model = joblib.load(model_path) else: model = load_model(model_path) except: # 如果图片路径下没有相应的图片或是模型路径下没有相应的模型,报错 QMessageBox.about(self, "提示", "暂不支持") self.resultLineEdit.setText("") self.board.fill(Qt.white) else: # 运行并返回预测结果 prediction = run(img_path, model_path, algorithmName_sub[algorithm], target_sub[target]) prediction = ' '.join([str(x) for x in prediction]) print(prediction) self.resultLineEdit.setText(prediction) # 将结果存放在LineEdit中 self.board.load("result.png") self.update() def upload(self): filename = QFileDialog.getOpenFileName(None, 'open', ".") self.board.load(filename[0]) self.update() def clear(self): self.board.fill(Qt.white) self.update() self.is_empty = True self.resultLineEdit.setText("") def paintEvent(self, paintEvent): self.painter.begin(self) self.painter.drawPixmap(0, 0, self.board) self.painter.end() def mouseReleaseEvent(self, QMouseEvent): self.is_empty = False def mousePressEvent(self, QMouseEvent): self.current_pos = QMouseEvent.pos() self.last_pos = self.current_pos def mouseMoveEvent(self, QMouseEvent): self.current_pos = QMouseEvent.pos() self.painter.begin(self.board) self.painter.setPen(QPen(Qt.black, 6)) self.painter.drawLine(self.last_pos, self.current_pos) self.painter.end() self.last_pos = self.current_pos self.update()
class PaintBoard(QWidget): def __init__(self, parent=None): super().__init__(parent) self.__size = QSize(350, 350) # 新建画板,尺寸为__size self.__board = QPixmap(self.__size) self.__board.fill(Qt.white) # 用白色填充画板 self.__painter = QPainter() # 新建绘图工具 self.eraser_mode = False # 默认为禁用橡皮擦模式 self.__thickness = 6 # 默认画笔粗细为10px self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 self.__undo_num = 0 self.__redo_num = 0 self.__undo_list = [] self.__redo_list = [] self.__undo_list.append(self.__board.toImage()) # 设置界面的尺寸为__size self.setFixedSize(self.__size) def clear(self): self.__board.fill(Qt.white) # 清空画板 self.update() self.__undo_list.append(self.__board.toImage()) self.__redo_list = [] self.__undo_num += 1 self.__redo_num = 0 def up(self, image): self.__board = image # 清空画板 self.update() self.__undo_list.append(self.__board.toImage()) self.__redo_list = [] self.__undo_num += 1 self.__redo_num = 0 def undo(self): if self.__undo_num > 0: image = self.__undo_list[self.__undo_num - 1] self.__board = QPixmap.fromImage(image) self.update() self.__redo_list.append(self.__undo_list.pop()) self.__redo_num += 1 self.__undo_num -= 1 def redo(self): if self.__redo_num > 0: image = self.__redo_list[self.__redo_num - 1] self.__board = QPixmap(image) self.update() self.__undo_list.append(self.__redo_list.pop()) self.__redo_num -= 1 self.__undo_num += 1 def change_pen_thickness(self, thickness=10): # 改变画笔粗细 self.__thickness = thickness def get_content_as_image(self): # 获取画板内容(返回QImage) image = self.__board.toImage() return image def paintEvent(self, paint_event): # 绘图事件 # 绘图时必须使用QPainter的实例,此处为__painter # 绘图在begin()函数与end()函数间进行 # begin(param)的参数要指定绘图设备,即把图画在哪里 self.__painter.begin(self) # 0,0为绘图的左上角起点的坐标,__board即要绘制的图 self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() def mouse_press_event(self, mouse_event): # 鼠标按下时,获取鼠标的当前位置保存为上一次位置 # self.__currentPos = mouse_event.pos() self.__currentPos.setX(mouse_event.pos().x() - 803) self.__currentPos.setY(mouse_event.pos().y() - 147) self.__lastPos = self.__currentPos def mouse_move_event(self, mouse_event): # self.__currentPos = mouse_event.pos() # 鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线 self.__currentPos.setX(mouse_event.pos().x() - 803) self.__currentPos.setY(mouse_event.pos().y() - 147) self.__painter.begin(self.__board) if not self.eraser_mode: # 非橡皮擦模式 self.__painter.setPen(QPen(Qt.black, self.__thickness)) # 设置画笔颜色,粗细 else: # 橡皮擦模式下画笔为纯白色,粗细为10 self.__painter.setPen(QPen(Qt.white, self.__thickness)) # 画线 self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() # 更新显示 def mouse_release_event(self, mouse_event): self.__undo_list.append(self.__board.toImage()) self.__redo_list = [] self.__undo_num += 1 self.__redo_num = 0
class PaintBoard(QWidget): set_paint = pyqtSignal(bool) def __init__(self, signals: ClientSignal, Parent=None): ''' Constructor ''' super().__init__(Parent) self.Signals = signals # 是否是本玩家在画图 # 判断是否需要发送画图信息 self.Painting = False self.BoardSize = QSize(*board_resolution) # 新建QPixmap作为画板,尺寸为size self.Board = QPixmap(self.BoardSize) self.Board.fill(Qt.white) # 用白色填充画板 self.IsEmpty = True # 默认为空画板 self.EraserMode = False # 默认为禁用橡皮擦模式 self.LastPos = QPoint(0, 0) # 上一次鼠标位置 self.CurrentPos = QPoint(0, 0) # 当前的鼠标位置 self.Painter = QPainter() # 新建绘图工具 self.Thickness = default_thickness # 默认画笔粗细为10px self.PenColor = QColor(default_color) # 设置默认画笔颜色为黑色 self.ColorList = QColor.colorNames() # 获取颜色列表 self.set_paint.connect(self.set_painting) self.PaintPoints = [] self.init_view() def init_view(self): # 设置界面的尺寸为size self.setFixedSize(self.BoardSize) def set_painting(self, painting): # print('seting painting to', painting) self.Painting = painting def set_pen_thickness(self, thickness): self.Thickness = int(thickness) def set_pen_color(self, color): self.PenColor = QColor(color) def set_eraser(self, e): self.EraserMode = e if self.Painting: self.Signals.EraserChangeSignal.emit(e) # self.EraserSender.emit(e) def clear(self): if self.Painting: self.Signals.ClearSignal.emit() # self.ClearSender.emit() # 清空画板 self.Board.fill(Qt.white) self.repaint()#update() self.IsEmpty = True def change_pen_color(self, color="black"): print('color changed:', color) if self.Painting: self.Signals.ColorChangeSignal.emit(color) # self.ColorSender.emit(color) # 改变画笔颜色 self.PenColor = QColor(color) def change_pen_thickness(self, thickness=default_thickness): if self.Painting: self.Signals.ThicknessChangeSignal.emit(thickness) # self.ThicknessSender.emit(thickness) # 改变画笔粗细 self.Thickness = thickness # print('thickness:',type(self.thickness), self.thickness) # 返回画板是否为空 def is_empty(self): return self.IsEmpty def get_content_as_QImage(self): # 获取画板内容(返回QImage) image = self.Board.toImage() return image def paintEvent(self, paintEvent): # 绘图事件 # 绘图时必须使用QPainter的实例,此处为painter # 绘图在begin()函数与end()函数间进行 # begin(param)的参数要指定绘图设备,即把图画在哪里 # drawPixmap用于绘制QPixmap类型的对象 self.Painter.begin(self) # 0,0为绘图的左上角起点的坐标,board即要绘制的图 self.Painter.drawPixmap(0, 0, self.Board) self.Painter.end() def mousePressEvent(self, mouseEvent): # 鼠标按下时,获取鼠标的当前位置保存为上一次位置 self.CurrentPos = mouseEvent.pos() self.LastPos = self.CurrentPos if self.Painting: self.Signals.ClickPointSignal.emit(mouseEvent.pos()) # self.click_point_sender.emit(mouseEvent.pos()) def mouseMoveEvent(self, mouseEvent): # print('moving! painting=', self.Painting) if self.Painting: # 鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线 self.CurrentPos = mouseEvent.pos() self.paint_point() # print('painting...') self.repaint() # print('complete painting...') self.LastPos = self.CurrentPos # self.paint_points.append([self.currentPos.x(), self.currentPos.y()]) # self.paint_point_sender.emit(mouseEvent.pos()) self.Signals.PaintPointSignal.emit(mouseEvent.pos()) def mouseReleaseEvent(self, mouseEvent): self.IsEmpty = False # 画板不再为空 if self.Painting: self.Signals.ReleasePointSignal.emit() # self.release_point_sender.emit() # self.paint_points.clear() def paint_point(self): self.Painter.begin(self.Board) if not self.EraserMode: # 非橡皮擦模式 self.Painter.setPen(QPen(self.PenColor, self.Thickness)) # 设置画笔颜色,粗细 else: # 橡皮擦模式下画笔为纯白色,粗细为10 self.Painter.setPen(QPen(Qt.white, 10)) # 画线 self.Painter.drawLine(self.LastPos, self.CurrentPos) self.Painter.end() def extern_click(self, x, y): self.LastPos = QPoint(x, y) self.CurrentPos = QPoint(x, y) def extern_paint(self, ps): for x,y in ps: self.CurrentPos = QPoint(x, y) self.paint_point() self.LastPos = self.CurrentPos self.repaint() def reset_last_point(self, x, y): self.LastPos = QPoint(x, y) self.CurrentPos = QPoint(x, y)
class PaintBoard(QWidget): def __init__(self, Parent=None, fpath=None): ''' Constructor ''' super().__init__(Parent) self.pos_xy = [] #保存鼠标移动过的点 self._InitData(fpath) #先初始化数据,再初始化界面 self.__InitView() def __InitView(self): self.setFixedSize(self.__size) def _InitData(self,fpath=None): self.__size = QSize(280,280) if fpath is None: self.__board = QPixmap(self.__size) #新建QPixmap作为画板,宽350px,高250px self.__board.fill(Qt.white) #用白色填充画板 else: self.__board = QPixmap(fpath).scaled(280,280) def paintEvent(self, event): self.__painter = QPainter() self.__painter.begin(self) self.__painter.drawPixmap(0,0,self.__board) pen = QPen(Qt.black, 30, Qt.SolidLine) self.__painter.setPen(pen) if len(self.pos_xy) > 1: point_start = self.pos_xy[0] for pos_tmp in self.pos_xy: point_end = pos_tmp if point_end == (-1, -1): point_start = (-1, -1) continue if point_start == (-1, -1): point_start = point_end continue self.__painter.drawLine(point_start[0], point_start[1], point_end[0], point_end[1]) point_start = point_end self.__painter.end() def mouseMoveEvent(self, event): ''' 按住鼠标移动事件:将当前点添加到pos_xy列表中 ''' #中间变量pos_tmp提取当前点 pos_tmp = (event.pos().x(), event.pos().y()) #pos_tmp添加到self.pos_xy中 self.pos_xy.append(pos_tmp) self.update() def mouseReleaseEvent(self, event): ''' 重写鼠标按住后松开的事件 在每次松开后向pos_xy列表中添加一个断点(-1, -1) ''' pos_test = (-1, -1) self.pos_xy.append(pos_test) self.update() def Clear(self): pass
class PaintBoard(QWidget): # Define virtual panel coordinates for different shapes/regions VPCoord_Start = [316, 332] #LeftTopX, Y VPCoord_Circle = [316, 332, 336, 363] #LeftTopX, Y, RightBotX, Y VPCoord_Rect = [336, 332, 356, 363] #LeftTopX, Y, RightBotX, Y VPCoord_Tri = [316, 363, 336, 395] #LeftTopX, Y, RightBotX, Y VPCoord_Line = [336, 363, 356, 395] #LeftTopX, Y, RightBotX, Y # A flag to check if the user is currently using the virtual panel usingVP = False def __init__(self, sizeX, sizeY, Parent=None): ''' Constructor ''' super().__init__(Parent) self.__InitData(sizeX, sizeY) #Initialize Data first, then interface/view self.__InitView() print("Init PaintBoard") def __InitView(self): self.setFixedSize(self.__size) def __InitData(self, sizeX, sizeY): self.__size = QSize(sizeX, sizeY) self.__board = QPixmap( self.__size) #Make a new QPixmap as paint board,350px * 250px self.__board.fill(Qt.white) #Fill the paint board with white self.__IsEmpty = True #board is empty by default self.EraserMode = False #eraser mode is disabled by default self.__lastPos = None self.__currentPos = QPoint(0, 0) self.__painter = QPainter() self.__thickness = 1 #default pen thickness is 1 self.__penColor = QColor("black") #default color is black self.__colorList = QColor.colorNames() #get the list of colors def Clear(self): #Clear the board self.__board.fill(Qt.white) self.update() self.__IsEmpty = True def ChangePenColor(self, color="black"): self.__penColor = QColor(color) def ChangePenThickness(self, thickness=1): self.__thickness = thickness def IsEmpty(self): #Is the board empty return self.__IsEmpty def GetContentAsQImage(self): #return the content of the board (return QImage) image = self.__board.toImage() return image def paintEvent(self, paintEvent): self.__painter.begin(self) self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() # print("inside paintEvent") def penPressEvent(self, pos): self.__currentPos = QPoint(pos[0], pos[1]) self.__lastPos = self.__currentPos def penMoveEvent(self, pos, pressure): pen_x = pos[0] pen_y = pos[1] pen_pressure = pressure if self.__lastPos is None: self.__lastPos = QPoint(pen_x, pen_y) elif (abs(pen_x - self.__lastPos.x()) > 21 or abs(pen_y - self.__lastPos.y()) > 21): self.__lastPos = QPoint(pen_x, pen_y) self.__currentPos = QPoint(pen_x, pen_y) self.__painter.begin(self.__board) if self.EraserMode == False: #Non-Eraser mode self.__painter.setPen(QPen( self.__penColor, self.__thickness)) #Set pen color, thickness else: #Eraser mode: pen color is white, thickness is 6 self.__painter.setPen(QPen(Qt.white, 6)) self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() #Show updates def penVPEvent(self, pos, pressure): pass ''' # Check if the pressure is over 500 if(pen_pressure > 400): # Check which region the pen is in and prepare to draw shape accordingly if(pen_x < self.VPCoord_Circle[2] and pen_y < self.VPCoord_Circle[3]): print("A") elif(pen_x < self.VPCoord_Rect[2] and pen_y < self.VPCoord_Rect[3]): print("B") elif(pen_x < self.VPCoord_Tri[2] and pen_y < self.VPCoord_Tri[3]): print("C") elif(pen_x < self.VPCoord_Line[2] and pen_y < self.VPCoord_Line[3]): print("D") ''' def penReleaseEvent(self, pos): self.__IsEmpty = False #board is not empty def paintEllipse(self, center_x, center_y, radias1, radias2): self.__painter.begin(self.__board) self.__painter.setPen(QPen(self.__penColor, self.__thickness)) self.__painter.drawEllipse(QPoint(center_x, center_y), radias1, radias2) self.__painter.end() self.update() #Show updates def paintRect(self, center_x, center_y, upper_left_x, upper_left_y): width = abs(2 * (center_x - upper_left_x)) height = abs(2 * (center_y - upper_left_y)) self.__painter.begin(self.__board) self.__painter.setPen(QPen(self.__penColor, self.__thickness)) self.__painter.drawRect(upper_left_x, upper_left_y, width, height) self.__painter.end() self.update() #Show updates def paintTriangle(self, points): self.__painter.begin(self.__board) self.__painter.setPen(QPen(self.__penColor, self.__thickness)) self.__painter.drawPolygon(points) self.__painter.end() self.update() #Show updates def paintLine(self, P1_x, P1_y, P2_x, P2_y): P1 = QPoint(P1_x, P1_y) P2 = QPoint(P2_x, P2_y) self.__painter.begin(self.__board) self.__painter.drawLine(P1, P2) self.__painter.end() self.update() #Show updates
class PaintBoard(QWidget): def __init__(self, Parent=None): ''' Constructor ''' super().__init__(Parent) self.__InitData() # 先初始化数据,再初始化界面 self.__InitView() def __InitData(self): self.__size = QSize(480, 460) # 新建QPixmap作为画板,尺寸为__size self.__board = QPixmap(self.__size) self.__board.fill(Qt.white) # 用白色填充画板 self.__IsEmpty = True # 默认为空画板 self.EraserMode = False # 默认为禁用橡皮擦模式 self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 self.__painter = QPainter() # 新建绘图工具 self.__thickness = 10 # 默认画笔粗细为10px self.__penColor = QColor("black") # 设置默认画笔颜色为黑色 self.__colorList = QColor.colorNames() # 获取颜色列表 def __InitView(self): # 设置界面的尺寸为__size self.setFixedSize(self.__size) def Clear(self): # 清空画板 self.__board.fill(Qt.white) self.update() self.__IsEmpty = True def ChangePenColor(self, color="black"): # 改变画笔颜色 self.__penColor = QColor(color) def ChangePenThickness(self, thickness=10): # 改变画笔粗细 self.__thickness = thickness def IsEmpty(self): # 返回画板是否为空 return self.__IsEmpty def GetContentAsQImage(self): # 获取画板内容(返回QImage) image = self.__board.toImage() return image def paintEvent(self, paintEvent): # 绘图事件 # 绘图时必须使用QPainter的实例,此处为__painter # 绘图在begin()函数与end()函数间进行 # begin(param)的参数要指定绘图设备,即把图画在哪里 # drawPixmap用于绘制QPixmap类型的对象 self.__painter.begin(self) # 0,0为绘图的左上角起点的坐标,__board即要绘制的图 self.__painter.drawPixmap(0, 0, self.__board) self.__painter.end() def mousePressEvent(self, mouseEvent): # 鼠标按下时,获取鼠标的当前位置保存为上一次位置 self.__currentPos = mouseEvent.pos() self.__lastPos = self.__currentPos def mouseMoveEvent(self, mouseEvent): # 鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线 self.__currentPos = mouseEvent.pos() self.__painter.begin(self.__board) if self.EraserMode == False: # 非橡皮擦模式 self.__painter.setPen(QPen(self.__penColor, self.__thickness)) # 设置画笔颜色,粗细 else: # 橡皮擦模式下画笔为纯白色,粗细为10 self.__painter.setPen(QPen(Qt.white, 10)) # 画线 self.__painter.drawLine(self.__lastPos, self.__currentPos) self.__painter.end() self.__lastPos = self.__currentPos self.update() # 更新显示 def mouseReleaseEvent(self, mouseEvent): self.__IsEmpty = False # 画板不再为空
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()