class Window(QLabel): def __init__(self, parent = None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.end = QPoint() self.title = 'Select the region of interest and close the window' self.setWindowTitle(self.title) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: #self.rubberBand.hide() self.end = QPoint(event.pos())
class QExampleLabel(QLabel): def __init__(self, parentQWidget=None): super(QExampleLabel, self).__init__(parentQWidget) self.initUI() def initUI(self): self.setPixmap(QtGui.QPixmap('input.png')) def mousePressEvent(self, eventQMouseEvent): self.originQPoint = eventQMouseEvent.pos() self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self) self.currentQRubberBand.setGeometry( QtCore.QRect(self.originQPoint, QtCore.QSize())) self.currentQRubberBand.show() def mouseMoveEvent(self, eventQMouseEvent): self.currentQRubberBand.setGeometry( QtCore.QRect(self.originQPoint, eventQMouseEvent.pos()).normalized()) def mouseReleaseEvent(self, eventQMouseEvent): self.currentQRubberBand.hide() currentQRect = self.currentQRubberBand.geometry() self.currentQRubberBand.deleteLater() cropQPixmap = self.pixmap().copy(currentQRect) cropQPixmap.save('output.png')
class Label(QtWidgets.QLabel): def __init__(self): super().__init__() self.origin = QPoint() self.rubberBand = None # def paintEvent(self, event): # qp = QtGui.QPainter(self) # br = QtGui.QBrush(QtGui.QColor(100, 10, 10, 40)) # qp.setBrush(br) # qp.drawRect(QtCore.QRect(self.begin, self.end)) def mousePressEvent(self, event): super(Label, self).mousePressEvent(event) self.origin = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) print("Rubber!") self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() #self.update() def mouseMoveEvent(self, event): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if self.rubberBand: self.rubberBand.hide()
class Window(QLabel): def __init__(self, pixmap, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.pixmap = pixmap def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.rubberBand.hide() print(self.rubberBand.geometry()) def resizeEvent(self, event): self.updateScreenshotLabel() # scaledSize = self.pixmap.size() # scaledSize.scale(self.screenshotLabel.size(), Qt.KeepAspectRatio) # if not self.screenshotLabel.pixmap() or scaledSize != self.screenshotLabel.pixmap().size(): # self.updateScreenshotLabel() def updateScreenshotLabel(self): self.setPixmap( self.pixmap.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
class Label(QLabel): selection_changed = pyqtSignal(QRect, name="selectionChanged") def __init__(self): QLabel.__init__(self) self.rb = QRubberBand(QRubberBand.Rectangle, self) self.setMouseTracking(True) def mousePressEvent(self, event: QMouseEvent): self.origin = event.pos() self.rb.setGeometry(QRect(self.origin, QSize())) self.rb.show() QLabel.mousePressEvent(self, event) def mouseMoveEvent(self, event: QMouseEvent): if self.rb.isVisible(): self.rb.setGeometry( QRect(self.origin, event.pos()).normalized()) QWidget.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if self.rb.isVisible(): self.rb.hide() self.selection_changed.emit(self.rb.geometry()) QLabel.mouseReleaseEvent(self, event)
class WidgetPicker(QWidget): """Widget for letting user point at another widget.""" selected = Signal() def __init__(self): super(WidgetPicker, self).__init__() self.band = QRubberBand(QRubberBand.Rectangle) self.setMouseTracking(True) self.el = QEventLoop() def mousePressEvent(self, ev): self.el.quit() self.widget = QApplication.widgetAt(ev.globalPos()) self.band.hide() def mouseMoveEvent(self, ev): widget = QApplication.widgetAt(ev.globalPos()) if widget: rect = widget.frameGeometry() if widget.parent(): rect.moveTo(widget.parent().mapToGlobal(rect.topLeft())) self.band.setGeometry(rect) self.band.show() else: self.band.hide() def run(self): self.grabMouse() try: self.el.exec_() finally: self.releaseMouse() return self.widget
class SelectAreaWidget(QLabel): areaSelected = pyqtSignal() def __init__(self): super(SelectAreaWidget, self).__init__() self.rubberBand = None pixmap = QApplication.primaryScreen().grabWindow(0) self.setPixmap(pixmap) self.showFullScreen() self.show() def mousePressEvent(self, event): if event.button() == Qt.RightButton: if self.rubberBand: self.rubberBand.hide() self.close() if event.button() == Qt.LeftButton: self.origin = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, None) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if self.rubberBand: self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if self.rubberBand: self.destination = event.pos() self.areaSelected.emit()
class MiniMapGraphicsView(QGraphicsView): def __init__(self, parent): super().__init__(parent) self._drag_start_pos = None self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setFixedSize(200, 200) self.viewport().setFixedSize(self.contentsRect().size()) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setInteractive(False) self.setFocusProxy(parent) self.band = QRubberBand(QRubberBand.Rectangle, self) self.band.hide() def centerOn(self, pos): if self.band.isVisible(): self.parent().centerOn(self.mapToScene(pos)) rect = self.band.geometry() rect.moveCenter(pos) self.band.setGeometry(rect) def mousePressEvent(self, event): if self.band.isVisible() and event.button() == Qt.LeftButton: rect = self.band.geometry() if event.pos() in rect: self._drag_start_pos = event.pos() else: self.centerOn(event.pos()) def mouseMoveEvent(self, event): if self.band.isVisible() and event.buttons() == Qt.MouseButtons( Qt.LeftButton) and self._drag_start_pos is not None: self.centerOn(event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.band.isVisible(): self.viewport().unsetCursor() self._drag_start_pos = None def adjustRubberband(self): scene = self.scene() if scene is None: return rect = self.parent().mapToScene(self.parent().rect()).boundingRect() if not rect.contains(scene.sceneRect()): rect = self.mapFromScene(rect).boundingRect() self.band.setGeometry(rect) self.band.show() else: self.band.hide() def zoomToFit(self): self.fitInView(self.scene().sceneRect().adjusted(-20, -20, 20, 20), Qt.KeepAspectRatio)
class QImageEdit(QLabel): def __init__(self, parentQWidget=None): super(QImageEdit, self).__init__(parentQWidget) self.rubberBand = None self.move_rubberBand = False self.rubberBand_offset = None self.originPoint = None def setImage(self, image: QPixmap): self.setPixmap(image) def getImage(self) -> QPixmap: if self.rubberBand is not None: currentRect = self.rubberBand.geometry() return self.pixmap().copy(currentRect) else: return self.pixmap() def clear(self): super(QImageEdit, self).clear() if self.rubberBand is not None: self.rubberBand.deleteLater() self.rubberBand = None self.move_rubberBand = False self.rubberBand_offset = None self.originPoint = None def mousePressEvent(self, event): self.originPoint = event.pos() if self.rubberBand is None: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.originPoint, QSize())) self.rubberBand.show() else: if self.rubberBand.geometry().contains(self.originPoint): self.rubberBand_offset = \ self.originPoint - self.rubberBand.pos() self.move_rubberBand = True else: self.rubberBand.hide() self.rubberBand.deleteLater() self.rubberBand = None self.move_rubberBand = False self.rubberBand_offset = None self.mousePressEvent(event) def mouseMoveEvent(self, event): newPoint = event.pos() if self.move_rubberBand: self.rubberBand.move(newPoint - self.rubberBand_offset) else: self.rubberBand.setGeometry( QRect(self.originPoint, newPoint).normalized()) def mouseReleaseEvent(self, event): self.move_rubberBand = False
class SelectWidget(QWidget, Ui_Form2): select = [0,0,0,0] def __init__(self, parent=None): super(SelectWidget, self).__init__(parent) self.setWindowOpacity(0.5) self.setupUi(self) desktop = QtWidgets.QDesktopWidget() self.resize(desktop.availableGeometry().width(), desktop.availableGeometry().height()) self.rubberband = QRubberBand( QRubberBand.Rectangle, self) self.setMouseTracking(True) def mousePressEvent(self, event): self.select[0] = event.screenPos().x() self.select[1] = event.screenPos().y() self.origin = event.pos() self.rubberband.setGeometry( QtCore.QRect(self.origin, QtCore.QSize())) self.rubberband.show() QWidget.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self.rubberband.isVisible(): self.rubberband.setGeometry( QtCore.QRect(self.origin, event.pos()).normalized()) QWidget.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): self.select[2] = event.screenPos().x() self.select[3] = event.screenPos().y() if self.rubberband.isVisible(): self.rubberband.hide() rect = self.rubberband.geometry() # ポインタ座標を左上→右下に揃える if self.select[0] > self.select[2]: tmp = self.select[0] self.select[0] = self.select[2] self.select[2] = tmp if self.select[1] > self.select[3]: tmp = self.select[1] self.select[1] = self.select[3] self.select[3] = tmp # 選択した面積がゼロの場合は何もしないで関数を終わる if self.select[0]==self.select[2] or self.select[1]==self.select[3]: QWidget.mouseReleaseEvent(self, event) self.close() return # ポインタ座標をメインウインドウに設定する area = '' for point in self.select: area = area + str(int(point)) + ',' main_window.lineEdit.setText(area[0:-1]) self.close() QWidget.mouseReleaseEvent(self, event)
class MyLabel(QLabel): def __init__(self, parent=None, func=None): self.func = func QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.slitpos = 250 self.focus = (333, 666, 333, 666) #xs,xe,ys,ye self.geometry = (0, 0, 1000, 1000) #x,y,w,h def paintEvent(self, event): QLabel.paintEvent(self, event) painter = QPainter(self) painter.setPen(Qt.red) x, y, w, h = self.geometry d = 20 painter.drawLine(x + w // 2 - self.slitpos * w // 1000, y, x + w // 2 - self.slitpos * w // 1000, y + h) painter.drawLine(x + w // 2 - self.slitpos * w // 1000 - d, y + h / 2, x + w // 2 - self.slitpos * w // 1000, y + h / 2 - d) painter.drawLine(x + w // 2 - self.slitpos * w // 1000 - d, y + h / 2, x + w // 2 - self.slitpos * w // 1000, y + h / 2 + d) painter.drawLine(x + w // 2 + self.slitpos * w // 1000, y, x + w // 2 + self.slitpos * w // 1000, y + h) painter.drawLine(x + w // 2 + self.slitpos * w // 1000 + d, y + h // 2, x + w // 2 + self.slitpos * w // 1000, y + h // 2 - d) painter.drawLine(x + w // 2 + self.slitpos * w // 1000 + d, y + h // 2, x + w // 2 + self.slitpos * w // 1000, y + h // 2 + d) painter.setPen(Qt.green) painter.drawRect(x + w * self.focus[0] // 1000, y + h * self.focus[2] // 1000, w * (self.focus[1] - self.focus[0]) // 1000, h * (self.focus[3] - self.focus[2]) // 1000) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.rubberBand.hide() self.region = QRect(self.origin, event.pos()).normalized() if self.func is not None: self.func(self.region)
class ImageView(QGraphicsView): def __init__(self, parent=None): QGraphicsView.__init__(self, parent) self.go_prev_img = parent.go_prev_img self.go_next_img = parent.go_next_img pal = self.palette() pal.setColor(self.backgroundRole(), Qt.black) self.setPalette(pal) self.setFrameShape(QFrame.NoFrame) def mousePressEvent(self, event): """Go to the next / previous image, or be able to drag the image with a hand.""" if event.button() == Qt.LeftButton: x = event.x() if x < 100: self.go_prev_img() elif x > self.width() - 100: self.go_next_img() else: self.setDragMode(QGraphicsView.ScrollHandDrag) QGraphicsView.mousePressEvent(self, event) def mouseReleaseEvent(self, event): self.setDragMode(QGraphicsView.NoDrag) QGraphicsView.mouseReleaseEvent(self, event) def zoom(self, zoomratio): self.scale(zoomratio, zoomratio) def wheelEvent(self, event): zoomratio = 1.1 if event.angleDelta().y() < 0: zoomratio = 1.0 / zoomratio self.scale(zoomratio, zoomratio) def setup_crop(self, width, height): self.rband = QRubberBand(QRubberBand.Rectangle, self) coords = self.mapFromScene(0, 0, width, height) self.rband.setGeometry(QRect(coords.boundingRect())) self.rband.show() def crop_draw(self, x, y, width, height): coords = self.mapFromScene(x, y, width, height) self.rband.setGeometry(QRect(coords.boundingRect())) def get_coords(self): rect = self.rband.geometry() size = self.mapToScene(rect).boundingRect() x = int(size.x()) y = int(size.y()) width = int(size.width()) height = int(size.height()) return (x, y, width, height)
class ImageView(QGraphicsView): def __init__(self, parent=None): QGraphicsView.__init__(self, parent) self.go_prev_img = parent.go_prev_img self.go_next_img = parent.go_next_img pal = self.palette() pal.setColor(self.backgroundRole(), Qt.black) self.setPalette(pal) self.setFrameShape(QFrame.NoFrame) def mousePressEvent(self, event): """Go to the next / previous image, or be able to drag the image with a hand.""" if event.button() == Qt.LeftButton: x = event.x() if x < 100: self.go_prev_img() elif x > self.width() - 100: self.go_next_img() else: self.setDragMode(QGraphicsView.ScrollHandDrag) QGraphicsView.mousePressEvent(self, event) def mouseReleaseEvent(self, event): self.setDragMode(QGraphicsView.NoDrag) QGraphicsView.mouseReleaseEvent(self, event) def zoom(self, zoomratio): self.scale(zoomratio, zoomratio) def wheelEvent(self, event): zoomratio = 1.1 if event.angleDelta().y() < 0: zoomratio = 1.0 / zoomratio self.scale(zoomratio, zoomratio) def setup_crop(self, width, height): self.rband = QRubberBand(QRubberBand.Rectangle, self) coords = self.mapFromScene(0, 0, width, height) self.rband.setGeometry(QRect(coords.boundingRect())) self.rband.show() def crop_draw(self, x, y, width, height): coords = self.mapFromScene(x, y, width, height) self.rband.setGeometry(QRect(coords.boundingRect())) def get_coords(self): rect = self.rband.geometry() size = self.mapToScene(rect).boundingRect() x = int(size.x()) y = int(size.y()) width = int(size.width()) height = int(size.height()) return (x, y, width, height)
class MyLabel(QLabel): def __init__(self, parent = None, func=None): self.func = func QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.slitpos = 250 self.focus = (333,666,333,666) #xs,xe,ys,ye self.geometry = (0,0,1000,1000) #x,y,w,h def paintEvent(self, event): QLabel.paintEvent(self, event) painter = QPainter(self) painter.setPen(Qt.red) x,y,w,h = self.geometry d = 20 painter.drawLine(x+w//2-self.slitpos*w//1000,y, x+w//2-self.slitpos*w//1000,y+h) painter.drawLine(x+w//2-self.slitpos*w//1000-d,y+h/2, x+w//2-self.slitpos*w//1000, y+h/2-d) painter.drawLine(x+w//2-self.slitpos*w//1000-d,y+h/2, x+w//2-self.slitpos*w//1000, y+h/2+d) painter.drawLine(x+w//2+self.slitpos*w//1000,y, x+w//2+self.slitpos*w//1000,y+h) painter.drawLine(x+w//2+self.slitpos*w//1000+d,y+h//2, x+w//2+self.slitpos*w//1000, y+h//2-d) painter.drawLine(x+w//2+self.slitpos*w//1000+d,y+h//2, x+w//2+self.slitpos*w//1000, y+h//2+d) painter.setPen(Qt.green) painter.drawRect(x+w*self.focus[0]//1000,y+h*self.focus[2]//1000,w*(self.focus[1]-self.focus[0])//1000,h*(self.focus[3]-self.focus[2])//1000) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.rubberBand.hide() self.region = QRect(self.origin, event.pos()).normalized() if self.func is not None: self.func(self.region)
class QLabelSelectable(QLabel): selectionFinished = pyqtSignal() def __init__(self, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.startSelection = False self.endSelection = False def reset(self): self.startSelection = False self.endSelection = False def mousePressEvent(self, event): if event.button( ) == Qt.LeftButton and self.startSelection and not self.endSelection: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull( ) and self.startSelection and not self.endSelection: self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.startSelection: #print(self.rubberBand.geometry()) self.drawRectangle() self.rubberBand.hide() self.endSelection = True def drawRectangle(self): # create painter instance with pixmap self.painterInstance = QPainter(self.pixmap()) # set rectangle color and thickness self.penRectangle = QPen(Qt.red) self.penRectangle.setWidth(3) # draw rectangle on painter self.painterInstance.setPen(self.penRectangle) self.painterInstance.drawRect(self.rubberBand.geometry()) self.selectionFinished.emit()
class ImageWidget(QLabel): areaSelected = pyqtSignal(float, float, float, float, QPixmap) def __init__(self, parent=None): super().__init__(parent) self.rubberBand = None self.origin = None def mousePressEvent(self, event): self.origin = event.pos() if self.rubberBand is None: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): self.rubberBand.hide() zoreRect = QRect(self.origin, event.pos()).normalized() pixmapSize = self.pixmap().size() pixX1 = zoreRect.x() pixX2 = zoreRect.x() + zoreRect.width() pixY1 = zoreRect.y() pixY2 = zoreRect.y() + zoreRect.height() width = pixmapSize.width() height = pixmapSize.height() x1 = pixX1/width x1 = x1 if x1 >= 0.0 else 0.0 x1 = x1 if x1 <= 1.0 else 1.0 y1 = pixY1/height y1 = y1 if y1 >= 0.0 else 0.0 y1 = y1 if y1 <= 1.0 else 1.0 x2 = pixX2/width x2 = x2 if x2 >= 0.0 else 0.0 x2 = x2 if x2 <= 1.0 else 1.0 y2 = pixY2/height y2 = y2 if y2 >= 0.0 else 0.0 y2 = y2 if y2 <= 1.0 else 1.0 rect = QRect(min(pixX1, pixX2), min(pixY1, pixY2), abs(pixX1- pixX2), abs(pixY1- pixY2)) selectedImg = self.pixmap().copy(rect) self.areaSelected.emit(min(x1, x2), min(y1, y2), np.abs(x1-x2), np.abs(y1-y2), selectedImg)
class BandMixin(object): def __init__(self, **kwargs): super(BandMixin, self).__init__(**kwargs) self.__band = None def showBand(self, *geom): if not self.__band: self.__band = QRubberBand(QRubberBand.Rectangle, parent=self) self.__band.setGeometry(*geom) self.__band.show() def hideBand(self): if self.__band: self.__band.hide() self.__band.setParent(None) self.__band = None
class screen(QWidget): close_signal = pyqtSignal() def __init__(self, image_path): super().__init__() # self.close_signal.connect(self.ocr) self.image_path = image_path self.cut = False self.setMouseTracking(True) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) # print("=======") self.showFullScreen() self.setWindowOpacity(0.5) def mousePressEvent(self, event): self.cut = True self.start_x = event.x() self.start_y = event.y() def mouseReleaseEvent(self, event): self.cut = False r = self.rubberBand.geometry() print(r.getRect()) self.setWindowOpacity(0) self.screen = QApplication.primaryScreen() screenshot = self.screen.grabWindow(QApplication.desktop().winId(), r.x(), r.y(), r.width(), r.height()) screenshot.save(self.image_path) # screenshot.save(r"C:\temp\png\a.jpg") # text = pytesseract.image_to_string(self.image_path) # print(text) self.close_signal.emit() self.close() def mouseMoveEvent(self, event): if self.cut: end_x = event.x() end_y = event.y() self.rect = QRect(QPoint(self.start_x, self.start_y), QPoint(end_x, end_y)) self.rubberBand.setGeometry(self.rect) self.rubberBand.show()
class TimeView(QGraphicsView): time_clicked = pyqtSignal(float) time_selected = pyqtSignal(float, float) def __init__(self, parent=None): super().__init__(parent=parent) self.initialClick = QPoint() self.selectionBand = QRubberBand(QRubberBand.Rectangle, self) self.selecting = False def mouseReleaseEvent(self, event): clicked_x = self.mapToScene(event.pos()).x() self.selectionBand.hide() if clicked_x == self.mapToScene(self.initialClick).x(): self.time_clicked.emit(clicked_x) else: if self.initialClick.x() < clicked_x: self.time_selected.emit( self.mapToScene(self.initialClick).x(), clicked_x) else: self.time_selected.emit(clicked_x, self.mapToScene(self.initialClick).x()) self.selecting = False def mousePressEvent(self, event): self.selecting = True self.initialClick = event.pos() self.selectionBand.setGeometry( QRect(self.initialClick.x(), 0, 1, self.height())) self.selectionBand.show() def mouseMoveEvent(self, event): if self.selecting: current_pos = event.pos() if current_pos.x() < self.initialClick.x(): start_x = current_pos.x() width = self.initialClick.x() - start_x else: start_x = self.initialClick.x() width = current_pos.x() - self.initialClick.x() self.selectionBand.setGeometry( QRect(start_x, 0, width, self.height()))
class PageScrollArea(QScrollArea): reachbottom = pyqtSignal() reachtop = pyqtSignal() areaSelected = pyqtSignal(QRect) def __init__(self, parent): super().__init__(parent) def wheelEvent(self, event): super().wheelEvent(event) if self.verticalScrollBar().value() == self.verticalScrollBar( ).maximum() and event.angleDelta().y() == -120: self.reachbottom.emit() if self.verticalScrollBar().value() == 0 and event.angleDelta().y( ) == 120: self.reachtop.emit() def mousePressEvent(self, event): self.rubberorigin = event.pos() self.rubberband = QRubberBand(QRubberBand.Rectangle, self) self.rubberband.setGeometry(QRect(self.rubberorigin, QSize())) self.rubberband.show() def mouseReleaseEvent(self, event): rect = QRect(self.rubberband.pos(), self.rubberband.size()) self.areaSelected.emit(rect) self.rubberband.hide() def mouseMoveEvent(self, event): super().mouseMoveEvent(event) self.rubberband.setGeometry( QRect(self.rubberorigin, event.pos()).normalized()) def keyPressEvent(self, event): super().keyPressEvent(event) if self.verticalScrollBar().value() == self.verticalScrollBar( ).maximum() and (event.key() == 16777237 or event.key() == 16777239): self.reachbottom.emit() if self.verticalScrollBar().value() == 0 and ( event.key() == 16777235 or event.key() == 16777238): self.reachtop.emit()
class Image_Display(RawImageWidget, QWidget): def __init__(self, parent=None, **kargs): RawImageWidget.__init__(self, parent=parent, scaled=True) super(QWidget, self).__init__(parent) self.setWindowTitle("image") self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.mousePressPosition = QPoint(0, 0) self.mouseReleasePosition = QPoint(0, 0) self.clientCallback = None self.mousePressed = False self.okToClose = False self.setGeometry(QRect(10, 300, 600, 600)) def closeEvent(self, event): if not self.okToClose: self.hide() return def display(self, image, pixelLevels): self.setImage(image, levels=pixelLevels) self.show() def mousePressEvent(self, event): self.mousePressPosition = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.mousePressPosition, QSize())) self.rubberBand.show() self.mousePressed = True def mouseMoveEvent(self, event): if not self.mousePressed: return self.rubberBand.setGeometry( QRect(self.mousePressPosition, event.pos()).normalized()) def mouseReleaseEvent(self, event): if not self.mousePressed: return self.mouseReleasePosition = QPoint(event.pos()) if not self.clientCallback == None: self.clientCallback(self.mousePressPosition, self.mouseReleasePosition) self.rubberBand.hide() self.mousePressed = False def clientReleaseEvent(self, clientCallback): self.clientCallback = clientCallback
class Window(QLabel): def __int__(self, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() def mousePressEvent(self, event: QMouseEvent): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event: QMouseEvent): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event: QMouseEvent): if event.button() == Qt.LeftButton: self.rubberBand.hide()
class ImageLabel(QLabel): refresh = pyqtSignal() def __init__(self, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() self.coords = (0, 0, 0, 0) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: #self.rubberBand.hide() x0 = self.origin.x() x1 = event.pos().x() y0 = self.origin.y() y1 = event.pos().y() self.coords = (x0, x1, y0, y1) self.refresh.emit() def getCoords(self): return self.coords
class Image(QLabel): # taken from https://wiki.python.org/moin/PyQt/Selecting%20a%20region%20of%20a%20widget def __init__(self, parent=None): QLabel.__init__(self, parent) self.selection = QRubberBand(QRubberBand.Rectangle, self) self.selection_origin = None self.selection_end = None self.image_path = None def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.selection_origin = QPoint(event.pos()) self.selection.setGeometry(QRect(self.selection_origin, QSize())) self.selection.show() def mouseMoveEvent(self, event): if not self.selection_origin.isNull(): self.selection.setGeometry(QRect(self.selection_origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.selection_end = QPoint(event.pos())
class Mylabel(QLabel): def __init__(self, parent=None): super(Mylabel, self).__init__(parent) self.rubber = None self.origin = None self.parent = parent def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None: super().mousePressEvent(a0) self.origin = a0.pos() print(self.origin) if self.rubber is None: self.rubber = QRubberBand(QRubberBand.Line, self) self.rubber.setGeometry(QRect(self.origin, QSize())) self.rubber.show() def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None: super().mouseMoveEvent(a0) if self.rubber: self.rubber.setGeometry(QRect(self.origin, a0.pos()).normalized()) def mouseReleaseEvent(self, a0: QtGui.QMouseEvent) -> None: super().mouseReleaseEvent(a0)
class VideoArea(QLabel): def __init__(self, parent=None, main=None): QLabel.__init__(self, parent) self.selection = QRubberBand(QRubberBand.Rectangle, self) self.main = main def mousePressEvent(self, event): if event.button() == Qt.LeftButton: position = QPoint(event.pos()) if self.selection.isVisible(): if (self.upper_left - position).manhattanLength() < 20: self.mode = "UL" elif (self.lower_right - position).manhattanLength() < 20: self.mode = "LR" else: self.selection.hide() else: self.upper_left = position self.lower_right = position self.mode = "LR" self.selection.show() def mouseMoveEvent(self, event): if self.selection.isVisible(): if self.mode == "LR": self.lower_right = QPoint(event.pos()) elif self.mode == "UL": self.upper_left = QPoint(event.pos()) self.selection.setGeometry( QRect(self.upper_left, self.lower_right).normalized()) def mouseReleaseEvent(self, event): self.main.controller.set_coordinates( *self.selection.geometry().getCoords()) self.selection.hide()
class App(QWidget): """Class App is the base class for the whole Screenshot Tool. """ def __init__(self, save_path): super().__init__() self.save_path = save_path # Destkop Screenshot desktop_capture = ImageGrab.grab() desktop_capture.save('desktop_capture_temp.png') self.screen_size = QDesktopWidget().screenGeometry() QApplication.setOverrideCursor(QCursor(QtCore.Qt.CrossCursor)) self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) self.area_defined = False self.imageName = None self.selected_area_center = None # Start the Qt UI self.initUI() def initUI(self): """Init the Qt UI """ # Create widget self.image_label = QLabel(self) # Screen capture of primary screen pixmap = QPixmap('desktop_capture_temp.png') # Set the image on the widget self.image_label.setPixmap(pixmap) # Transparent overlay self.overlay_label = QLabel(self) self.overlay_label.setStyleSheet( 'background-color: rgba(0, 0, 0, 40);') self.overlay_label.setGeometry(self.screen_size) # Green X when clicking the offset self.offset_label = QLabel(self) self.offset_label.setText('<font color="green" size=5>x</font>') # Red Text when screen snipping is in progress self.help_text = QLabel(self) self.help_text.setGeometry( QtCore.QRect(((self.screen_size.width() - 350) / 2), 0, 350, 100)) self.help_text.setText( '<font color="red" size=14>Screen Snipping In Progress...</font>') # Display app fullscreen self.showFullScreen() def keyPressEvent(self, keyPressed): """Handle key press events. Save image or close everything withouth save. """ key = keyPressed.key() # If enter or return is pressed save the image and offset data and ask for image name if key == QtCore.Qt.Key_Return or key == QtCore.Qt.Key_Enter: self.hide() self.getImageName() if self.save_path == 'None': self.cropQPixmap.save(os.path.normpath(self.imageName + '.png')) else: self.cropQPixmap.save( os.path.normpath(self.save_path + '/' + self.imageName + '.png')) try: self.offset_pos # If there is not offset set. Set the offset to 0, 0 except AttributeError: if self.save_path == 'None': with open(os.path.normpath(self.imageName + '.json'), 'w') as outfile: image_data = {'clickOffset': [0, 0]} json.dump(image_data, outfile, indent=4) else: with open( os.path.normpath(self.save_path + '/' + self.imageName + '.json'), 'w') as outfile: image_data = {'clickOffset': [0, 0]} json.dump(image_data, outfile, indent=4) # If there is a offset set. Savet the offset. else: if self.save_path == 'None': with open(os.path.normpath(self.imageName + '.json'), 'w') as outfile: image_data = { 'clickOffset': [self.offset_pos[0], self.offset_pos[1]] } json.dump(image_data, outfile, indent=4) else: with open( os.path.normpath(self.save_path + '/' + self.imageName + '.json'), 'w') as outfile: image_data = { 'clickOffset': [self.offset_pos[0], self.offset_pos[1]] } json.dump(image_data, outfile, indent=4) self.close() # If escape is pressed exit screenshot tool without saving elif key == QtCore.Qt.Key_Escape: self.close() def mousePressEvent(self, eventQMouseEvent): # If area is not defined for snipping, start the selection if self.area_defined == False: self.originQPoint = eventQMouseEvent.pos() self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self) self.currentQRubberBand.setGeometry( QtCore.QRect(self.originQPoint, QtCore.QSize())) self.currentQRubberBand.show() # If are is defined for snipping, show the green x for the offset elif self.area_defined == True: self.offset_label.move((eventQMouseEvent.pos().x() - self.offset_label.geometry().width()), (eventQMouseEvent.pos().y() - self.offset_label.geometry().height())) click_location = [ eventQMouseEvent.pos().x(), eventQMouseEvent.pos().y() ] self.offset_pos = [ (click_location[0] - self.selected_area_center[0]), (click_location[1] - self.selected_area_center[1]) ] def mouseMoveEvent(self, eventQMouseEvent): # If area not defined for snipping read the current mouse pointer position and redraw selection box if self.area_defined == False: self.currentQRubberBand.setGeometry( QtCore.QRect(self.originQPoint, eventQMouseEvent.pos()).normalized()) def mouseReleaseEvent(self, eventQMouseEvent): # If area is not defined crop the image to the defined selection box if self.area_defined == False: currentQRect = self.currentQRubberBand.geometry() self.selected_area_center = [ currentQRect.center().x(), currentQRect.center().y() ] self.cropQPixmap = self.image_label.pixmap().copy(currentQRect) self.area_defined = True def getImageName(self): """Pop up box with text input for the user to enter the new image's name. """ text, okPressed = QInputDialog.getText(self, "Get Image Name", "Type Image Name:", QLineEdit.Normal, "") if okPressed and text != '': self.imageName = text
class SlideViewer(QWidget): eventSignal = pyqtSignal(PyQt5.QtCore.QEvent) def __init__(self, parent: QWidget = None, viewer_top_else_left=True): super().__init__(parent) self.init_view() self.init_labels(word_wrap=viewer_top_else_left) self.init_layout(viewer_top_else_left) def init_view(self): self.scene = MyGraphicsScene() self.view = QGraphicsView() self.view.setScene(self.scene) self.view.setTransformationAnchor(QGraphicsView.NoAnchor) self.view.viewport().installEventFilter(self) self.rubber_band = QRubberBand(QRubberBand.Rectangle, self) self.mouse_press_view = QPoint() self.view.horizontalScrollBar().sliderMoved.connect( self.on_view_changed) self.view.verticalScrollBar().sliderMoved.connect(self.on_view_changed) self.scale_initializer_deffered_function = None self.slide_view_params = None self.slide_helper = None def init_labels(self, word_wrap): # word_wrap = True self.level_downsample_label = QLabel() self.level_downsample_label.setWordWrap(word_wrap) self.level_size_label = QLabel() self.level_size_label.setWordWrap(word_wrap) self.selected_rect_label = QLabel() self.selected_rect_label.setWordWrap(word_wrap) self.mouse_pos_scene_label = QLabel() self.mouse_pos_scene_label.setWordWrap(word_wrap) self.view_rect_scene_label = QLabel() self.view_rect_scene_label.setWordWrap(word_wrap) self.labels_layout = QVBoxLayout() self.labels_layout.setAlignment(Qt.AlignTop) self.labels_layout.addWidget(self.level_downsample_label) self.labels_layout.addWidget(self.level_size_label) self.labels_layout.addWidget(self.mouse_pos_scene_label) # self.labels_layout.addWidget(self.selected_rect_label) self.labels_layout.addWidget(self.view_rect_scene_label) def init_layout(self, viewer_top_else_left=True): main_layout = QVBoxLayout( self) if viewer_top_else_left else QHBoxLayout(self) main_layout.addWidget(self.view, ) main_layout.addLayout(self.labels_layout) # main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) """ If you want to start view frome some point at some level, specify <level> and <level_rect> params. level_rect : rect in dimensions of slide at level=level. If None - fits the whole size of slide """ def load(self, slide_view_params: SlideViewParams, preffered_rects_count=2000, zoom_step=1.15): self.zoom_step = zoom_step self.slide_view_params = slide_view_params self.slide_helper = SlideHelper(slide_view_params.slide_path) self.slide_graphics = SlideGraphicsGroup(slide_view_params, preffered_rects_count) self.scene.clear() self.scene.addItem(self.slide_graphics) if self.slide_view_params.level == -1 or self.slide_view_params.level is None: self.slide_view_params.level = self.slide_helper.get_max_level() self.slide_graphics.update_visible_level(self.slide_view_params.level) self.scene.setSceneRect( self.slide_helper.get_rect_for_level(self.slide_view_params.level)) def scale_initializer_deffered_function(): self.view.resetTransform() # print("size when loading: ", self.view.viewport().size()) if self.slide_view_params.level_rect: # self.view.fitInView(QRectF(*self.slide_view_params.level_rect), Qt.KeepAspectRatioByExpanding) self.view.fitInView(QRectF(*self.slide_view_params.level_rect), Qt.KeepAspectRatio) # print("after fit: ", self.get_current_view_scene_rect()) else: start_margins = QMarginsF(200, 200, 200, 200) start_image_rect_ = self.slide_helper.get_rect_for_level( self.slide_view_params.level) self.view.fitInView(start_image_rect_ + start_margins, Qt.KeepAspectRatio) self.scale_initializer_deffered_function = scale_initializer_deffered_function def eventFilter(self, qobj: 'QObject', event: QEvent): self.eventSignal.emit(event) event_processed = False # print("size when event: ", event, event.type(), self.view.viewport().size()) if isinstance(event, QShowEvent): """ we need it deffered because fitInView logic depends on current viewport size. Expecting at this point widget is finally resized before being shown at first """ if self.scale_initializer_deffered_function: # TODO labels start to occupy some space after view was already fitted, and labels will reduce size of viewport # self.update_labels() self.scale_initializer_deffered_function() self.on_view_changed() self.scale_initializer_deffered_function = None elif isinstance(event, QWheelEvent): event_processed = self.process_viewport_wheel_event(event) # we handle wheel event to prevent GraphicsView interpret it as scrolling elif isinstance(event, QMouseEvent): event_processed = self.process_mouse_event(event) return event_processed def process_viewport_wheel_event(self, event: QWheelEvent): # print("size when wheeling: ", self.view.viewport().size()) zoom_in = self.zoom_step zoom_out = 1 / zoom_in zoom_ = zoom_in if event.angleDelta().y() > 0 else zoom_out self.update_scale(event.pos(), zoom_) event.accept() self.on_view_changed() return True def process_mouse_event(self, event: QMouseEvent): if self.slide_helper is None: return False if event.button() == Qt.MiddleButton: if event.type() == QEvent.MouseButtonPress: self.slide_graphics.update_grid_visibility( not self.slide_graphics.slide_view_params.grid_visible) # items=self.scene.items() # QMessageBox.information(None, "Items", str(items)) return True # self.update_scale(QPoint(), 1.15) elif event.button() == Qt.LeftButton: if event.type() == QEvent.MouseButtonPress: self.mouse_press_view = QPoint(event.pos()) self.rubber_band.setGeometry( QRect(self.mouse_press_view, QSize())) self.rubber_band.show() return True elif event.type() == QEvent.MouseButtonRelease: self.rubber_band.hide() self.remember_selected_rect_params() self.slide_graphics.update_selected_rect_0_level( self.slide_view_params.selected_rect_0_level) self.update_labels() self.scene.invalidate() return True elif event.type() == QEvent.MouseMove: self.mouse_pos_scene_label.setText( "mouse_scene: " + point_to_str(self.view.mapToScene(event.pos()))) if not self.mouse_press_view.isNull(): self.rubber_band.setGeometry( QRect(self.mouse_press_view, event.pos()).normalized()) return True return False def remember_selected_rect_params(self): pos_scene = self.view.mapToScene(self.rubber_band.pos()) rect_scene = self.view.mapToScene( self.rubber_band.rect()).boundingRect() downsample = self.slide_helper.get_downsample_for_level( self.slide_view_params.level) selected_qrectf_0_level = QRectF(pos_scene * downsample, rect_scene.size() * downsample) self.slide_view_params.selected_rect_0_level = selected_qrectf_0_level.getRect( ) def update_scale(self, mouse_pos: QPoint, zoom): old_mouse_pos_scene = self.view.mapToScene(mouse_pos) old_view_scene_rect = self.view.mapToScene( self.view.viewport().rect()).boundingRect() old_level = self.get_best_level_for_scale( self.get_current_view_scale()) old_level_downsample = self.slide_helper.get_downsample_for_level( old_level) new_level = self.get_best_level_for_scale( self.get_current_view_scale() * zoom) new_level_downsample = self.slide_helper.get_downsample_for_level( new_level) level_scale_delta = 1 / (new_level_downsample / old_level_downsample) r = old_view_scene_rect.topLeft() m = old_mouse_pos_scene new_view_scene_rect_top_left = (m - (m - r) / zoom) * level_scale_delta new_view_scene_rect = QRectF( new_view_scene_rect_top_left, old_view_scene_rect.size() * level_scale_delta / zoom) new_scale = self.get_current_view_scale( ) * zoom * new_level_downsample / old_level_downsample transform = QTransform().scale(new_scale, new_scale).translate( -new_view_scene_rect.x(), -new_view_scene_rect.y()) new_rect = self.slide_helper.get_rect_for_level(new_level) self.scene.setSceneRect(new_rect) self.slide_view_params.level = new_level self.reset_view_transform() self.view.setTransform(transform, False) self.slide_graphics.update_visible_level(new_level) self.update_labels() def get_best_level_for_scale(self, scale): scene_width = self.scene.sceneRect().size().width() candidates = [0] for level in self.slide_helper.get_levels(): w, h = self.slide_helper.get_level_size(level) if scene_width * scale <= w: candidates.append(level) best_level = max(candidates) return best_level def update_labels(self): level_downsample = self.slide_helper.get_downsample_for_level( self.slide_view_params.level) level_size = self.slide_helper.get_level_size( self.slide_view_params.level) self.level_downsample_label.setText( "level, downsample: {}, {:.0f}".format( self.slide_view_params.level, level_downsample)) self.level_size_label.setText( "level_size: ({}, {})".format(*level_size)) self.view_rect_scene_label.setText( "view_scene: ({:.0f},{:.0f},{:.0f},{:.0f})".format( *self.get_current_view_scene_rect().getRect())) if self.slide_view_params.selected_rect_0_level: self.selected_rect_label.setText( "selected rect (0-level): ({:.0f},{:.0f},{:.0f},{:.0f})". format(*self.slide_view_params.selected_rect_0_level)) def on_view_changed(self): if self.scale_initializer_deffered_function is None and self.slide_view_params: self.slide_view_params.level_rect = self.get_current_view_scene_rect( ).getRect() self.update_labels() def reset_view_transform(self): self.view.resetTransform() self.view.horizontalScrollBar().setValue(0) self.view.verticalScrollBar().setValue(0) def get_current_view_scene_rect(self): return self.view.mapToScene(self.view.viewport().rect()).boundingRect() def get_current_view_scale(self): scale = self.view.transform().m11() return scale
class PieView(QAbstractItemView): def __init__(self, parent=None): super(PieView, self).__init__(parent) self.horizontalScrollBar().setRange(0, 0) self.verticalScrollBar().setRange(0, 0) self.margin = 8 self.totalSize = 300 self.pieSize = self.totalSize - 2 * self.margin self.validItems = 0 self.totalValue = 0.0 self.origin = QPoint() self.rubberBand = None def dataChanged(self, topLeft, bottomRight, roles): super(PieView, self).dataChanged(topLeft, bottomRight, roles) self.validItems = 0 self.totalValue = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 self.viewport().update() def edit(self, index, trigger, event): if index.column() == 0: return super(PieView, self).edit(index, trigger, event) else: return False def indexAt(self, point): if self.validItems == 0: return QModelIndex() # Transform the view coordinates into contents widget coordinates. wx = point.x() + self.horizontalScrollBar().value() wy = point.y() + self.verticalScrollBar().value() if wx < self.totalSize: cx = wx - self.totalSize / 2 cy = self.totalSize / 2 - wy # positive cy for items above the center # Determine the distance from the center point of the pie chart. d = (cx**2 + cy**2)**0.5 if d == 0 or d > self.pieSize / 2: return QModelIndex() # Determine the angle of the point. angle = (180 / math.pi) * math.acos(cx / d) if cy < 0: angle = 360 - angle # Find the relevant slice of the pie. startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: sliceAngle = 360 * value / self.totalValue if angle >= startAngle and angle < (startAngle + sliceAngle): return self.model().index(row, 1, self.rootIndex()) startAngle += sliceAngle else: itemHeight = QFontMetrics(self.viewOptions().font).height() listItem = int((wy - self.margin) / itemHeight) validRow = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) if self.model().data(index) > 0.0: if listItem == validRow: return self.model().index(row, 0, self.rootIndex()) # Update the list index that corresponds to the next valid # row. validRow += 1 return QModelIndex() def isIndexHidden(self, index): return False def itemRect(self, index): if not index.isValid(): return QRect() # Check whether the index's row is in the list of rows represented # by slices. if index.column() != 1: valueIndex = self.model().index(index.row(), 1, self.rootIndex()) else: valueIndex = index if self.model().data(valueIndex) > 0.0: listItem = 0 for row in range(index.row() - 1, -1, -1): if self.model().data(self.model().index( row, 1, self.rootIndex())) > 0.0: listItem += 1 if index.column() == 0: itemHeight = QFontMetrics(self.viewOptions().font).height() return QRect(self.totalSize, int(self.margin + listItem * itemHeight), self.totalSize - self.margin, int(itemHeight)) elif index.column() == 1: return self.viewport().rect() return QRect() def itemRegion(self, index): if not index.isValid(): return QRegion() if index.column() != 1: return QRegion(self.itemRect(index)) if self.model().data(index) <= 0.0: return QRegion() startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): sliceIndex = self.model().index(row, 1, self.rootIndex()) value = self.model().data(sliceIndex) if value > 0.0: angle = 360 * value / self.totalValue if sliceIndex == index: slicePath = QPainterPath() slicePath.moveTo(self.totalSize / 2, self.totalSize / 2) slicePath.arcTo(self.margin, self.margin, self.margin + self.pieSize, self.margin + self.pieSize, startAngle, angle) slicePath.closeSubpath() return QRegion(slicePath.toFillPolygon().toPolygon()) startAngle += angle return QRegion() def horizontalOffset(self): return self.horizontalScrollBar().value() def mousePressEvent(self, event): super(PieView, self).mousePressEvent(event) self.origin = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if self.rubberBand: self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) super(PieView, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): super(PieView, self).mouseReleaseEvent(event) if self.rubberBand: self.rubberBand.hide() self.viewport().update() def moveCursor(self, cursorAction, modifiers): current = self.currentIndex() if cursorAction in (QAbstractItemView.MoveLeft, QAbstractItemView.MoveUp): if current.row() > 0: current = self.model().index(current.row() - 1, current.column(), self.rootIndex()) else: current = self.model().index(0, current.column(), self.rootIndex()) elif cursorAction in (QAbstractItemView.MoveRight, QAbstractItemView.MoveDown): if current.row() < self.rows(current) - 1: current = self.model().index(current.row() + 1, current.column(), self.rootIndex()) else: current = self.model().index( self.rows(current) - 1, current.column(), self.rootIndex()) self.viewport().update() return current def paintEvent(self, event): selections = self.selectionModel() option = self.viewOptions() state = option.state background = option.palette.base() foreground = QPen(option.palette.color(QPalette.WindowText)) textPen = QPen(option.palette.color(QPalette.Text)) highlightedPen = QPen(option.palette.color(QPalette.HighlightedText)) painter = QPainter(self.viewport()) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(event.rect(), background) painter.setPen(foreground) # Viewport rectangles pieRect = QRect(self.margin, self.margin, self.pieSize, self.pieSize) keyPoint = QPoint(self.totalSize - self.horizontalScrollBar().value(), self.margin - self.verticalScrollBar().value()) if self.validItems > 0: painter.save() painter.translate(pieRect.x() - self.horizontalScrollBar().value(), pieRect.y() - self.verticalScrollBar().value()) painter.drawEllipse(0, 0, self.pieSize, self.pieSize) startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: angle = 360 * value / self.totalValue colorIndex = self.model().index(row, 0, self.rootIndex()) color = self.model().data(colorIndex, Qt.DecorationRole) if self.currentIndex() == index: painter.setBrush(QBrush(color, Qt.Dense4Pattern)) elif selections.isSelected(index): painter.setBrush(QBrush(color, Qt.Dense3Pattern)) else: painter.setBrush(QBrush(color)) painter.drawPie(0, 0, self.pieSize, self.pieSize, int(startAngle * 16), int(angle * 16)) startAngle += angle painter.restore() keyNumber = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: labelIndex = self.model().index(row, 0, self.rootIndex()) option = self.viewOptions() option.rect = self.visualRect(labelIndex) if selections.isSelected(labelIndex): option.state |= QStyle.State_Selected if self.currentIndex() == labelIndex: option.state |= QStyle.State_HasFocus self.itemDelegate().paint(painter, option, labelIndex) keyNumber += 1 def resizeEvent(self, event): self.updateGeometries() def rows(self, index): return self.model().rowCount(self.model().parent(index)) def rowsInserted(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 super(PieView, self).rowsInserted(parent, start, end) def rowsAboutToBeRemoved(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue -= value self.validItems -= 1 super(PieView, self).rowsAboutToBeRemoved(parent, start, end) def scrollContentsBy(self, dx, dy): self.viewport().scroll(dx, dy) def scrollTo(self, index, ScrollHint): area = self.viewport().rect() rect = self.visualRect(index) if rect.left() < area.left(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + rect.left() - area.left()) elif rect.right() > area.right(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + min(rect.right() - area.right(), rect.left() - area.left())) if rect.top() < area.top(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + rect.top() - area.top()) elif rect.bottom() > area.bottom(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + min(rect.bottom() - area.bottom(), rect.top() - area.top())) def setSelection(self, rect, command): # Use content widget coordinates because we will use the itemRegion() # function to check for intersections. contentsRect = rect.translated( self.horizontalScrollBar().value(), self.verticalScrollBar().value()).normalized() rows = self.model().rowCount(self.rootIndex()) columns = self.model().columnCount(self.rootIndex()) indexes = [] for row in range(rows): for column in range(columns): index = self.model().index(row, column, self.rootIndex()) region = self.itemRegion(index) if not region.intersect(QRegion(contentsRect)).isEmpty(): indexes.append(index) if len(indexes) > 0: firstRow = indexes[0].row() lastRow = indexes[0].row() firstColumn = indexes[0].column() lastColumn = indexes[0].column() for i in range(1, len(indexes)): firstRow = min(firstRow, indexes[i].row()) lastRow = max(lastRow, indexes[i].row()) firstColumn = min(firstColumn, indexes[i].column()) lastColumn = max(lastColumn, indexes[i].column()) selection = QItemSelection( self.model().index(firstRow, firstColumn, self.rootIndex()), self.model().index(lastRow, lastColumn, self.rootIndex())) self.selectionModel().select(selection, command) else: noIndex = QModelIndex() selection = QItemSelection(noIndex, noIndex) self.selectionModel().select(selection, command) self.update() def updateGeometries(self): self.horizontalScrollBar().setPageStep(self.viewport().width()) self.horizontalScrollBar().setRange( 0, max(0, 2 * self.totalSize - self.viewport().width())) self.verticalScrollBar().setPageStep(self.viewport().height()) self.verticalScrollBar().setRange( 0, max(0, self.totalSize - self.viewport().height())) def verticalOffset(self): return self.verticalScrollBar().value() def visualRect(self, index): rect = self.itemRect(index) if rect.isValid(): return QRect(rect.left() - self.horizontalScrollBar().value(), rect.top() - self.verticalScrollBar().value(), rect.width(), rect.height()) else: return rect def visualRegionForSelection(self, selection): region = QRegion() for span in selection: for row in range(span.top(), span.bottom() + 1): for col in range(span.left(), span.right() + 1): index = self.model().index(row, col, self.rootIndex()) region += self.visualRect(index) return region
class ResizableRubberBand(QWidget): def __init__(self, parent=None): super(ResizableRubberBand, self).__init__(parent) self.draggable = True self.dragging_threshold = 0 self.mousePressPos = None self.mouseMovePos = None self.borderRadius = 5 self.setWindowFlags(Qt.SubWindow) layout = QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) self.grip2 = QSizeGrip(self) self.grip2.setFixedSize(15, 15) layout.addWidget(self.grip2, 0, Qt.AlignRight | Qt.AlignBottom) self.band = QRubberBand(QRubberBand.Rectangle, self) self.band.show() self.show() def resizeEvent(self, event): # Note: resizing from a top left grip creates loop rect = self.geometry() side = min(rect.width(), rect.height()) self.band.setGeometry(0, 0, side, side) self.setGeometry(self.x(), self.y(), side, side) def paintEvent(self, event): # Get current window size window_size = self.size() qp = QPainter() qp.begin(self) qp.setRenderHint(QPainter.Antialiasing, True) side = min(window_size.width(), window_size.height()) qp.drawRoundedRect(0, 0, window_size.width(), window_size.height(), self.borderRadius, self.borderRadius) qp.end() def mousePressEvent(self, event): if self.draggable and event.button() == Qt.LeftButton: self.mousePressPos = event.globalPos() # global self.mouseMovePos = event.globalPos() - self.pos() # local super(ResizableRubberBand, self).mousePressEvent(event) def mouseMoveEvent(self, event): if self.draggable and event.buttons() & Qt.LeftButton: globalPos = event.globalPos() moved = globalPos - self.mousePressPos if moved.manhattanLength() > self.dragging_threshold: # Move when user drag window more than dragging_threshold diff = globalPos - self.mouseMovePos diffNew = QPoint( max( 0, min( diff.x(), self.parent().geometry().width() - self.size().width())), max( 0, min( diff.y(), self.parent().geometry().height() - self.size().height()))) self.move(diffNew) self.mouseMovePos = globalPos - self.pos() super(ResizableRubberBand, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): if self.mousePressPos is not None: if event.button() == Qt.LeftButton: moved = event.globalPos() - self.mousePressPos if moved.manhattanLength() > self.dragging_threshold: # Do not call click event or so on event.ignore() self.mousePressPos = None super(ResizableRubberBand, self).mouseReleaseEvent(event)
class PieView(QAbstractItemView): def __init__(self, parent=None): super(PieView, self).__init__(parent) self.horizontalScrollBar().setRange(0, 0) self.verticalScrollBar().setRange(0, 0) self.margin = 8 self.totalSize = 300 self.pieSize = self.totalSize - 2*self.margin self.validItems = 0 self.totalValue = 0.0 self.origin = QPoint() self.rubberBand = None def dataChanged(self, topLeft, bottomRight, roles): super(PieView, self).dataChanged(topLeft, bottomRight, roles) self.validItems = 0 self.totalValue = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 self.viewport().update() def edit(self, index, trigger, event): if index.column() == 0: return super(PieView, self).edit(index, trigger, event) else: return False def indexAt(self, point): if self.validItems == 0: return QModelIndex() # Transform the view coordinates into contents widget coordinates. wx = point.x() + self.horizontalScrollBar().value() wy = point.y() + self.verticalScrollBar().value() if wx < self.totalSize: cx = wx - self.totalSize/2 cy = self.totalSize/2 - wy; # positive cy for items above the center # Determine the distance from the center point of the pie chart. d = (cx**2 + cy**2)**0.5 if d == 0 or d > self.pieSize/2: return QModelIndex() # Determine the angle of the point. angle = (180 / math.pi) * math.acos(cx/d) if cy < 0: angle = 360 - angle # Find the relevant slice of the pie. startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: sliceAngle = 360*value/self.totalValue if angle >= startAngle and angle < (startAngle + sliceAngle): return self.model().index(row, 1, self.rootIndex()) startAngle += sliceAngle else: itemHeight = QFontMetrics(self.viewOptions().font).height() listItem = int((wy - self.margin) / itemHeight) validRow = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) if self.model().data(index) > 0.0: if listItem == validRow: return self.model().index(row, 0, self.rootIndex()) # Update the list index that corresponds to the next valid # row. validRow += 1 return QModelIndex() def isIndexHidden(self, index): return False def itemRect(self, index): if not index.isValid(): return QRect() # Check whether the index's row is in the list of rows represented # by slices. if index.column() != 1: valueIndex = self.model().index(index.row(), 1, self.rootIndex()) else: valueIndex = index if self.model().data(valueIndex) > 0.0: listItem = 0 for row in range(index.row()-1, -1, -1): if self.model().data(self.model().index(row, 1, self.rootIndex())) > 0.0: listItem += 1 if index.column() == 0: itemHeight = QFontMetrics(self.viewOptions().font).height() return QRect(self.totalSize, int(self.margin + listItem*itemHeight), self.totalSize - self.margin, int(itemHeight)) elif index.column() == 1: return self.viewport().rect() return QRect() def itemRegion(self, index): if not index.isValid(): return QRegion() if index.column() != 1: return QRegion(self.itemRect(index)) if self.model().data(index) <= 0.0: return QRegion() startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): sliceIndex = self.model().index(row, 1, self.rootIndex()) value = self.model().data(sliceIndex) if value > 0.0: angle = 360*value/self.totalValue if sliceIndex == index: slicePath = QPainterPath() slicePath.moveTo(self.totalSize/2, self.totalSize/2) slicePath.arcTo(self.margin, self.margin, self.margin+self.pieSize, self.margin+self.pieSize, startAngle, angle) slicePath.closeSubpath() return QRegion(slicePath.toFillPolygon().toPolygon()) startAngle += angle return QRegion() def horizontalOffset(self): return self.horizontalScrollBar().value() def mousePressEvent(self, event): super(PieView, self).mousePressEvent(event) self.origin = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if self.rubberBand: self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) super(PieView, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): super(PieView, self).mouseReleaseEvent(event) if self.rubberBand: self.rubberBand.hide() self.viewport().update() def moveCursor(self, cursorAction, modifiers): current = self.currentIndex() if cursorAction in (QAbstractItemView.MoveLeft, QAbstractItemView.MoveUp): if current.row() > 0: current = self.model().index(current.row() - 1, current.column(), self.rootIndex()) else: current = self.model().index(0, current.column(), self.rootIndex()) elif cursorAction in (QAbstractItemView.MoveRight, QAbstractItemView.MoveDown): if current.row() < self.rows(current) - 1: current = self.model().index(current.row() + 1, current.column(), self.rootIndex()) else: current = self.model().index(self.rows(current) - 1, current.column(), self.rootIndex()) self.viewport().update() return current def paintEvent(self, event): selections = self.selectionModel() option = self.viewOptions() state = option.state background = option.palette.base() foreground = QPen(option.palette.color(QPalette.WindowText)) textPen = QPen(option.palette.color(QPalette.Text)) highlightedPen = QPen(option.palette.color(QPalette.HighlightedText)) painter = QPainter(self.viewport()) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(event.rect(), background) painter.setPen(foreground) # Viewport rectangles pieRect = QRect(self.margin, self.margin, self.pieSize, self.pieSize) keyPoint = QPoint(self.totalSize - self.horizontalScrollBar().value(), self.margin - self.verticalScrollBar().value()) if self.validItems > 0: painter.save() painter.translate(pieRect.x() - self.horizontalScrollBar().value(), pieRect.y() - self.verticalScrollBar().value()) painter.drawEllipse(0, 0, self.pieSize, self.pieSize) startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: angle = 360*value/self.totalValue colorIndex = self.model().index(row, 0, self.rootIndex()) color = self.model().data(colorIndex, Qt.DecorationRole) if self.currentIndex() == index: painter.setBrush(QBrush(color, Qt.Dense4Pattern)) elif selections.isSelected(index): painter.setBrush(QBrush(color, Qt.Dense3Pattern)) else: painter.setBrush(QBrush(color)) painter.drawPie(0, 0, self.pieSize, self.pieSize, int(startAngle*16), int(angle*16)) startAngle += angle painter.restore() keyNumber = 0 for row in range(self.model().rowCount(self.rootIndex())): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value > 0.0: labelIndex = self.model().index(row, 0, self.rootIndex()) option = self.viewOptions() option.rect = self.visualRect(labelIndex) if selections.isSelected(labelIndex): option.state |= QStyle.State_Selected if self.currentIndex() == labelIndex: option.state |= QStyle.State_HasFocus self.itemDelegate().paint(painter, option, labelIndex) keyNumber += 1 def resizeEvent(self, event): self.updateGeometries() def rows(self, index): return self.model().rowCount(self.model().parent(index)) def rowsInserted(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue += value self.validItems += 1 super(PieView, self).rowsInserted(parent, start, end) def rowsAboutToBeRemoved(self, parent, start, end): for row in range(start, end + 1): index = self.model().index(row, 1, self.rootIndex()) value = self.model().data(index) if value is not None and value > 0.0: self.totalValue -= value self.validItems -= 1 super(PieView, self).rowsAboutToBeRemoved(parent, start, end) def scrollContentsBy(self, dx, dy): self.viewport().scroll(dx, dy) def scrollTo(self, index, ScrollHint): area = self.viewport().rect() rect = self.visualRect(index) if rect.left() < area.left(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + rect.left() - area.left()) elif rect.right() > area.right(): self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + min( rect.right() - area.right(), rect.left() - area.left())) if rect.top() < area.top(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + rect.top() - area.top()) elif rect.bottom() > area.bottom(): self.verticalScrollBar().setValue( self.verticalScrollBar().value() + min( rect.bottom() - area.bottom(), rect.top() - area.top())) def setSelection(self, rect, command): # Use content widget coordinates because we will use the itemRegion() # function to check for intersections. contentsRect = rect.translated(self.horizontalScrollBar().value(), self.verticalScrollBar().value()).normalized() rows = self.model().rowCount(self.rootIndex()) columns = self.model().columnCount(self.rootIndex()) indexes = [] for row in range(rows): for column in range(columns): index = self.model().index(row, column, self.rootIndex()) region = self.itemRegion(index) if not region.intersect(QRegion(contentsRect)).isEmpty(): indexes.append(index) if len(indexes) > 0: firstRow = indexes[0].row() lastRow = indexes[0].row() firstColumn = indexes[0].column() lastColumn = indexes[0].column() for i in range(1, len(indexes)): firstRow = min(firstRow, indexes[i].row()) lastRow = max(lastRow, indexes[i].row()) firstColumn = min(firstColumn, indexes[i].column()) lastColumn = max(lastColumn, indexes[i].column()) selection = QItemSelection( self.model().index(firstRow, firstColumn, self.rootIndex()), self.model().index(lastRow, lastColumn, self.rootIndex())) self.selectionModel().select(selection, command) else: noIndex = QModelIndex() selection = QItemSelection(noIndex, noIndex) self.selectionModel().select(selection, command) self.update() def updateGeometries(self): self.horizontalScrollBar().setPageStep(self.viewport().width()) self.horizontalScrollBar().setRange(0, max(0, 2*self.totalSize - self.viewport().width())) self.verticalScrollBar().setPageStep(self.viewport().height()) self.verticalScrollBar().setRange(0, max(0, self.totalSize - self.viewport().height())) def verticalOffset(self): return self.verticalScrollBar().value() def visualRect(self, index): rect = self.itemRect(index) if rect.isValid(): return QRect(rect.left() - self.horizontalScrollBar().value(), rect.top() - self.verticalScrollBar().value(), rect.width(), rect.height()) else: return rect def visualRegionForSelection(self, selection): region = QRegion() for span in selection: for row in range(span.top(), span.bottom() + 1): for col in range(span.left(), span.right() + 1): index = self.model().index(row, col, self.rootIndex()) region += self.visualRect(index) return region
class ImageCropperDropper(QLabel): '''A QLabel that displays a rectangle when drawing a rectangle with the mouse''' cropped = Signal(QPixmap) fileDropped = Signal(QUrl) def __init__(self, mainwin): QLabel.__init__(self) self.setAcceptDrops(True) self.marker = QRubberBand(QRubberBand.Rectangle, self) self.markOrigin = self.markEnd = None self.setContextMenuPolicy(Qt.ActionsContextMenu) self.addAction(mainwin.cropAction) self.addAction(mainwin.saveAction) def setPixmap(self, pix): QLabel.setPixmap(self, pix) self.resize(pix.size()) self.marker.hide() self.markOrigin = self.markEnd = None @Slot() def doCrop(self): '''Crop the pixmap using the user-drawn rectangle, emits cropped(QPixmap) signal''' if not self.markEnd: QMessageBox.warning(self, 'Error', 'Select a region to crop first') return cropzone = self._makeRect(self.markOrigin, self.markEnd) croppedpix = self.pixmap().copy(cropzone) self.setPixmap(croppedpix) self.cropped.emit(croppedpix) def _makeRect(self, p1, p2): '''Make a QRect based on QPoints p1 and p2. The 2 points must be 2 corners but don't need to be upper-left&lower-right''' x1, x2 = min(p1.x(), p2.x()), max(p1.x(), p2.x()) y1, y2 = min(p1.y(), p2.y()), max(p1.y(), p2.y()) return QRect().adjusted(x1, y1, x2, y2) def mouseMoveEvent(self, ev): if ev.buttons() != Qt.LeftButton: return QLabel.mouseMoveEvent(self, ev) self.markEnd = ev.pos() diffpoint = self.markEnd - self.markOrigin #~ self.marker.resize(diffpoint.x(), diffpoint.y()) self.marker.setGeometry(self._makeRect(self.markOrigin, self.markEnd)) #~ ev.accept() def mousePressEvent(self, ev): if ev.button() != Qt.LeftButton: return QLabel.mousePressEvent(self, ev) self.markOrigin = ev.pos() self.marker.move(ev.pos()) self.marker.resize(QSize()) self.marker.show() #~ ev.accept() def dragEnterEvent(self, ev): if ev.mimeData().hasUrls(): ev.setDropAction(Qt.CopyAction) ev.accept() def dropEvent(self, ev): if ev.mimeData().hasUrls(): ev.setDropAction(Qt.CopyAction) ev.accept() self.fileDropped.emit(ev.mimeData().urls()[0])
class DragWidget(QWidget): spacerX = 16 spacerY = 16 clipicon = None new_window_signal = pyqtSignal(str) query = pyqtSignal() src_dragwidget = None src_selected = [] def __init__(self, path, parent=None): super(DragWidget, self).__init__(parent) self.setMinimumSize(400, 200) self.setAcceptDrops(True) self.parent = parent # self.parent.menu.connect(self.delete_icon) self.modifier = False self.rubberband = QRubberBand(QRubberBand.Rectangle, self) self.path = path self.icons = [] self.icon_offsetx = 0 self.icon_offsety = 0 # self.clipicon = None # self.moving_icons = [] self.read_drawer() self.clean_up() # print(type(IconWidget.icon)) # print(self.findChildren(ClickableIcon)) def read_drawer(self): # self.icons.clear() for item in os.scandir(self.path): if item.is_dir(): icon_widget = IconWidget(parent=self, name=item.name, path=self.path, dir=True) else: icon_widget = IconWidget(parent=self, name=item.name, path=self.path, dir=False) icon_widget.new_window.connect(self.new_window_signal.emit) icon_widget.clipboard.connect(self.on_clipboard) self.icons.append(icon_widget) self.icons[-1].setAttribute(Qt.WA_DeleteOnClose) # self.update() def updateScrollArea(self): """ set the dimension of the widget """ iconx = [] icony = [] if len(self.icons) > 0: for item in self.icons: iconx.append(item.x()) icony.append(item.y()) self.setMinimumWidth(max(iconx)+75) self.setMinimumHeight(max(icony)+75) def dragEnterEvent(self, event): event.accept() def dragMoveEvent(self, event): event.accept() def get_dnd_list(self, event): icon_list = [] icon_offsetx = None icon_offsety = None if len(DragWidget.src_selected) > 0: for item in DragWidget.src_selected: icon_list.append(item) else: icon_list.append(event.source()) return icon_list def create_icon(self, name, drawer): if drawer: icon_widget = IconWidget(self, name=name, path=self.path, dir=True) else: icon_widget = IconWidget(self, name=name, path=self.path, dir=False) icon_widget.new_window.connect(self.new_window_signal.emit) self.icons.append(icon_widget) def place_icon(self, x, y): self.icons[-1].move(x, y) self.icons[-1].show() def dropEvent(self, event): event.accept() icon_list = self.get_dnd_list(event) icon_offsetx = event.pos().x() icon_offsety = event.pos().y() for item in icon_list: name = item.name drawer = item.drawer src_path = item.path + "/" + name dst_path = self.path + "/" if event.mimeData().hasFormat("application/x-icon"): self.create_icon(name, drawer) self.move_data(src_path, dst_path) self.place_icon(icon_offsetx, icon_offsety) icon_offsetx += 100 if icon_offsetx > self.window().width(): icon_offsetx = event.pos().x() icon_offsety += 75 icon_offsetx = None icon_offsety = None self.updateScrollArea() def clear_dnd(self): DragWidget.src_dragwidget = None DragWidget.src_selected.clear() def get_modifier(self): return self.parent.modifier def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: for item in self.icons: item.icon.deselect_icon() self.clear_dnd() self.origin = event.pos() self.rubberband.setGeometry(QRect(self.origin, QSize())) self.rubberband.show() def mouseMoveEvent(self, event): if self.rubberband.isVisible(): self.rubberband.setGeometry( QRect(self.origin, event.pos()).normalized()) # QWidget.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): self.clear_dnd() if self.rubberband.isVisible(): self.rubberband.hide() rect = self.rubberband.geometry() for child in self.findChildren(IconWidget): if rect.intersects(child.geometry()): child.icon.select_icon() DragWidget.src_selected.append(child) if DragWidget.src_dragwidget is not self: DragWidget.src_dragwidget = self def mouseDoubleClickEvent(self, event): print(BLU, "Double Click", END) self.query.emit() def create_file(self): new_file = self.path + "/" + "newfile.txt" open(new_file, 'w').close() icon_widget = IconWidget(self, name="newfile.txt", path=self.path, dir=False) icon_widget.new_window.connect(self.new_window_signal.emit) icon_widget.show() self.icons.append(icon_widget) def create_drawer(self): print("creating new drawer") new_drawer = self.path + "/" + "NewDrawer" os.makedirs(new_drawer) icon_widget = IconWidget(self, name="NewDrawer", path=self.path, dir=True) icon_widget.new_window.connect(self.new_window_signal.emit) icon_widget.show() self.icons.append(icon_widget) def rename_file(self): print("renaming file") def clean_up(self): for item in self.icons: item.move(DragWidget.spacerX, DragWidget.spacerY) # initial icon placement DragWidget.spacerX += 100 if DragWidget.spacerX + 100 > self.window().width(): DragWidget.spacerY += 75 DragWidget.spacerX = 16 # reset placement values DragWidget.spacerX = 16 DragWidget.spacerY = 16 self.updateScrollArea() def move_data(self, source, dest): srce_path = source.rsplit('/', 1)[0] dest_path = dest.rsplit('/', 1)[0] if srce_path != dest_path: try: shutil.move(source, dest) except Exception as err: print(err) def copy_icon(self, source, dest): pass def delete_icon(self): dest = os.path.expanduser("~") + "/.Trash/" error_string = "" for item in self.icons: if item.icon.selected: source = item.path + "/" + item.name if source is not "": try: shutil.move(source, dest) except Exception as err: error_string += str(err) + "\n" + "\n" else: self.icons.remove(item) item.deleteLater() if error_string is not "": QMessageBox.information(self, 'Info', error_string, QMessageBox.Ok) def paste_icon(self): print("---") print("srce=", self.clipicon.path + "/" + self.clipicon.name) # print("res=", self.clipicon.path + "/" + self.clipicon.name) print("dest=", self.path + "/") # if os.path.isdir(os.path.join(self.clipicon.path, self.clipicon.name)): SRCE = self.clipicon.path + "/" + self.clipicon.name DEST = self.path+"/" + self.clipicon.name shutil.copytree(SRCE, DEST) def on_clipboard(self, icon): print("realpath", self.path) print("clip_icon_name=", icon.name) DragWidget.clipicon = icon
class ImageView(QGraphicsView): @staticmethod def close_enough(point1, point2): d = 20 return abs(point1.x() - point2.x()) < d and abs(point1.y() - point2.y()) < d def __init__(self, parent=None): QGraphicsView.__init__(self, parent) self.go_prev_img = parent.go_prev_img self.go_next_img = parent.go_next_img pal = self.palette() pal.setColor(self.backgroundRole(), Qt.black) self.setPalette(pal) self.setFrameShape(QFrame.NoFrame) self.rband = None self.rband_state = None self.rband_corner = None # If mouse is over a corner self.rband_origin = QPoint() self.rband_endpoint = QPoint() def mousePressEvent(self, event): """Go to the next / previous image, or be able to drag the image with a hand.""" if self.rband_state == "initial": self.rband = QRubberBand(QRubberBand.Rectangle, self) self.rband_origin = event.pos() self.rband.setGeometry(QRect(self.rband_origin, QSize())) self.rband.show() self.rband_state = "set-endpoint" elif self.rband_state == "drawn": if self.rband_corner == "nw": self.rband_state = "set-origin" elif self.rband_corner == "se": self.rband_state = "set-endpoint" elif self.rband_corner == "inside": self.rband_state = "move" self.setCursor(QCursor(Qt.ClosedHandCursor)) self.rband_previous_pos = event.pos() else: if event.button() == Qt.LeftButton: x = event.x() if x < 100: self.go_prev_img() elif x > self.width() - 100: self.go_next_img() else: self.setDragMode(QGraphicsView.ScrollHandDrag) QGraphicsView.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self.rband_state == "set-endpoint": self.rband.setGeometry( QRect(self.rband_origin, event.pos()).normalized()) self.rband_endpoint = event.pos() elif self.rband_state == "set-origin": self.rband.setGeometry( QRect(event.pos(), self.rband_endpoint).normalized()) self.rband_origin = event.pos() elif self.rband_state == "move": old_pos = self.rband.geometry() new_pos = old_pos.translated(event.pos() - self.rband_previous_pos) trace(0) self.rband.setGeometry(new_pos) self.rband_previous_pos = event.pos() elif self.rband_state == "drawn": if ImageView.close_enough(self.rband_origin, event.pos()): self.rband_corner = "nw" self.setCursor(QCursor(Qt.SizeFDiagCursor)) elif ImageView.close_enough(self.rband_endpoint, event.pos()): self.rband_corner = "se" self.setCursor(QCursor(Qt.SizeFDiagCursor)) elif self.rband.geometry().contains(event.pos()): self.rband_corner = "inside" self.setCursor(QCursor(Qt.OpenHandCursor)) else: self.rband_corner = None self.setCursor(QCursor(Qt.ArrowCursor)) QGraphicsView.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): #print("State %s", self.rband_state) if self.rband_state == "set-endpoint" or self.rband_state == "set-origin": self.rband_state = "drawn" elif self.rband_state == "move": self.setCursor(QCursor(Qt.ArrowCursor)) self.rband_state = "drawn" self.rband_origin = self.rband.geometry().topLeft() self.rband_endpoint = self.rband.geometry().bottomRight() else: self.setCursor(QCursor(Qt.ArrowCursor)) self.setDragMode(QGraphicsView.NoDrag) QGraphicsView.mouseReleaseEvent(self, event) def keyPressEvent(self, event): if self.rband_state == "drawn": if event.key() == Qt.Key_Escape: self.setCursor(QCursor(Qt.ArrowCursor)) self.rband.hide() self.rband_state = None self.setMouseTracking(False) elif event.key() in [Qt.Key_Return, Qt.Key_Enter, Qt.Key_Space]: self.setCursor(QCursor(Qt.ArrowCursor)) self.rband.hide() self.rband_state = None self.setMouseTracking(False) #print("CB ", self.get_coords()) self.crop_callback(self.get_coords()) event.accept() def zoom(self, zoomratio): self.scale(zoomratio, zoomratio) def wheelEvent(self, event): zoomratio = 1.1 if event.angleDelta().y() < 0: zoomratio = 1.0 / zoomratio self.scale(zoomratio, zoomratio) def crop(self, callback): self.crop_callback = callback self.rband_state = "initial" self.setMouseTracking(True) def get_coords(self): rect = self.rband.geometry() size = self.mapToScene(rect).boundingRect() x = int(size.x()) y = int(size.y()) width = int(size.width()) height = int(size.height()) return (x, y, width, height)
class FrameLess(QObject): def __init__(self, parent): super(FrameLess, self).__init__(parent) self._parent = parent self._cursorChanged = False self._leftButtonPressed = False self._mouseMove = Edge.NoEdge self._mousePress = Edge.NoEdge self._borderWidth = 5 self._rubberBand = QRubberBand(QRubberBand.Rectangle) self._parent.setWindowFlags(Qt.FramelessWindowHint | Qt.CustomizeWindowHint | Qt.Window) self._parent.setAttribute(Qt.WA_Hover) self._parent.setMouseTracking(True) self._parent.installEventFilter(self) def eventFilter(self, obj, event): if event.type() == QEvent.MouseMove: self.__mouseMove(QMouseEvent(event)) return True else: if event.type() == QEvent.Leave: self.__mouseLeave(event) return True else: if event.type() == QEvent.HoverMove: self.__mouseHover(QHoverEvent(event)) return True else: if event.type() == QEvent.MouseButtonPress: self.__mousePress(QMouseEvent(event)) return True else: if event.type() == QEvent.MouseButtonRelease: self.__mouseRelease(QMouseEvent(event)) return True else: return False def __mouseHover(self, event): self.__updateCursorShape(self._parent.mapToGlobal(event.pos())) def __mouseLeave(self, event): if not self._leftButtonPressed: self._parent.unsetCursor() def __mousePress(self, event): if event.button() == Qt.LeftButton: self._leftButtonPressed = True self._mousePress = self.__calculateCursorPosition(event.globalPos(), self._parent.frameGeometry()) if self._mousePress != Edge.NoEdge: self._rubberBand.setGeometry(self._parent.frameGeometry()) def __mouseRelease(self, event): if event.button() == Qt.LeftButton: self._leftButtonPressed = False def __mouseMove(self, event): if self._leftButtonPressed: if self._mousePress != Edge.NoEdge: left = self._rubberBand.frameGeometry().left() top = self._rubberBand.frameGeometry().top() right = self._rubberBand.frameGeometry().right() bottom = self._rubberBand.frameGeometry().bottom() if self._mousePress == Edge.Top: top = event.globalPos().y() else: if self._mousePress == Edge.Bottom: bottom = event.globalPos().y() else: if self._mousePress == Edge.Right: right = event.globalPos().x() else: if self._mousePress == Edge.Left: left = event.globalPos().x() else: if self._mousePress == Edge.TopRight: top = event.globalPos().y() right = event.globalPos().x() else: if self._mousePress == Edge.TopLeft: top = event.globalPos().y() left = event.globalPos().x() else: if self._mousePress == Edge.BottomLeft: bottom = event.globalPos().y() left = event.globalPos().x() else: if self._mousePress == Edge.BottomRight: bottom = event.globalPos().y() right = event.globalPos().x() newRect = QRect(QPoint(left, top), QPoint(right, bottom)) if newRect.width() < self._parent.minimumWidth(): left = self.frameGeometry().x() else: if newRect.height() < self._parent.minimumHeight(): top = self.frameGeometry().y() self._parent.setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))) self._rubberBand.setGeometry(QRect(QPoint(left, top), QPoint(right, bottom))) else: self.__updateCursorShape(event.globalPos()) def __updateCursorShape(self, pos): if self._parent.isFullScreen() or self._parent.isMaximized(): if self._cursorChanged: self._parent.unsetCursor() return self._mouseMove = self.__calculateCursorPosition(pos, self._parent.frameGeometry()) if self._mouseMove == Edge.Left or self._mouseMove == Edge.Right: self._parent.setCursor(Qt.SizeHorCursor) self._cursorChanged = True else: if self._mouseMove == Edge.Top or self._mouseMove == Edge.Bottom: self._parent.setCursor(Qt.SizeVerCursor) self._cursorChanged = True else: if self._mouseMove == Edge.TopLeft or self._mouseMove == Edge.BottomRight: self._parent.setCursor(Qt.SizeFDiagCursor) self._cursorChanged = True else: if self._mouseMove == Edge.TopRight or self._mouseMove == Edge.BottomLeft: self._parent.setCursor(Qt.SizeBDiagCursor) self._cursorChanged = True else: self._parent.unsetCursor() self._cursorChanged = False def __calculateCursorPosition(self, pos, framerect): onLeft = pos.x() <= framerect.x() + self._borderWidth and \ pos.x() >= framerect.x() and \ pos.y() <= framerect.y() + framerect.height() - self._borderWidth and \ pos.y() >= framerect.y() + self._borderWidth onRight = pos.x() >= framerect.x() + framerect.width() - self._borderWidth and \ pos.x() <= framerect.x() + framerect.width() and \ pos.y() >= framerect.y() + self._borderWidth and \ pos.y() <= framerect.y() + framerect.height() - self._borderWidth onBottom = pos.x() >= framerect.x() + self._borderWidth and \ pos.x() <= framerect.x() + framerect.width() - self._borderWidth and \ pos.y() >= framerect.y() + framerect.height() - self._borderWidth and \ pos.y() <= framerect.y() + framerect.height() onTop = pos.x() >= framerect.x() + self._borderWidth and \ pos.x() <= framerect.x() + framerect.width() - self._borderWidth and \ pos.y() >= framerect.y() and pos.y() <= framerect.y() + self._borderWidth onBottomLeft = pos.x() <= framerect.x() + self._borderWidth and \ pos.x() >= framerect.x() and \ pos.y() <= framerect.y() + framerect.height() and \ pos.y() >= framerect.y() + framerect.height() - self._borderWidth onBottomRight = pos.x() >= framerect.x() + framerect.width() - self._borderWidth and \ pos.x() <= framerect.x() + framerect.width() and \ pos.y() >= framerect.y() + framerect.height() - self._borderWidth and \ pos.y() <= framerect.y() + framerect.height() onTopRight = pos.x() >= framerect.x() + framerect.width() - self._borderWidth and \ pos.x() <= framerect.x() + framerect.width() and \ pos.y() >= framerect.y() and \ pos.y() <= framerect.y() + self._borderWidth onTopLeft = pos.x() >= framerect.x() and \ pos.x() <= framerect.x() + self._borderWidth and \ pos.y() >= framerect.y() and \ pos.y() <= framerect.y() + self._borderWidth if onLeft: return Edge.Left else: if onRight: return Edge.Right else: if onBottom: return Edge.Bottom else: if onTop: return Edge.Top else: if onBottomLeft: return Edge.BottomLeft else: if onBottomRight: return Edge.BottomRight else: if onBottomRight: return Edge.BottomRight else: if onTopRight: return Edge.TopRight else: if onTopLeft: return Edge.TopLeft else: return Edge.NoEdge def setBorderWidth(self, borderWidth): self._borderWidth = borderWidth def borderWidth(self): return self._borderWidth
class ImageHolder(QWidget): foregroundState = list() foreground = None mousePressPoint = None cropMode = False def __init__(self, image): super(ImageHolder, self).__init__() self.image = image self.setMinimumSize(self.image.size()) self.resize(self.image.size()) self.foreground = QImage(self.image.size(),QImage.Format_ARGB32_Premultiplied) undo = QShortcut(QKeySequence("Ctrl+z"), self) undo.activated.connect(self.undo) crop = QShortcut(QKeySequence("c"), self) crop.activated.connect(self.toggleCropMode) def applyState(self): print("apply state") if self.cropMode: rect = self.currentQRubberBand.geometry() self.image = self.image.copy(rect) self.setMinimumSize(self.image.size()) self.resize(self.image.size()) QApplication.restoreOverrideCursor() self.toggleCropMode() self.currentQRubberBand.hide() self.repaint() def cancelState(self): if cropMode: self.currentQRubberBand.hide() def toggleCropMode(self): self.cropMode = not self.cropMode if self.cropMode: QApplication.setOverrideCursor(QCursor(Qt.CrossCursor)) else: QApplication.restoreOverrideCursor() def mousePressEvent(self, event): print("ImageHolder: " + str(event.pos())) self.mousePressPoint = event.pos(); if self.cropMode: if hasattr(self, "currentQRubberBand"): self.currentQRubberBand.hide() self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self) self.currentQRubberBand.setGeometry(QRect(self.mousePressPoint, QSize())) self.currentQRubberBand.show() def mouseMoveEvent(self, event): print("mouseMove: " + str(event.pos())) if self.cropMode: self.currentQRubberBand.setGeometry(QRect(self.mousePressPoint, event.pos()).normalized()) def undo(self): if self.cropMode: self.currentQRubberBand.hide() elif len(self.foregroundState) > 0: self.foreground = self.foregroundState.pop() self.repaint() def mouseReleaseEvent(self, event): if not self.cropMode: self.foregroundState.append(QImage(self.foreground)) self.painter.begin(self.foreground) self.painter.setPen(QPen(QBrush(QColor(255,241,18,100)), 15, Qt.SolidLine, Qt.RoundCap)) self.painter.drawLine(QLine(self.mousePressPoint.x(),self.mousePressPoint.y(), event.pos().x(), event.pos().y())) self.painter.end() self.repaint() def saveChanges(self): newImage = QImage(self.image.size(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(newImage) painter.drawImage(0,0, self.image) painter.drawImage(0,0, self.foreground) painter.end() return newImage def paintEvent(self, event): self.painter = QPainter(self) self.painter.setPen(QPen(QBrush(QColor(255,241,18,100)), 15, Qt.SolidLine, Qt.RoundCap)) self.painter.drawImage(0,0, self.image) self.painter.drawImage(0,0, self.foreground) self.painter.end()
class FsApp(QMainWindow): def __init__(self, app): super(FsApp, self).__init__() self.app = app self.selRect = None self.screenPix = None # Set up the user interface from Designer. self.ui = Ui_MainWindow() self.ui.setupUi(self) #self.setWindowOpacity(0.5) #self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True) self.captureScreen() self.showMaximized() self.showFullScreen() #capture screen and display rec = QApplication.desktop().screenGeometry() height = rec.height() width = rec.width() self.ui.labPix.resize(width, height) self.ui.labPix.setScaledContents(True) self.ui.labPix.setPixmap(self.screenPix) #start rubberband self.rubberband = QRubberBand(QRubberBand.Rectangle, self) bla = QtGui.QPalette() bla.setBrush(QtGui.QPalette.Highlight, QtGui.QBrush(QtCore.Qt.red)) self.rubberband.setPalette(bla) self.rubberband.setWindowOpacity(1.0) def captureScreen(self): screens = self.app.screens() self.screenPix = screens[0].grabWindow(0) def mousePressEvent(self, event): self.origin = event.pos() self.rubberband.setGeometry(QtCore.QRect(self.origin, QtCore.QSize())) self.rubberband.show() QWidget.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self.rubberband.isVisible(): self.rubberband.setGeometry(QtCore.QRect(self.origin, event.pos()).normalized()) QWidget.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if self.rubberband.isVisible(): self.selRect = self.rubberband.geometry() self.rubberband.hide() codePix = self.screenPix.copy( self.selRect.x(), self.selRect.y(), self.selRect.width(), self.selRect.height()) QApplication.clipboard().setPixmap(codePix) self.exit() QWidget.mouseReleaseEvent(self, event) def exit(self): sys.exit(0)
class MyGraphicsView(CanvasBase): """ This is the used Canvas to print the graphical interface of dxf2gcode. All GUI things should be performed in the View and plotting functions in the scene """ def __init__(self, parent=None): """ Initialisation of the View Object. This is called by the gui created with the QTDesigner. @param parent: Main is passed as a pointer for reference. """ super(MyGraphicsView, self).__init__(parent) self.currentItem = None self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) # self.setDragMode(QGraphicsView.RubberBandDrag ) self.setDragMode(QGraphicsView.NoDrag) self.parent = parent self.mppos = None self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.prvRectRubberBand = QtCore.QRect() def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(QtCore.QCoreApplication.translate('MyGraphicsView', string_to_translate)) def contextMenuEvent(self, event): """ Create the contextmenu. @purpose: Links the new Class of ContextMenu to Graphicsview. """ position = self.mapToGlobal(event.pos()) GVPos = self.mapToScene(event.pos()) real_pos = Point(GVPos.x(), -GVPos.y()) menu = MyDropDownMenu(self.scene(), position, real_pos) def wheelEvent(self, event): """ With Mouse Wheel the object is scaled @purpose: Scale by mouse wheel @param event: Event Parameters passed to function """ if c.PYQT5notPYQT4: delta = event.angleDelta().y() else: delta = event.delta() scale = (1000 + delta) / 1000.0 self.scale(scale, scale) def mousePressEvent(self, event): """ Right Mouse click shall have no function, Therefore pass only left click event @purpose: Change inherited mousePressEvent @param event: Event Parameters passed to function """ if self.dragMode() == 1: super(MyGraphicsView, self).mousePressEvent(event) elif event.button() == QtCore.Qt.LeftButton: self.mppos = event.pos() else: pass def mouseReleaseEvent(self, event): """ Right Mouse click shall have no function, Therefore pass only left click event @purpose: Change inherited mousePressEvent @param event: Event Parameters passed to function """ delta = 2 if self.dragMode() == 1: # if (event.key() == QtCore.Qt.Key_Shift): # self.setDragMode(QGraphicsView.NoDrag) super(MyGraphicsView, self).mouseReleaseEvent(event) # Selection only enabled for left Button elif event.button() == QtCore.Qt.LeftButton: self.currentItems = [] scene = self.scene() if not self.isMultiSelect: for item in scene.selectedItems(): item.setSelected(False, False) # If the mouse button is pressed without movement of rubberband if self.rubberBand.isHidden(): rect = QtCore.QRect(event.pos().x()-delta, event.pos().y() - delta, 2 * delta, 2*delta) # logger.debug(rect) point = self.mapToScene(event.pos()) min_distance = float(0x7fffffff) for item in self.items(rect): itemDistance = item.contains_point(point) if itemDistance < min_distance: min_distance = itemDistance self.currentItems = item if self.currentItems: if self.currentItems.isSelected(): self.currentItems.setSelected(False, False) else: self.currentItems.setSelected(True, False) else: rect = self.rubberBand.geometry() self.currentItems = self.items(rect) self.rubberBand.hide() # logger.debug("Rubberband Selection") # All items in the selection # self.currentItems = self.items(rect) # print self.currentItems # logger.debug(rect) for item in self.currentItems: if item.isSelected(): item.setSelected(False, False) else: # print (item.flags()) item.setSelected(True, False) else: pass self.mppos = None # super(MyGraphicsView, self).mouseReleaseEvent(event) def mouseMoveEvent(self, event): """ MouseMoveEvent of the Graphiscview. May also be used for the Statusbar. @purpose: Get the MouseMoveEvent and use it for the Rubberband Selection @param event: Event Parameters passed to function """ if self.mppos is not None: Point = event.pos() - self.mppos if Point.manhattanLength() > 3: # print 'the mouse has moved more than 3 pixels since the oldPosition' # print "Mouse Pointer is currently hovering at: ", event.pos() rect = QtCore.QRect(self.mppos, event.pos()) ''' The following is needed because of PyQt5 doesn't like to switch from sign it will keep displaying last rectangle, i.e. you can end up will multiple rectangles ''' if self.prvRectRubberBand.width() > 0 and not rect.width() > 0 or rect.width() == 0 or\ self.prvRectRubberBand.height() > 0 and not rect.height() > 0 or rect.height() == 0: self.rubberBand.hide() self.rubberBand.setGeometry(rect.normalized()) self.rubberBand.show() self.prvRectRubberBand = rect scpoint = self.mapToScene(event.pos()) # self.setStatusTip('X: %3.1f; Y: %3.1f' % (scpoint.x(), -scpoint.y())) # works not as supposed to self.setToolTip('X: %3.1f; Y: %3.1f' %(scpoint.x(), -scpoint.y())) super(MyGraphicsView, self).mouseMoveEvent(event) def autoscale(self): """ Automatically zooms to the full extend of the current GraphicsScene """ scene = self.scene() width = scene.bottomRight.x - scene.topLeft.x height = scene.topLeft.y - scene.bottomRight.y scext = QtCore.QRectF(scene.topLeft.x, -scene.topLeft.y, width * 1.05, height * 1.05) self.fitInView(scext, QtCore.Qt.KeepAspectRatio) logger.debug(self.tr("Autoscaling to extend: %s") % scext) def setShowPathDirections(self, flag): """ This function is called by the Main Window from the Menubar. @param flag: This flag is true if all Path Direction shall be shown """ scene = self.scene() for shape in scene.shapes: shape.starrow.setallwaysshow(flag) shape.enarrow.setallwaysshow(flag) shape.stmove.setallwaysshow(flag) def resetAll(self): """ Deletes the existing GraphicsScene. """ scene = self.scene() del scene
class QtImagePartSelector(QGraphicsView): """ Partly based on https://github.com/marcel-goldschen-ohm/PyQtImageViewer by Marcel Goldschen-Ohm, MIT license """ rectSet = pyqtSignal(QRect) def __init__(self): QGraphicsView.__init__(self) # Image is displayed as a QPixmap in a QGraphicsScene attached to this QGraphicsView. self.scene = QGraphicsScene() self.setScene(self.scene) # Store a local handle to the scene's current image pixmap. self._pixmapHandle = None self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) # rubber band for area selection self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBandScenePos = None # so it can be restored after resizing self.setMouseTracking(True) self.origin = QPoint() self.changeRubberBand = False # previous mouse position during mouse drag action self.dragPrevMousePos = None self.setCursor(Qt.CrossCursor) def hasImage(self): """ Returns whether or not the scene contains an image pixmap. """ return self._pixmapHandle is not None def clearImage(self): """ Removes the current image pixmap from the scene if it exists. """ if self.hasImage(): self.scene.removeItem(self._pixmapHandle) self._pixmapHandle = None def pixmap(self): """ Returns the scene's current image pixmap as a QPixmap, or else None if no image exists. :rtype: QPixmap | None """ if self.hasImage(): return self._pixmapHandle.pixmap() return None def image(self): """ Returns the scene's current image pixmap as a QImage, or else None if no image exists. :rtype: QImage | None """ if self.hasImage(): return self._pixmapHandle.pixmap().toImage() return None def resizeEvent(self, event): QGraphicsView.resizeEvent(self, event) self.updateRubberBandDisplay() def showEvent(self, event): self.old_center = self.mapToScene(self.rect().center()) def setImage(self, image): """ Set the scene's current image pixmap to the input QImage or QPixmap. Raises a RuntimeError if the input image has type other than QImage or QPixmap. :type image: QImage | QPixmap """ if type(image) is QPixmap: pixmap = image elif type(image) is QImage: pixmap = QPixmap.fromImage(image) else: raise RuntimeError("ImageViewer.setImage: Argument must be a QImage or QPixmap.") if self.hasImage(): self._pixmapHandle.setPixmap(pixmap) else: self._pixmapHandle = self.scene.addPixmap(pixmap) self.setSceneRect(QRectF(pixmap.rect())) # Set scene size to image size. def loadImageFromFile(self, fileName=""): """ Load an image from file. Without any arguments, loadImageFromFile() will popup a file dialog to choose the image file. With a fileName argument, loadImageFromFile(fileName) will attempt to load the specified image file directly. """ if len(fileName) == 0: fileName, dummy = QFileDialog.getOpenFileName(self, "Open image file.") if len(fileName) and os.path.isfile(fileName): image = QImage(fileName) self.setImage(image) def mousePressEvent(self, event): """ Start creation of rubber band """ if event.button() == Qt.LeftButton: self.origin = event.pos() self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBandScenePos = self.mapToScene(self.rubberBand.geometry()) self.rubberBand.show() self.changeRubberBand = True elif event.button() == Qt.MidButton: self.setCursor(Qt.ClosedHandCursor) self.dragPrevMousePos = event.pos() QGraphicsView.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self.changeRubberBand: # update rubber self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) self.rubberBandScenePos = self.mapToScene(self.rubberBand.geometry()) if event.buttons() & Qt.MidButton: # drag image offset = self.dragPrevMousePos - event.pos() self.dragPrevMousePos = event.pos() self.verticalScrollBar().setValue(self.verticalScrollBar().value() + offset.y()) self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() + offset.x()) self.updateRubberBandDisplay() QGraphicsView.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: # Emit rubber band size self.changeRubberBand = False self.rectSet.emit(self.rubberBandScenePos.boundingRect().toAlignedRect()) elif event.button() == Qt.MiddleButton: self.setCursor(Qt.CrossCursor) QGraphicsView.mouseReleaseEvent(self, event) def updateRubberBandDisplay(self): if self.rubberBandScenePos is not None: self.rubberBand.setGeometry(self.mapFromScene(self.rubberBandScenePos).boundingRect()) def wheelEvent(self, event): # Zoom Factor zoomInFactor = 1.1 zoomOutFactor = 1 / zoomInFactor # Set Anchors self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) # Save the scene pos oldPos = self.mapToScene(event.pos()) # Zoom if event.angleDelta().y() > 0: zoomFactor = zoomInFactor else: zoomFactor = zoomOutFactor self.scale(zoomFactor, zoomFactor) # Get the new position newPos = self.mapToScene(event.pos()) # Move scene to old position delta = newPos - oldPos self.translate(delta.x(), delta.y()) self.updateRubberBandDisplay()
class TcamScreen(QtWidgets.QGraphicsView): new_pixmap = pyqtSignal(QtGui.QPixmap) new_pixel_under_mouse = pyqtSignal(bool, int, int, QtGui.QColor) destroy_widget = pyqtSignal() fit_in_view = pyqtSignal() def __init__(self, parent=None): super(TcamScreen, self).__init__(parent) self.setMouseTracking(True) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setFrameStyle(0) self.scene = QGraphicsScene(self) self.setScene(self.scene) self.new_pixmap.connect(self.on_new_pixmap) self.fit_in_view.connect(self.fit_view) self.pix = ViewItem() self.scene.addItem(self.pix) self.scene.setSceneRect(self.pix.boundingRect()) self.is_fullscreen = False # Flag to differentiate between actual images # and 'fake images' i.e. color background + text while # waiting for first trigger image self.display_real_image = True self.text_item = None self.fit_in_view_called = False self.mouse_position_x = -1 self.mouse_position_y = -1 self.zoom_factor = 1.0 self.first_image = True self.image_counter = 0 self.capture_roi = False self.roi_obj = None self.roi_origin = None self.roi_widgets = [] self.selection_area = None self.capture_widget = None self.origin = None def fit_view(self): """ """ self.reset_zoom() self.scene.setSceneRect(self.pix.boundingRect()) self.scene.update() self.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio) def reset_zoom(self): self.zoom_factor = 1.0 # this resets the view internal transformation matrix self.setTransform(QtGui.QTransform()) def on_new_pixmap(self, pixmap): self.image_counter += 1 self.pix.setPixmap(pixmap) if not self.display_real_image: self.text_item.hide() self.scene.removeItem(self.text_item) self.display_real_image = True if self.image_counter == 1: self.resize(self.size()) self.scene.setSceneRect(self.pix.boundingRect()) self.update() self.reset_zoom() self.first_image = False # wait for the second image # resizeEvents, etc appear before the scene has adjusted # to the actual image size. By waiting for the 2. image # we circumvent this by having the first image making all # adjustments for us. The only scenario where this will # cause problems is triggering. if self.is_fullscreen and self.image_counter == 2: self.fit_view() self.send_mouse_pixel() # don't call repaint here # it causes problems once the screen goes blank due to screensavers, etc # self.repaint() def wait_for_first_image(self): if not self.display_real_image: return self.reset_zoom() self.display_real_image = False self.text_item = QGraphicsTextItem() self.text_item.setDefaultTextColor(QColor("white")) self.text_item.setPos(100, 70) self.text_item.setPlainText("In Trigger Mode. Waiting for first image...") bg = QPixmap(1280, 720) bg.fill(QColor("grey")) self.pix.setPixmap(bg) self.image_counter += 1 self.scene.addItem(self.text_item) def send_mouse_pixel(self): # mouse positions start at 0 # we want the lower right corner to have the correct coordinates # e.g. an 1920x1080 image should have the coordinates # 1920x1080 for the last pixel self.new_pixel_under_mouse.emit(self.pix.legal_coordinates(self.mouse_position_x, self.mouse_position_y), self.mouse_position_x + 1, self.mouse_position_y + 1, self.pix.get_color_at_position(self.mouse_position_x, self.mouse_position_y)) def mouseMoveEvent(self, event): mouse_position = self.mapToScene(event.pos()) self.mouse_position_x = mouse_position.x() self.mouse_position_y = mouse_position.y() if self.selection_area: # adjust rect since we want to pull in all directions # origin can well be bottom left, thus recalc def calc_selection_rect(): x = min(self.origin.x(), event.pos().x()) y = min(self.origin.y(), event.pos().y()) x2 = max(self.origin.x(), event.pos().x()) y2 = max(self.origin.y(), event.pos().y()) return QPoint(x, y), QPoint(x2, y2) p1, p2 = calc_selection_rect() self.selection_area.setGeometry(QRect(p1, p2)) super().mouseMoveEvent(event) def mousePressEvent(self, event): """""" if self.capture_widget: self.selection_area = QRubberBand(QRubberBand.Rectangle, self) self.selection_area.setGeometry(QRect(event.pos(), QSize())) self.origin = event.pos() self.selection_area.show() super().mousePressEvent(event) def mouseReleaseEvent(self, event): if self.capture_widget: selectionBBox = self.selection_area.rect() rect = QRect(self.selection_area.pos(), selectionBBox.size()) selectionBBox = self.mapToScene(rect).boundingRect().toRect() self.capture_widget.emit(selectionBBox) self.selection_area.hide() self.selection_area = None QApplication.restoreOverrideCursor() self.capture_widget = None self.selection_area = None super().mouseReleaseEvent(event) def is_scene_larger_than_image(self): """ checks if the entire ViewItem is visible in the scene """ port_rect = self.viewport().rect() scene_rect = self.mapToScene(port_rect).boundingRect() item_rect = self.pix.mapRectFromScene(scene_rect) isec = item_rect.intersected(self.pix.boundingRect()) res = self.pix.get_resolution() if (isec.size().width() >= QSizeF(res).width() and isec.size().height() >= QSizeF(res).height()): return True return False def wheelEvent(self, event): if not self.display_real_image: return # Zoom Factor zoomInFactor = 1.25 zoomOutFactor = 1 / zoomInFactor # Set Anchors self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) # Save the scene pos oldPos = self.mapToScene(event.pos()) # Zoom if event.angleDelta().y() > 0: zoomFactor = zoomInFactor else: zoomFactor = zoomOutFactor if (self.is_scene_larger_than_image() and zoomFactor < 1.0): return self.zoom_factor *= zoomFactor # we scale the view itself to get infinite zoom # so that we can inspect a single pixel self.scale(zoomFactor, zoomFactor) # Get the new position newPos = self.mapToScene(event.pos()) # Move scene to old position delta = newPos - oldPos self.translate(delta.x(), delta.y()) self.scene.setSceneRect(self.pix.boundingRect()) def set_scale_position(self, scale_factor, x, y): self.scale(scale_factor, scale_factor) self.translate(x, y) def keyPressEvent(self, event): if self.isFullScreen(): if (event.key() == Qt.Key_F11 or event.key() == Qt.Key_Escape or event.key() == Qt.Key_F): self.destroy_widget.emit() elif self.capture_widget and event.key() == Qt.Key_Escape: self.abort_roi_capture() else: # Ignore event so that parent widgets can use it. # This is only called when we are not fullscreen. # Fullscreen causes us to have no parents. event.ignore() def start_roi_capture(self, finished_signal): """ Capture a region of interest """ self.capture_widget = finished_signal QApplication.setOverrideCursor(Qt.CrossCursor) def abort_roi_capture(self): """ Abort the capture of a regoin of interest """ self.capture_widget = None self.origin = None if self.selection_area: self.selection_area.hide() self.selection_area = None QApplication.restoreOverrideCursor() def add_roi(self, roi_widget): """ Add roi_widget to the QGraphicsScene for display """ if not roi_widget: return self.roi_widgets.append(roi_widget) self.scene.addItem(roi_widget) roi_widget.show() def remove_roi(self, roi_widget): """ Remove given roi widget from the scene """ if not roi_widget: return roi_widget.hide() try: self.roi_widgets.remove(roi_widget) except ValueError as e: # This means the widget is not in the list pass
class QMainLabel(QLabel): def __init__(self, parentQWidget): super(QMainLabel, self).__init__(parentQWidget) self.original_image_pixmap = None self.original_mask_pixmap = None self.target_size = self.parent().main_label_size def set_size(self, size): self.target_size = size def load_pixmap(self, image, mask=None): self.original_image_pixmap = QPixmap(image) if mask: self.original_mask_pixmap = QPixmap(mask) combo = self.merge_image_mask(self.original_image_pixmap, self.original_mask_pixmap) self.setPixmap(combo) return self.setPixmap(self.original_image_pixmap) def merge_image_mask(self, image, mask): print(type(image), type(mask)) if type(image) == QPixmap and type(mask) == QPixmap: pil_image = ImageQt.fromqpixmap(image) pil_mask = ImageQt.fromqpixmap(mask) else: pil_image = image pil_mask = mask np_image = np.array(pil_image) np_mask = np.array(pil_mask) print(np_image.shape, np_mask.shape) prob = np.float32(np_mask) / 255.0 np_combo = np.uint8(np_image * (1 - prob) + np_mask * prob * np.array([[[0., 1., 0.]]])) pil_combo = Image.fromarray(np_combo) combo = ImageQt.toqpixmap(pil_combo) return combo def restore_original(self): print('Ctrl+Z') image = self.original_image_pixmap mask = self.original_mask_pixmap if image and mask: image = self.merge_image_mask(image, mask) self.setPixmap(image) def mousePressEvent(self, eventQMouseEvent): self.originQPoint = eventQMouseEvent.pos() self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self) self.currentQRubberBand.setGeometry(QRect(self.originQPoint, QSize())) self.currentQRubberBand.show() def mouseMoveEvent(self, eventQMouseEvent): self.currentQRubberBand.setGeometry( QRect(self.originQPoint, eventQMouseEvent.pos()).normalized()) def mouseReleaseEvent(self, eventQMouseEvent): self.currentQRubberBand.hide() currentQRect = self.currentQRubberBand.geometry() self.currentQRubberBand.deleteLater() cropQPixmap = self.pixmap().copy(currentQRect) # cropQPixmap.save('output.png') crop_PIL = ImageQt.fromqpixmap(cropQPixmap) crop_PIL = pad_to_square(crop_PIL, self.target_size) cropQPixmap = ImageQt.toqpixmap(crop_PIL) self.setPixmap(cropQPixmap)
class MainView(QGraphicsView): """ This class implements the main view displayed in the MDI area. """ MoveRate = 40 MoveBound = 10 sgnScaled = pyqtSignal(float) def __init__(self, mainwindow, scene): """ Initialize the main scene. :type mainwindow: MainWindow :type scene: DiagramScene """ super().__init__(scene) self.setContextMenuPolicy(Qt.PreventContextMenu) self.setDragMode(QGraphicsView.NoDrag) self.setOptimizationFlags(QGraphicsView.DontAdjustForAntialiasing) self.setOptimizationFlags(QGraphicsView.DontSavePainterState) self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate) self.mainwindow = mainwindow self.mousePressCenterPos = None self.mousePressPos = None self.moveTimer = None self.rubberBandOrigin = None self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.hide() self.zoom = 1.00 #################################################################################################################### # # # SLOTS # # # #################################################################################################################### @pyqtSlot() def updateView(self): """ Update the Overview. """ viewport = self.viewport() viewport.update() @pyqtSlot(float) def zoomChanged(self, zoom): """ Executed when the zoom factor changes (triggered by the Zoom widget). :type zoom: float """ self.scaleView(zoom) #################################################################################################################### # # # DRAWING # # # #################################################################################################################### def drawBackground(self, painter, rect): """ Draw the scene background. :type painter: QPainter :type rect: QRectF """ if self.mainwindow.snapToGrid: s = DiagramScene.GridSize x = int(rect.left()) - (int(rect.left()) % s) y = int(rect.top()) - (int(rect.top()) % s) painter.setPen(DiagramScene.GridPen) painter.drawPoints(*(QPointF(i, j) for i in rangeF(x, rect.right(), s) for j in rangeF(y, rect.bottom(), s))) #################################################################################################################### # # # EVENTS # # # #################################################################################################################### def keyPressEvent(self, keyEvent): """ Executed when a combination of key is pressed. :type keyEvent: QKeyEvent """ scene = self.scene() key = keyEvent.key() modifiers = keyEvent.modifiers() if scene.mode is DiagramMode.Idle and \ modifiers & Qt.ControlModifier and \ key in {Qt.Key_Minus, Qt.Key_Plus, Qt.Key_0}: if key == Qt.Key_Minus: zoom = self.zoom - Zoom.Step elif key == Qt.Key_Plus: zoom = self.zoom + Zoom.Step else: zoom = Zoom.Default zoom = clamp(zoom, Zoom.Min, Zoom.Max) if zoom != self.zoom: self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) self.scaleView(zoom) self.sgnScaled.emit(zoom) else: super().keyPressEvent(keyEvent) def mousePressEvent(self, mouseEvent): """ Executed when a mouse button is clicked on the view. :type mouseEvent: QGraphicsSceneMouseEvent """ scene = self.scene() mouseButtons = mouseEvent.buttons() mousePos = mouseEvent.pos() if mouseButtons & Qt.RightButton: ############################################################################################################ # # # SCENE DRAG # # # ############################################################################################################ visibleRect = self.visibleRect() self.mousePressCenterPos = visibleRect.center() self.mousePressPos = mousePos else: if mouseButtons & Qt.LeftButton: ######################################################################################################## # # # RUBBERBAND SELECTION # # # ######################################################################################################## if scene.mode is DiagramMode.Idle and not self.itemAt(mousePos): self.rubberBandOrigin = self.mapToScene(mousePos) self.rubberBand.setGeometry(QRectF(mousePos, mousePos).toRect()) self.rubberBand.show() scene.setMode(DiagramMode.RubberBandDrag) super().mousePressEvent(mouseEvent) # noinspection PyArgumentList def mouseMoveEvent(self, mouseEvent): """ Executed when then mouse is moved on the view. :type mouseEvent: QGraphicsSceneMouseEvent """ scene = self.scene() mousePos = mouseEvent.pos() mouseButtons = mouseEvent.buttons() viewport = self.viewport() if mouseButtons & Qt.RightButton: if (mouseEvent.pos() - self.mousePressPos).manhattanLength() >= QApplication.startDragDistance(): ######################################################################################################## # # # SCENE DRAG # # # ######################################################################################################## if scene.mode is not DiagramMode.SceneDrag: scene.setMode(DiagramMode.SceneDrag) viewport.setCursor(Qt.ClosedHandCursor) mousePos /= self.zoom mousePressPos = self.mousePressPos / self.zoom self.centerOn(self.mousePressCenterPos - mousePos + mousePressPos) else: super().mouseMoveEvent(mouseEvent) if mouseButtons & Qt.LeftButton: self.stopMove() if scene.mode is DiagramMode.RubberBandDrag: #################################################################################################### # # # RUBBERBAND DRAG # # # #################################################################################################### area = QRectF(self.mapFromScene(self.rubberBandOrigin), mousePos).normalized() path = QPainterPath() path.addRect(area) scene.setSelectionArea(self.mapToScene(path)) self.rubberBand.setGeometry(area.toRect()) if scene.mode in { DiagramMode.BreakPointMove, DiagramMode.InsertEdge, DiagramMode.MoveNode, DiagramMode.ResizeNode, DiagramMode.RubberBandDrag }: #################################################################################################### # # # VIEW SCROLLING # # # #################################################################################################### R = viewport.rect() if not R.contains(mousePos): move = QPointF(0, 0) if mousePos.x() < R.left(): move.setX(mousePos.x() - R.left()) elif mousePos.x() > R.right(): move.setX(mousePos.x() - R.right()) if mousePos.y() < R.top(): move.setY(mousePos.y() - R.top()) elif mousePos.y() > R.bottom(): move.setY(mousePos.y() - R.bottom()) if move: move.setX(clamp(move.x(), -MainView.MoveBound, +MainView.MoveBound)) move.setY(clamp(move.y(), -MainView.MoveBound, +MainView.MoveBound)) self.startMove(move, MainView.MoveRate) def mouseReleaseEvent(self, mouseEvent): """ Executed when the mouse is released from the view. :type mouseEvent: QGraphicsSceneMouseEvent """ self.mousePressCenterPos = None self.mousePressPos = None self.rubberBandOrigin = None self.rubberBand.hide() self.stopMove() scene = self.scene() viewport = self.viewport() viewport.setCursor(Qt.ArrowCursor) viewport.update() super().mouseReleaseEvent(mouseEvent) if scene.mode in {DiagramMode.RubberBandDrag, DiagramMode.SceneDrag}: scene.setMode(DiagramMode.Idle) def wheelEvent(self, wheelEvent): """ Executed when the mouse wheel is moved on the scene. :type wheelEvent: QWheelEvent """ if wheelEvent.modifiers() & Qt.ControlModifier: wheelPos = wheelEvent.pos() wheelAngle = wheelEvent.angleDelta() zoom = self.zoom zoom += +Zoom.Step if wheelAngle.y() > 0 else -Zoom.Step zoom = clamp(zoom, Zoom.Min, Zoom.Max) if zoom != self.zoom: self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) p1 = self.mapToScene(wheelPos) self.scaleView(zoom) self.sgnScaled.emit(zoom) p2 = self.mapToScene(wheelPos) move = p2 - p1 self.translate(move.x(), move.y()) else: super().wheelEvent(wheelEvent) #################################################################################################################### # # # INTERFACE # # # #################################################################################################################### def moveBy(self, *__args): """ Move the view by the given delta. """ if len(__args) == 1: delta = __args[0] elif len(__args) == 2: delta = QPointF(__args[0], __args[1]) else: raise TypeError('too many arguments; expected {}, got {}'.format(2, len(__args))) self.centerOn(self.visibleRect().center() + delta) def scaleView(self, zoom): """ Scale the view according to the given zoom. :type zoom: float """ transform = self.transform() self.resetTransform() self.translate(transform.dx(), transform.dy()) self.scale(zoom, zoom) self.zoom = zoom def startMove(self, delta, rate): """ Start the view movement. :type delta: QPointF :type rate: float """ if self.moveTimer: self.stopMove() # move the view: this is needed before the timer so that if we keep # moving the mouse fast outside the viewport rectangle we still are able # to move the view; if we don't do this the timer may not have kicked in # and thus we remain with a non-moving view with a unfocused graphicsitem self.moveBy(delta) # setup a timer for future move, so the view keeps moving # also if we are not moving the mouse anymore but we are # holding the position outside the viewport rect self.moveTimer = QTimer() connect(self.moveTimer.timeout, self.moveBy, delta) self.moveTimer.start(rate) def stopMove(self): """ Stop the view movement by destroying the timer object causing it. """ if self.moveTimer: self.moveTimer.stop() disconnect(self.moveTimer.timeout) self.moveTimer = None def visibleRect(self): """ Returns the visible area in scene coordinates. :rtype: QRectF """ return self.mapToScene(self.viewport().rect()).boundingRect()