def drawSizeInfo(self): sizeInfoAreaWidth = 200 sizeInfoAreaHeight = 30 spacing = 5 rect = self.selected_area.normalized() sizeInfoArea = QRect(rect.left(), rect.top() - spacing - sizeInfoAreaHeight, sizeInfoAreaWidth, sizeInfoAreaHeight) if sizeInfoArea.top() < 0: sizeInfoArea.moveTopLeft(rect.topLeft() + QPoint(spacing, spacing)) if sizeInfoArea.right() >= self.screenPixel.width(): sizeInfoArea.moveTopLeft(rect.topLeft() - QPoint(spacing, spacing) - QPoint(sizeInfoAreaWidth, 0)) if sizeInfoArea.left() < spacing: sizeInfoArea.moveLeft(spacing) if sizeInfoArea.top() < spacing: sizeInfoArea.moveTop(spacing) self.items_to_remove.append( self.graphics_scene.addRect(QRectF(sizeInfoArea), QPen(Qt.white), QBrush(Qt.black))) sizeInfo = self.graphics_scene.addSimpleText(' {0} x {1}'.format( rect.width() * self.scale, rect.height() * self.scale)) sizeInfo.setPos(sizeInfoArea.topLeft() + QPoint(0, 2)) sizeInfo.setPen(QPen(QColor(255, 255, 255), 2)) self.items_to_remove.append(sizeInfo)
class Overlay(): def __init__(self, topleft=None, pixmap=None): self.pixmap = pixmap if topleft and pixmap: self.rect = QRect(self.topleft.x(), self.topleft.y(), pixmap.width(), pixmap.height()) else: self.rect = None self.blend_with_next = False def __repr__(self): return f'<Overlay {self.rect}>' def paint(self, painter): if self.rect: painter.drawPixmap(self.rect.topLeft(), self.pixmap) def reserve(self, rect): if self.rect: new_rect = self.rect.united(rect) else: new_rect = rect new_pixmap = QPixmap(new_rect.width(), new_rect.height()) new_pixmap.fill(QColor(0, 0, 0, 0)) if self.pixmap: painter = QPainter(new_pixmap) painter.drawPixmap(self.rect.left() - new_rect.left(), self.rect.top() - new_rect.top(), self.pixmap) painter.end() self.pixmap = new_pixmap self.rect = new_rect def add(self, other_overlay): if self.rect: self.reserve(other_overlay.rect) painter = QPainter(self.pixmap) painter.drawPixmap(other_overlay.rect.left() - self.rect.left(), other_overlay.rect.top() - self.rect.top(), other_overlay.pixmap) painter.end() else: self.pixmap = other_overlay.pixmap.copy() self.rect = other_overlay.rect @contextlib.contextmanager def painter_context(self): if self.pixmap: painter = QPainter(self.pixmap) painter.translate(-self.rect.topLeft()) try: yield painter finally: painter.end() else: yield None
def draw_rect_image(self, rect: QRect): paint = QPainter(self) paint.setPen(QPen(Qt.red, 3, Qt.SolidLine)) # 画边框 paint.drawRect(rect) draw_circle(5, rect.top(), rect.left(), QColor(Qt.white), QColor(Qt.red), self) draw_circle(5, rect.top(), rect.right(), QColor(Qt.white), QColor(Qt.red), self) draw_circle(5, rect.bottom(), rect.left(), QColor(Qt.white), QColor(Qt.red), self) draw_circle(5, rect.bottom(), rect.right(), QColor(Qt.white), QColor(Qt.red), self)
def restoreGeometry(self, geometry): """ Restores the geometry of this subwindow :param geometry: the saved state as a QByteArray instance :return: """ if geometry.size() < 4: return False stream = QDataStream(geometry) if stream.readUInt32() != 0x1D9D0CB: return False if stream.readUInt16() != 1: return False stream.readUInt16() # minorVersion is ignored. x = stream.readInt64() y = stream.readInt64() width = stream.readInt64() height = stream.readInt64() restoredFrameGeometry = QRect(x, y, width, height) x = stream.readInt64() y = stream.readInt64() width = stream.readInt64() height = stream.readInt64() restoredNormalGeometry = QRect(x, y, width, height) maximized = stream.readUInt32() fullScreen = stream.readUInt32() frameHeight = 20 if not restoredFrameGeometry.isValid(): restoredFrameGeometry = QRect(QPoint(0, 0), self.sizeHint()) if not restoredNormalGeometry.isValid(): restoredNormalGeometry = QRect(QPoint(0, frameHeight), self.sizeHint()) restoredFrameGeometry.moveTop(max(restoredFrameGeometry.top(), 0)) restoredNormalGeometry.moveTop( max(restoredNormalGeometry.top(), 0 + frameHeight)) if maximized or fullScreen: self.setGeometry(restoredNormalGeometry) ws = self.windowState() if maximized: ws |= Qt.WindowMaximized if fullScreen: ws |= Qt.WindowFullScreen self.setWindowState(ws) else: offset = QPoint() self.setWindowState(self.windowState() & ~(Qt.WindowMaximized | Qt.WindowFullScreen)) self.move(restoredFrameGeometry.topLeft() + offset) self.resize(restoredNormalGeometry.size()) return True
def array2DSlices(a2D, rect): """ Return the 2-uple of slice objects convenient to index the intersection of the 2 dimensional array a2D with rect. @param a2D: @type a2D: ndarray, ndims >=2 @param rect: (x, y, w, h) @type rect: 4-uple of int or QRect object @return: @rtype: 2-uple of slice objects """ # convert rect to a QRect object if type(rect) not in [QRect]: try: rect = QRect(*rect) except (TypeError, ValueError): rect = QRect() # intersect a2D with rect qrect = QRect(0, 0, a2D.shape[1], a2D.shape[0]) & rect if qrect.isValid(): return slice(qrect.top(), qrect.bottom()), slice(qrect.left(), qrect.right()) else: return slice(0, 0), slice(0, 0)
def saveScreenshot(self, clipboard=False, fileName='screenshot.png', picType='png'): fullWindow = QRect(0, 0, self.width() - 1, self.height() - 1) selected = QRect(self.selected_area) if selected.left() < 0: selected.setLeft(0) if selected.right() >= self.width(): selected.setRight(self.width() - 1) if selected.top() < 0: selected.setTop(0) if selected.bottom() >= self.height(): selected.setBottom(self.height() - 1) source = (fullWindow & selected) source.setTopLeft( QPoint(source.topLeft().x() * self.scale, source.topLeft().y() * self.scale)) source.setBottomRight( QPoint(source.bottomRight().x() * self.scale, source.bottomRight().y() * self.scale)) image = self.screenPixel.copy(source) if clipboard: QGuiApplication.clipboard().setImage(image.toImage(), QClipboard.Clipboard) else: image.save(fileName, picType, 10) self.target_img = image self.target_img_pos = source self.screen_shot_grabed.emit(image.toImage()) self.screen_shot_pos_grabed.emit(source)
def _rect_to_area(self, rect: QRect): return { "x": rect.left(), "y": rect.top(), "width": rect.width(), "height": rect.height() }
def nearestPosOnRect(pos: QtCore.QPoint, rect: QtCore.QRect): """ Finds the position on a rectangle nearest to the given point. """ # Bounds: xmax, ymax, xmin, ymin bounds = (rect.right(), rect.bottom(), rect.left(), rect.top()) # Line origin point c = rect.center() # Clipped line: returns (x1, y1, x2, y2) clipped = cohenSutherlandClip(c.x(), c.y(), pos.x(), pos.y(), *bounds) # "clipped" should only be None if both points lie outside the # bounding area. This should never happen, since one point # is always the center of the area. assert clipped is not None # The nearest position to the given point, on the rectangle, is # the second point returned by the clipping function. _, _, x2, y2 = clipped return QtCore.QPoint(x2, y2)
class SlippyMap(QObject): updated = Signal(QRect) def __init__(self, parent=None): """ :param parent: """ super(SlippyMap, self).__init__(parent) self._offset = QPoint() self._tiles_rectangle = QRect() self._tile_pixmaps = {} # Point(x, y) to QPixmap mapping self._manager = QNetworkAccessManager() self._url = QUrl() # public vars self.width = 400 self.height = 300 self.zoom = 4 self.latitude = 59.9138204 self.longitude = 10.7387413 self._emptyTile = QPixmap(TDIM, TDIM) self._emptyTile.fill(Qt.lightGray) self.request = QNetworkRequest() self.cache = QNetworkDiskCache() self.cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation)) self._manager.setCache(self.cache) self._manager.finished.connect(self.handle_network_data) def invalidate(self): """ :return: """ if self.width <= 0 or self.height <= 0: return ct = tile_for_coordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM) yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM) # first tile vertical and horizontal xa = (xp + TDIM - 1) / TDIM ya = (yp + TDIM - 1) / TDIM xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self._offset = QPoint(int(xp - xa * TDIM), int(yp - ya * TDIM)) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / TDIM ye = int(ty) + (self.height - yp - 1) / TDIM # build a rect self._tiles_rectangle = QRect(int(xs), int(ys), int(xe - xs + 1), int(ye - ys + 1)) if self._url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, p: QPainter, rect: QRect): """ Render a tile :param p: QPainter instance, place where to pain the tiles :param rect: QRect instance, dimensions of the painter (the window that renders the tiles) :return: Nothing """ rx = range(self._tiles_rectangle.width()) ry = range(self._tiles_rectangle.height()) for x, y in product(rx, ry): tp = Point(x + self._tiles_rectangle.left(), y + self._tiles_rectangle.top()) box = self.tile_rectangle(tp) if rect.intersects(box): p.drawPixmap(box, self._tile_pixmaps.get(tp, self._emptyTile)) def pan(self, delta: QPoint): """ Move the map :param delta: x, y delta as a QPoint instance :return: Nothing """ dx = QPointF(delta) / float(TDIM) center = tile_for_coordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitude_from_tile(center.y(), self.zoom) self.longitude = longitude_from_tile(center.x(), self.zoom) self.invalidate() # slots def handle_network_data(self, reply: QNetworkReply): """ This function is called automatically by a QNetworkAccessManager object (self._manager) :param reply: QNetworkReply instance :return: Nothing """ img = QImage() tp = Point(reply.request().attribute(QNetworkRequest.User)) url = reply.url() if not reply.error(): # if there was no url error... if img.load(reply, None): # if the image loading went well... self._tile_pixmaps[tp] = QPixmap.fromImage( img) # store the image in the tiles dictionary reply.deleteLater() self.updated.emit(self.tile_rectangle(tp)) # purge unused tiles bound = self._tiles_rectangle.adjusted(-2, -2, 2, 2) for tp in list(self._tile_pixmaps.keys()): if not bound.contains(tp): del self._tile_pixmaps[tp] self.download() def download(self): """ Download tile :return: Nothing """ grab = None rx = range(self._tiles_rectangle.width()) ry = range(self._tiles_rectangle.height()) for x, y in product(rx, ry): tp = Point(self._tiles_rectangle.topLeft() + QPoint(x, y)) if tp not in self._tile_pixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % ( self.zoom, grab.x(), grab.y()) self._url = QUrl(path) self.request = QNetworkRequest() self.request.setUrl(self._url) self.request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') self.request.setAttribute(QNetworkRequest.User, grab) self._manager.get(self.request) print('downloading z:', self.zoom, 'x:', grab.x(), 'y:', grab.y()) def tile_rectangle(self, tp: Point): """ Get tile rectangle :param tp: Tile point :return: QRect instance """ t = tp - self._tiles_rectangle.topLeft() x = t.x() * TDIM + self._offset.x() y = t.y() * TDIM + self._offset.y() return QRect(x, y, TDIM, TDIM)
class SlippyMap(QObject): updated = Signal(QRect) def __init__(self, parent=None): super(SlippyMap, self).__init__(parent) self._offset = QPoint() self._tilesRect = QRect() self._tilePixmaps = {} # Point(x, y) to QPixmap mapping self._manager = QNetworkAccessManager() self._url = QUrl() # public vars self.width = 400 self.height = 300 self.zoom = 15 self.latitude = 59.9138204 self.longitude = 10.7387413 self._emptyTile = QPixmap(TDIM, TDIM) self._emptyTile.fill(Qt.lightGray) self.request = QNetworkRequest() self.cache = QNetworkDiskCache() self.cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation)) self._manager.setCache(self.cache) self._manager.finished.connect(self.handleNetworkData) def invalidate(self): if self.width <= 0 or self.height <= 0: return ct = tileForCoordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM) yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM) # first tile vertical and horizontal xa = (xp + TDIM - 1) / TDIM ya = (yp + TDIM - 1) / TDIM xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self._offset = QPoint(xp - xa * TDIM, yp - ya * TDIM) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / TDIM ye = int(ty) + (self.height - yp - 1) / TDIM # build a rect self._tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1) if self._url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, p, rect): for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(x + self._tilesRect.left(), y + self._tilesRect.top()) box = self.tileRect(tp) if rect.intersects(box): p.drawPixmap(box, self._tilePixmaps.get(tp, self._emptyTile)) def pan(self, delta): dx = QPointF(delta) / float(TDIM) center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitudeFromTile(center.y(), self.zoom) self.longitude = longitudeFromTile(center.x(), self.zoom) self.invalidate() # slots def handleNetworkData(self, reply): img = QImage() tp = Point(reply.request().attribute(QNetworkRequest.User)) url = reply.url() if not reply.error(): if img.load(reply, None): self._tilePixmaps[tp] = QPixmap.fromImage(img) reply.deleteLater() self.updated.emit(self.tileRect(tp)) # purge unused tiles bound = self._tilesRect.adjusted(-2, -2, 2, 2) for tp in list(self._tilePixmaps.keys()): if not bound.contains(tp): del self._tilePixmaps[tp] self.download() def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % ( self.zoom, grab.x(), grab.y()) self._url = QUrl(path) self.request = QNetworkRequest() self.request.setUrl(self._url) self.request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') self.request.setAttribute(QNetworkRequest.User, grab) self._manager.get(self.request) def tileRect(self, tp): t = tp - self._tilesRect.topLeft() x = t.x() * TDIM + self._offset.x() y = t.y() * TDIM + self._offset.y() return QRect(x, y, TDIM, TDIM)
def paint(self, painter, option, index): rect = option.rect playerObject = index.data(Qt.UserRole) if option.state & QStyle.State_Selected: painter.setBrush(self.selectedColor) else: painter.setBrush(self.bgColor) # Background painter.setPen(Qt.NoPen) painter.drawRect(rect) # avatar pixmap = QPixmap(playerObject.avatar).scaledToHeight( 128, Qt.SmoothTransformation) pixmapRect = QRect(rect.x() + 10, rect.y() + 8, pixmap.width(), pixmap.height()) painter.drawPixmap(pixmapRect, pixmap) # Player name painter.setFont(self.fontPlayerName) painter.setPen(self.name) nameRect = QRect(rect.x() + 110, pixmapRect.top(), 100, 40) painter.drawText(nameRect, Qt.AlignLeft | Qt.AlignVCenter, playerObject.name) # Draw ingame stats if players in game if playerObject.inGame == 1: # Player Level: painter.setFont(self.fontPlayerTotal) painter.setPen(self.name) levelRect = QRect(nameRect.right() + 70, pixmapRect.top(), 100, 40) painter.drawText(levelRect, Qt.AlignHCenter | Qt.AlignVCenter, "Level") painter.setFont(self.fontPlayerTotalValue) levelValRect = QRect(levelRect.left(), levelRect.bottom() + 20, 100, 55) painter.drawText(levelValRect, Qt.AlignHCenter | Qt.AlignVCenter, str(playerObject.currentLevel)) # Player Bonus: painter.setFont(self.fontPlayerTotal) painter.setPen(self.name) bonusRect = QRect(levelRect.right() + 50, pixmapRect.top(), 100, 40) painter.drawText(bonusRect, Qt.AlignHCenter | Qt.AlignVCenter, "Bonus") painter.setFont(self.fontPlayerTotalValue) bonusValRect = QRect(levelRect.right() + 50, levelRect.bottom() + 20, 100, 55) painter.drawText(bonusValRect, Qt.AlignHCenter | Qt.AlignVCenter, str(playerObject.currentBonus)) # Player Total: painter.setFont(self.fontPlayerTotal) painter.setPen(self.name) totalRect = QRect(bonusRect.right() + 50, pixmapRect.top(), 100, 40) painter.drawText(totalRect, Qt.AlignHCenter | Qt.AlignVCenter, "Total") painter.setFont(self.fontPlayerTotalValue) totalValRect = QRect(bonusRect.right() + 50, bonusRect.bottom() + 20, 100, 55) painter.drawText( totalValRect, Qt.AlignHCenter | Qt.AlignVCenter, str(playerObject.currentLevel + playerObject.currentBonus)) # Player bonus painter.setFont(self.fontPlayerLevel) bonusRect = QRect(nameRect.x(), pixmapRect.top() + 40, 80, 20) painter.drawText(bonusRect, Qt.AlignLeft | Qt.AlignVCenter, "Gender:") bonusValRect = QRect(bonusRect.right() + 5, pixmapRect.top() + 40, 120, 20) painter.drawText(bonusValRect, Qt.AlignLeft | Qt.AlignVCenter, str(playerObject.gender)) # Player played games painter.setFont(self.fontPlayerLevel) roundsRect = QRect(nameRect.x(), bonusRect.bottom(), 80, 20) painter.drawText(roundsRect, Qt.AlignLeft | Qt.AlignVCenter, "Games:") roundsValRect = QRect(nameRect.left(), bonusRect.bottom(), 120, 20) painter.drawText(roundsValRect, Qt.AlignRight | Qt.AlignVCenter, str(playerObject.games)) # Player wins painter.setFont(self.fontPlayerLevel) winsRect = QRect(nameRect.x(), roundsRect.bottom(), 80, 20) painter.drawText(winsRect, Qt.AlignLeft | Qt.AlignVCenter, "Wins:") winsValRect = QRect(nameRect.left(), roundsRect.bottom(), 120, 20) painter.drawText(winsValRect, Qt.AlignRight | Qt.AlignVCenter, str(playerObject.wins)) # Player played Rounds painter.setFont(self.fontPlayerLevel) roundsRect = QRect(nameRect.x(), winsRect.bottom(), 80, 20) painter.drawText(roundsRect, Qt.AlignLeft | Qt.AlignVCenter, "Rounds:") roundsValRect = QRect(nameRect.left(), winsRect.bottom(), 120, 20) painter.drawText(roundsValRect, Qt.AlignRight | Qt.AlignVCenter, str(playerObject.rounds))
class Screenshot(QGraphicsView): """ Main Class """ screen_shot_grabed = Signal(QImage) screen_shot_pos_grabed = Signal(QRect) widget_closed = Signal() def __init__(self, flags=constant.DEFAULT, parent=None): """ flags: binary flags. see the flags in the constant.py """ super().__init__(parent) # Init self.penColorNow = QColor(PENCOLOR) self.penSizeNow = PENSIZE self.fontNow = QFont('Sans') self.clipboard = QApplication.clipboard() self.drawListResult = [ ] # draw list that sure to be drew, [action, coord] self.drawListProcess = None # the process to the result self.selected_area = QRect( ) # a QRect instance which stands for the selected area self.selectedAreaRaw = QRect() self.mousePosition = MousePosition.OUTSIDE_AREA # mouse position self.screenPixel = None self.textRect = None self.mousePressed = False self.action = ACTION_SELECT self.mousePoint = self.cursor().pos() self.startX, self.startY = 0, 0 # the point where you start self.endX, self.endY = 0, 0 # the point where you end self.pointPath = QPainterPath( ) # the point mouse passes, used by draw free line self.items_to_remove = [ ] # the items that should not draw on screenshot picture self.textPosition = None # result self.target_img = None self.target_img_pos = None # Init window self.getscreenshot() self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) self.setMouseTracking(True) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("QGraphicsView { border-style: none; }") self.tooBar = MyToolBar(flags, self) self.tooBar.trigger.connect(self.changeAction) self.penSetBar = None if flags & constant.RECT or flags & constant.ELLIPSE or flags & constant.LINE or flags & constant.FREEPEN \ or flags & constant.ARROW or flags & constant.TEXT: self.penSetBar = PenSetWidget(self) self.penSetBar.penSizeTrigger.connect(self.changePenSize) self.penSetBar.penColorTrigger.connect(self.changePenColor) self.penSetBar.fontChangeTrigger.connect(self.changeFont) self.textInput = TextInput(self) self.textInput.inputChanged.connect(self.textChange) self.textInput.cancelPressed.connect(self.cancelInput) self.textInput.okPressed.connect(self.okInput) self.graphics_scene = QGraphicsScene(0, 0, self.screenPixel.width(), self.screenPixel.height()) self.show() self.setScene(self.graphics_scene) self.windowHandle().setScreen(QGuiApplication.screenAt(QCursor.pos())) self.scale = self.get_scale() # self.setFixedSize(self.screenPixel.width(), self.screenPixel.height()) self.setGeometry(QGuiApplication.screenAt(QCursor.pos()).geometry()) self.showFullScreen() self.redraw() QShortcut(QKeySequence('ctrl+s'), self).activated.connect(self.saveScreenshot) QShortcut(QKeySequence('esc'), self).activated.connect(self.close) @staticmethod def take_screenshot(flags): loop = QEventLoop() screen_shot = Screenshot(flags) screen_shot.show() screen_shot.widget_closed.connect(loop.quit) loop.exec_() img = screen_shot.target_img return img @staticmethod def take_screenshot_pos(flags): loop = QEventLoop() screen_shot = Screenshot(flags) screen_shot.show() screen_shot.widget_closed.connect(loop.quit) loop.exec_() pos = screen_shot.target_img_pos return pos def getscreenshot(self): screen = QGuiApplication.screenAt(QCursor.pos()) self.screenPixel = screen.grabWindow(0) def mousePressEvent(self, event): """ :type event: QMouseEvent :param event: :return: """ if event.button() != Qt.LeftButton: return if self.action is None: self.action = ACTION_SELECT self.startX, self.startY = event.x(), event.y() if self.action == ACTION_SELECT: if self.mousePosition == MousePosition.OUTSIDE_AREA: self.mousePressed = True self.selected_area = QRect() self.selected_area.setTopLeft(QPoint(event.x(), event.y())) self.selected_area.setBottomRight(QPoint(event.x(), event.y())) self.redraw() elif self.mousePosition == MousePosition.INSIDE_AREA: self.mousePressed = True else: pass elif self.action == ACTION_MOVE_SELECTED: if self.mousePosition == MousePosition.OUTSIDE_AREA: self.action = ACTION_SELECT self.selected_area = QRect() self.selected_area.setTopLeft(QPoint(event.x(), event.y())) self.selected_area.setBottomRight(QPoint(event.x(), event.y())) self.redraw() self.mousePressed = True elif self.action in DRAW_ACTION: self.mousePressed = True if self.action == ACTION_FREEPEN: self.pointPath = QPainterPath() self.pointPath.moveTo(QPoint(event.x(), event.y())) elif self.action == ACTION_TEXT: if self.textPosition is None: self.textPosition = QPoint(event.x(), event.y()) self.textRect = None self.redraw() def mouseMoveEvent(self, event: QMouseEvent): """ :type event: QMouseEvent :param event: :return: """ self.mousePoint = QPoint(event.globalPos().x(), event.globalPos().y()) if self.action is None: self.action = ACTION_SELECT if not self.mousePressed: point = QPoint(event.x(), event.y()) self.detect_mouse_position(point) self.setCursorStyle() self.redraw() else: self.endX, self.endY = event.x(), event.y() # if self.mousePosition != OUTSIDE_AREA: # self.action = ACTION_MOVE_SELECTED if self.action == ACTION_SELECT: self.selected_area.setBottomRight(QPoint(event.x(), event.y())) self.redraw() elif self.action == ACTION_MOVE_SELECTED: self.selected_area = QRect(self.selectedAreaRaw) if self.mousePosition == MousePosition.INSIDE_AREA: move_to_x = event.x( ) - self.startX + self.selected_area.left() move_to_y = event.y( ) - self.startY + self.selected_area.top() if 0 <= move_to_x <= self.screenPixel.width( ) - 1 - self.selected_area.width(): self.selected_area.moveLeft(move_to_x) if 0 <= move_to_y <= self.screenPixel.height( ) - 1 - self.selected_area.height(): self.selected_area.moveTop(move_to_y) self.selected_area = self.selected_area.normalized() self.selectedAreaRaw = QRect(self.selected_area) self.startX, self.startY = event.x(), event.y() self.redraw() elif self.mousePosition == MousePosition.ON_THE_LEFT_SIDE: move_to_x = event.x( ) - self.startX + self.selected_area.left() if move_to_x <= self.selected_area.right(): self.selected_area.setLeft(move_to_x) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_RIGHT_SIDE: move_to_x = event.x( ) - self.startX + self.selected_area.right() self.selected_area.setRight(move_to_x) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_UP_SIDE: move_to_y = event.y( ) - self.startY + self.selected_area.top() self.selected_area.setTop(move_to_y) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_DOWN_SIDE: move_to_y = event.y( ) - self.startY + self.selected_area.bottom() self.selected_area.setBottom(move_to_y) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_TOP_LEFT_CORNER: move_to_x = event.x( ) - self.startX + self.selected_area.left() move_to_y = event.y( ) - self.startY + self.selected_area.top() self.selected_area.setTopLeft(QPoint(move_to_x, move_to_y)) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_BOTTOM_RIGHT_CORNER: move_to_x = event.x( ) - self.startX + self.selected_area.right() move_to_y = event.y( ) - self.startY + self.selected_area.bottom() self.selected_area.setBottomRight( QPoint(move_to_x, move_to_y)) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_TOP_RIGHT_CORNER: move_to_x = event.x( ) - self.startX + self.selected_area.right() move_to_y = event.y( ) - self.startY + self.selected_area.top() self.selected_area.setTopRight(QPoint( move_to_x, move_to_y)) self.selected_area = self.selected_area.normalized() self.redraw() elif self.mousePosition == MousePosition.ON_THE_BOTTOM_LEFT_CORNER: move_to_x = event.x( ) - self.startX + self.selected_area.left() move_to_y = event.y( ) - self.startY + self.selected_area.bottom() self.selected_area.setBottomLeft( QPoint(move_to_x, move_to_y)) self.redraw() else: pass elif self.action == ACTION_RECT: self.drawRect(self.startX, self.startY, event.x(), event.y(), False) self.redraw() pass elif self.action == ACTION_ELLIPSE: self.drawEllipse(self.startX, self.startY, event.x(), event.y(), False) self.redraw() elif self.action == ACTION_ARROW: self.drawArrow(self.startX, self.startY, event.x(), event.y(), False) self.redraw() elif self.action == ACTION_LINE: self.drawLine(self.startX, self.startY, event.x(), event.y(), False) self.redraw() elif self.action == ACTION_FREEPEN: y1, y2 = event.x(), event.y() rect = self.selected_area.normalized() if y1 <= rect.left(): y1 = rect.left() elif y1 >= rect.right(): y1 = rect.right() if y2 <= rect.top(): y2 = rect.top() elif y2 >= rect.bottom(): y2 = rect.bottom() self.pointPath.lineTo(y1, y2) self.drawFreeLine(self.pointPath, False) self.redraw() def mouseReleaseEvent(self, event): """ :type event: QMouseEvent :param event: :return: """ if event.button() != Qt.LeftButton: return if self.mousePressed: self.mousePressed = False self.endX, self.endY = event.x(), event.y() if self.action == ACTION_SELECT: self.selected_area.setBottomRight(QPoint(event.x(), event.y())) self.selectedAreaRaw = QRect(self.selected_area) self.action = ACTION_MOVE_SELECTED self.redraw() elif self.action == ACTION_MOVE_SELECTED: self.selectedAreaRaw = QRect(self.selected_area) self.redraw() # self.action = None elif self.action == ACTION_RECT: self.drawRect(self.startX, self.startY, event.x(), event.y(), True) self.redraw() elif self.action == ACTION_ELLIPSE: self.drawEllipse(self.startX, self.startY, event.x(), event.y(), True) self.redraw() elif self.action == ACTION_ARROW: self.drawArrow(self.startX, self.startY, event.x(), event.y(), True) self.redraw() elif self.action == ACTION_LINE: self.drawLine(self.startX, self.startY, event.x(), event.y(), True) self.redraw() elif self.action == ACTION_FREEPEN: self.drawFreeLine(self.pointPath, True) self.redraw() def detect_mouse_position(self, point): """ :type point: QPoint :param point: the mouse position you want to check :return: """ if self.selected_area == QRect(): self.mousePosition = MousePosition.OUTSIDE_AREA return if self.selected_area.left() - ERRORRANGE <= point.x( ) <= self.selected_area.left() and ( self.selected_area.top() - ERRORRANGE <= point.y() <= self.selected_area.top()): self.mousePosition = MousePosition.ON_THE_TOP_LEFT_CORNER elif self.selected_area.right() <= point.x( ) <= self.selected_area.right() + ERRORRANGE and ( self.selected_area.top() - ERRORRANGE <= point.y() <= self.selected_area.top()): self.mousePosition = MousePosition.ON_THE_TOP_RIGHT_CORNER elif self.selected_area.left() - ERRORRANGE <= point.x( ) <= self.selected_area.left() and ( self.selected_area.bottom() <= point.y() <= self.selected_area.bottom() + ERRORRANGE): self.mousePosition = MousePosition.ON_THE_BOTTOM_LEFT_CORNER elif self.selected_area.right() <= point.x( ) <= self.selected_area.right() + ERRORRANGE and ( self.selected_area.bottom() <= point.y() <= self.selected_area.bottom() + ERRORRANGE): self.mousePosition = MousePosition.ON_THE_BOTTOM_RIGHT_CORNER elif -ERRORRANGE <= point.x() - self.selected_area.left() <= 0 and ( self.selected_area.topLeft().y() < point.y() < self.selected_area.bottomLeft().y()): self.mousePosition = MousePosition.ON_THE_LEFT_SIDE elif 0 <= point.x() - self.selected_area.right() <= ERRORRANGE and ( self.selected_area.topRight().y() < point.y() < self.selected_area.bottomRight().y()): self.mousePosition = MousePosition.ON_THE_RIGHT_SIDE elif -ERRORRANGE <= point.y() - self.selected_area.top() <= 0 and ( self.selected_area.topLeft().x() < point.x() < self.selected_area.topRight().x()): self.mousePosition = MousePosition.ON_THE_UP_SIDE elif 0 <= point.y() - self.selected_area.bottom() <= ERRORRANGE and ( self.selected_area.bottomLeft().x() < point.x() < self.selected_area.bottomRight().x()): self.mousePosition = MousePosition.ON_THE_DOWN_SIDE elif not self.selected_area.contains(point): self.mousePosition = MousePosition.OUTSIDE_AREA else: self.mousePosition = MousePosition.INSIDE_AREA def setCursorStyle(self): if self.action in DRAW_ACTION: self.setCursor(Qt.CrossCursor) return if self.mousePosition == MousePosition.ON_THE_LEFT_SIDE or \ self.mousePosition == MousePosition.ON_THE_RIGHT_SIDE: self.setCursor(Qt.SizeHorCursor) elif self.mousePosition == MousePosition.ON_THE_UP_SIDE or \ self.mousePosition == MousePosition.ON_THE_DOWN_SIDE: self.setCursor(Qt.SizeVerCursor) elif self.mousePosition == MousePosition.ON_THE_TOP_LEFT_CORNER or \ self.mousePosition == MousePosition.ON_THE_BOTTOM_RIGHT_CORNER: self.setCursor(Qt.SizeFDiagCursor) elif self.mousePosition == MousePosition.ON_THE_TOP_RIGHT_CORNER or \ self.mousePosition == MousePosition.ON_THE_BOTTOM_LEFT_CORNER: self.setCursor(Qt.SizeBDiagCursor) elif self.mousePosition == MousePosition.OUTSIDE_AREA: self.setCursor(Qt.ArrowCursor) elif self.mousePosition == MousePosition.INSIDE_AREA: self.setCursor(Qt.OpenHandCursor) else: self.setCursor(Qt.ArrowCursor) pass def drawMagnifier(self): # First, calculate the magnifier position due to the mouse position watch_area_width = 16 watch_area_height = 16 cursor_pos = self.mousePoint watch_area = QRect( QPoint(cursor_pos.x() - watch_area_width / 2, cursor_pos.y() - watch_area_height / 2), QPoint(cursor_pos.x() + watch_area_width / 2, cursor_pos.y() + watch_area_height / 2)) if watch_area.left() < 0: watch_area.moveLeft(0) watch_area.moveRight(watch_area_width) if self.mousePoint.x( ) + watch_area_width / 2 >= self.screenPixel.width(): watch_area.moveRight(self.screenPixel.width() - 1) watch_area.moveLeft(watch_area.right() - watch_area_width) if self.mousePoint.y() - watch_area_height / 2 < 0: watch_area.moveTop(0) watch_area.moveBottom(watch_area_height) if self.mousePoint.y( ) + watch_area_height / 2 >= self.screenPixel.height(): watch_area.moveBottom(self.screenPixel.height() - 1) watch_area.moveTop(watch_area.bottom() - watch_area_height) # tricks to solve the hidpi impact on QCursor.pos() watch_area.setTopLeft( QPoint(watch_area.topLeft().x() * self.scale, watch_area.topLeft().y() * self.scale)) watch_area.setBottomRight( QPoint(watch_area.bottomRight().x() * self.scale, watch_area.bottomRight().y() * self.scale)) watch_area_pixmap = self.screenPixel.copy(watch_area) # second, calculate the magnifier area magnifier_area_width = watch_area_width * 10 magnifier_area_height = watch_area_height * 10 font_area_height = 40 cursor_size = 24 magnifier_area = QRectF( QPoint(QCursor.pos().x() + cursor_size, QCursor.pos().y() + cursor_size), QPoint(QCursor.pos().x() + cursor_size + magnifier_area_width, QCursor.pos().y() + cursor_size + magnifier_area_height)) if magnifier_area.right() >= self.screenPixel.width(): magnifier_area.moveLeft(QCursor.pos().x() - magnifier_area_width - cursor_size / 2) if magnifier_area.bottom( ) + font_area_height >= self.screenPixel.height(): magnifier_area.moveTop(QCursor.pos().y() - magnifier_area_height - cursor_size / 2 - font_area_height) # third, draw the watch area to magnifier area watch_area_scaled = watch_area_pixmap.scaled( QSize(magnifier_area_width * self.scale, magnifier_area_height * self.scale)) magnifier_pixmap = self.graphics_scene.addPixmap(watch_area_scaled) magnifier_pixmap.setOffset(magnifier_area.topLeft()) # then draw lines and text self.graphics_scene.addRect(QRectF(magnifier_area), QPen(QColor(255, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.center().x(), magnifier_area.top()), QPointF(magnifier_area.center().x(), magnifier_area.bottom())), QPen(QColor(0, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.left(), magnifier_area.center().y()), QPointF(magnifier_area.right(), magnifier_area.center().y())), QPen(QColor(0, 255, 255), 2)) # get the rgb of mouse point point_rgb = QColor(self.screenPixel.toImage().pixel(self.mousePoint)) # draw information self.graphics_scene.addRect( QRectF( magnifier_area.bottomLeft(), magnifier_area.bottomRight() + QPoint(0, font_area_height + 30)), QPen(Qt.black), QBrush(Qt.black)) rgb_info = self.graphics_scene.addSimpleText( ' Rgb: ({0}, {1}, {2})'.format(point_rgb.red(), point_rgb.green(), point_rgb.blue())) rgb_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 5)) rgb_info.setPen(QPen(QColor(255, 255, 255), 2)) rect = self.selected_area.normalized() size_info = self.graphics_scene.addSimpleText( ' Size: {0} x {1}'.format(rect.width() * self.scale, rect.height() * self.scale)) size_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 15) + QPoint(0, font_area_height / 2)) size_info.setPen(QPen(QColor(255, 255, 255), 2)) def get_scale(self): return self.devicePixelRatio() def saveScreenshot(self, clipboard=False, fileName='screenshot.png', picType='png'): fullWindow = QRect(0, 0, self.width() - 1, self.height() - 1) selected = QRect(self.selected_area) if selected.left() < 0: selected.setLeft(0) if selected.right() >= self.width(): selected.setRight(self.width() - 1) if selected.top() < 0: selected.setTop(0) if selected.bottom() >= self.height(): selected.setBottom(self.height() - 1) source = (fullWindow & selected) source.setTopLeft( QPoint(source.topLeft().x() * self.scale, source.topLeft().y() * self.scale)) source.setBottomRight( QPoint(source.bottomRight().x() * self.scale, source.bottomRight().y() * self.scale)) image = self.screenPixel.copy(source) if clipboard: QGuiApplication.clipboard().setImage(image.toImage(), QClipboard.Clipboard) else: image.save(fileName, picType, 10) self.target_img = image self.target_img_pos = source self.screen_shot_grabed.emit(image.toImage()) self.screen_shot_pos_grabed.emit(source) def redraw(self): self.graphics_scene.clear() # draw screenshot self.graphics_scene.addPixmap(self.screenPixel) # prepare for drawing selected area rect = QRectF(self.selected_area) rect = rect.normalized() top_left_point = rect.topLeft() top_right_point = rect.topRight() bottom_left_point = rect.bottomLeft() bottom_right_point = rect.bottomRight() top_middle_point = (top_left_point + top_right_point) / 2 left_middle_point = (top_left_point + bottom_left_point) / 2 bottom_middle_point = (bottom_left_point + bottom_right_point) / 2 right_middle_point = (top_right_point + bottom_right_point) / 2 # draw the picture mask mask = QColor(0, 0, 0, 155) if self.selected_area == QRect(): self.graphics_scene.addRect(0, 0, self.screenPixel.width(), self.screenPixel.height(), QPen(Qt.NoPen), mask) else: self.graphics_scene.addRect(0, 0, self.screenPixel.width(), top_right_point.y(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect(0, top_left_point.y(), top_left_point.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect( top_right_point.x(), top_right_point.y(), self.screenPixel.width() - top_right_point.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect( 0, bottom_left_point.y(), self.screenPixel.width(), self.screenPixel.height() - bottom_left_point.y(), QPen(Qt.NoPen), mask) # draw the toolBar if self.action != ACTION_SELECT: spacing = 5 # show the toolbar first, then move it to the correct position # because the width of it may be wrong if this is the first time it shows self.tooBar.show() dest = QPointF(rect.bottomRight() - QPointF(self.tooBar.width(), 0) - QPointF(spacing, -spacing)) if dest.x() < spacing: dest.setX(spacing) pen_set_bar_height = self.penSetBar.height( ) if self.penSetBar is not None else 0 if dest.y() + self.tooBar.height( ) + pen_set_bar_height >= self.height(): if rect.top() - self.tooBar.height( ) - pen_set_bar_height < spacing: dest.setY(rect.top() + spacing) else: dest.setY(rect.top() - self.tooBar.height() - pen_set_bar_height - spacing) self.tooBar.move(dest.toPoint()) if self.penSetBar is not None: self.penSetBar.show() self.penSetBar.move(dest.toPoint() + QPoint(0, self.tooBar.height() + spacing)) if self.action == ACTION_TEXT: self.penSetBar.showFontWidget() else: self.penSetBar.showPenWidget() else: self.tooBar.hide() if self.penSetBar is not None: self.penSetBar.hide() # draw the list for step in self.drawListResult: self.drawOneStep(step) if self.drawListProcess is not None: self.drawOneStep(self.drawListProcess) if self.action != ACTION_TEXT: self.drawListProcess = None if self.selected_area != QRect(): self.items_to_remove = [] # draw the selected rectangle pen = QPen(QColor(0, 255, 255), 2) self.items_to_remove.append(self.graphics_scene.addRect(rect, pen)) # draw the drag point radius = QPoint(3, 3) brush = QBrush(QColor(0, 255, 255)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_left_point - radius, top_left_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_middle_point - radius, top_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_right_point - radius, top_right_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(left_middle_point - radius, left_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(right_middle_point - radius, right_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_left_point - radius, bottom_left_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_middle_point - radius, bottom_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_right_point - radius, bottom_right_point + radius), pen, brush)) # draw the textedit if self.textPosition is not None: textSpacing = 50 position = QPoint() if self.textPosition.x() + self.textInput.width( ) >= self.screenPixel.width(): position.setX(self.textPosition.x() - self.textInput.width()) else: position.setX(self.textPosition.x()) if self.textRect is not None: if self.textPosition.y() + self.textInput.height( ) + self.textRect.height() >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height() - self.textRect.height()) else: position.setY(self.textPosition.y() + self.textRect.height()) else: if self.textPosition.y() + self.textInput.height( ) >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height()) else: position.setY(self.textPosition.y()) self.textInput.move(position) self.textInput.show() # self.textInput.getFocus() # draw the magnifier if self.action == ACTION_SELECT: self.drawMagnifier() if self.mousePressed: self.drawSizeInfo() if self.action == ACTION_MOVE_SELECTED: self.drawSizeInfo() # deal with every step in drawList def drawOneStep(self, step): """ :type step: tuple """ if step[0] == ACTION_RECT: self.graphics_scene.addRect( QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_ELLIPSE: self.graphics_scene.addEllipse( QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_ARROW: arrow = QPolygonF() linex = float(step[1] - step[3]) liney = float(step[2] - step[4]) line = sqrt(pow(linex, 2) + pow(liney, 2)) # in case to divided by 0 if line == 0: return sinAngel = liney / line cosAngel = linex / line # sideLength is the length of bottom side of the body of an arrow # arrowSize is the size of the head of an arrow, left and right # sides' size is arrowSize, and the bottom side's size is arrowSize / 2 sideLength = step[5].width() arrowSize = 8 bottomSize = arrowSize / 2 tmpPoint = QPointF(step[3] + arrowSize * sideLength * cosAngel, step[4] + arrowSize * sideLength * sinAngel) point1 = QPointF(step[1] + sideLength * sinAngel, step[2] - sideLength * cosAngel) point2 = QPointF(step[1] - sideLength * sinAngel, step[2] + sideLength * cosAngel) point3 = QPointF(tmpPoint.x() - sideLength * sinAngel, tmpPoint.y() + sideLength * cosAngel) point4 = QPointF(tmpPoint.x() - bottomSize * sideLength * sinAngel, tmpPoint.y() + bottomSize * sideLength * cosAngel) point5 = QPointF(step[3], step[4]) point6 = QPointF(tmpPoint.x() + bottomSize * sideLength * sinAngel, tmpPoint.y() - bottomSize * sideLength * cosAngel) point7 = QPointF(tmpPoint.x() + sideLength * sinAngel, tmpPoint.y() - sideLength * cosAngel) arrow.append(point1) arrow.append(point2) arrow.append(point3) arrow.append(point4) arrow.append(point5) arrow.append(point6) arrow.append(point7) arrow.append(point1) self.graphics_scene.addPolygon(arrow, step[5], step[6]) elif step[0] == ACTION_LINE: self.graphics_scene.addLine( QLineF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_FREEPEN: self.graphics_scene.addPath(step[1], step[2]) elif step[0] == ACTION_TEXT: textAdd = self.graphics_scene.addSimpleText(step[1], step[2]) textAdd.setPos(step[3]) textAdd.setBrush(QBrush(step[4])) self.textRect = textAdd.boundingRect() # draw the size information on the top left corner def drawSizeInfo(self): sizeInfoAreaWidth = 200 sizeInfoAreaHeight = 30 spacing = 5 rect = self.selected_area.normalized() sizeInfoArea = QRect(rect.left(), rect.top() - spacing - sizeInfoAreaHeight, sizeInfoAreaWidth, sizeInfoAreaHeight) if sizeInfoArea.top() < 0: sizeInfoArea.moveTopLeft(rect.topLeft() + QPoint(spacing, spacing)) if sizeInfoArea.right() >= self.screenPixel.width(): sizeInfoArea.moveTopLeft(rect.topLeft() - QPoint(spacing, spacing) - QPoint(sizeInfoAreaWidth, 0)) if sizeInfoArea.left() < spacing: sizeInfoArea.moveLeft(spacing) if sizeInfoArea.top() < spacing: sizeInfoArea.moveTop(spacing) self.items_to_remove.append( self.graphics_scene.addRect(QRectF(sizeInfoArea), QPen(Qt.white), QBrush(Qt.black))) sizeInfo = self.graphics_scene.addSimpleText(' {0} x {1}'.format( rect.width() * self.scale, rect.height() * self.scale)) sizeInfo.setPos(sizeInfoArea.topLeft() + QPoint(0, 2)) sizeInfo.setPen(QPen(QColor(255, 255, 255), 2)) self.items_to_remove.append(sizeInfo) def drawRect(self, x1, x2, y1, y2, result): rect = self.selected_area.normalized() tmpRect = QRect(QPoint(x1, x2), QPoint(y1, y2)).normalized() resultRect = rect & tmpRect tmp = [ ACTION_RECT, resultRect.topLeft().x(), resultRect.topLeft().y(), resultRect.bottomRight().x(), resultRect.bottomRight().y(), QPen(QColor(self.penColorNow), int(self.penSizeNow)) ] if result: self.drawListResult.append(tmp) else: self.drawListProcess = tmp def drawEllipse(self, x1, x2, y1, y2, result): rect = self.selected_area.normalized() tmpRect = QRect(QPoint(x1, x2), QPoint(y1, y2)).normalized() resultRect = rect & tmpRect tmp = [ ACTION_ELLIPSE, resultRect.topLeft().x(), resultRect.topLeft().y(), resultRect.bottomRight().x(), resultRect.bottomRight().y(), QPen(QColor(self.penColorNow), int(self.penSizeNow)) ] if result: self.drawListResult.append(tmp) else: self.drawListProcess = tmp def drawArrow(self, x1, x2, y1, y2, result): rect = self.selected_area.normalized() if y1 <= rect.left(): y1 = rect.left() elif y1 >= rect.right(): y1 = rect.right() if y2 <= rect.top(): y2 = rect.top() elif y2 >= rect.bottom(): y2 = rect.bottom() tmp = [ ACTION_ARROW, x1, x2, y1, y2, QPen(QColor(self.penColorNow), int(self.penSizeNow)), QBrush(QColor(self.penColorNow)) ] if result: self.drawListResult.append(tmp) else: self.drawListProcess = tmp def drawLine(self, x1, x2, y1, y2, result): rect = self.selected_area.normalized() if y1 <= rect.left(): y1 = rect.left() elif y1 >= rect.right(): y1 = rect.right() if y2 <= rect.top(): y2 = rect.top() elif y2 >= rect.bottom(): y2 = rect.bottom() tmp = [ ACTION_LINE, x1, x2, y1, y2, QPen(QColor(self.penColorNow), int(self.penSizeNow)) ] if result: self.drawListResult.append(tmp) else: self.drawListProcess = tmp def drawFreeLine(self, pointPath, result): tmp = [ ACTION_FREEPEN, QPainterPath(pointPath), QPen(QColor(self.penColorNow), int(self.penSizeNow)) ] if result: self.drawListResult.append(tmp) else: self.drawListProcess = tmp def textChange(self): if self.textPosition is None: return self.text = self.textInput.getText() self.drawListProcess = [ ACTION_TEXT, str(self.text), QFont(self.fontNow), QPoint(self.textPosition), QColor(self.penColorNow) ] self.redraw() def undoOperation(self): if len(self.drawListResult) == 0: self.action = ACTION_SELECT self.selected_area = QRect() self.selectedAreaRaw = QRect() self.tooBar.hide() if self.penSetBar is not None: self.penSetBar.hide() else: self.drawListResult.pop() self.redraw() def saveOperation(self): filename = QFileDialog.getSaveFileName(self, 'Save file', './screenshot.png', '*.png;;*.jpg') if len(filename[0]) == 0: return else: self.saveScreenshot(False, filename[0], filename[1][2:]) self.close() def close(self): self.widget_closed.emit() super().close() self.tooBar.close() if self.penSetBar is not None: self.penSetBar.close() def saveToClipboard(self): QApplication.clipboard().setText('Test in save function') self.saveScreenshot(True) self.close() # slots def changeAction(self, nextAction): QApplication.clipboard().setText('Test in changeAction function') if nextAction == ACTION_UNDO: self.undoOperation() elif nextAction == ACTION_SAVE: self.saveOperation() elif nextAction == ACTION_CANCEL: self.close() elif nextAction == ACTION_SURE: self.saveToClipboard() else: self.action = nextAction self.setFocus() def changePenSize(self, nextPenSize): self.penSizeNow = nextPenSize def changePenColor(self, nextPenColor): self.penColorNow = nextPenColor def cancelInput(self): self.drawListProcess = None self.textPosition = None self.textRect = None self.textInput.hide() self.textInput.clearText() self.redraw() def okInput(self): self.text = self.textInput.getText() self.drawListResult.append([ ACTION_TEXT, str(self.text), QFont(self.fontNow), QPoint(self.textPosition), QColor(self.penColorNow) ]) self.textPosition = None self.textRect = None self.textInput.hide() self.textInput.clearText() self.redraw() def changeFont(self, font): self.fontNow = font