class GraphicsPixmapWidget(QGraphicsWidget): """ A QGraphicsWidget displaying a QPixmap """ def __init__(self, pixmap=None, parent=None): super().__init__(parent) self.setCacheMode(QGraphicsItem.ItemCoordinateCache) self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap() self._keepAspect = True self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) def setPixmap(self, pixmap): self._pixmap = QPixmap(pixmap) self.updateGeometry() self.update() def pixmap(self): return QPixmap(self._pixmap) def setKeepAspectRatio(self, keep): if self._keepAspect != keep: self._keepAspect = bool(keep) self.update() def keepAspectRatio(self): return self._keepAspect def setGeometry(self, rect): self.prepareGeometryChange() super().setGeometry(rect) def sizeHint(self, which, constraint=QSizeF()): if which == Qt.PreferredSize: return QSizeF(self._pixmap.size()) else: return QGraphicsWidget.sizeHint(self, which, constraint) def paint(self, painter, option, widget=0): if self._pixmap.isNull(): return rect = self.contentsRect() pixsize = QSizeF(self._pixmap.size()) aspectmode = (Qt.KeepAspectRatio if self._keepAspect else Qt.IgnoreAspectRatio) pixsize.scale(rect.size(), aspectmode) pixrect = QRectF(QPointF(0, 0), pixsize) pixrect.moveCenter(rect.center()) painter.save() painter.setPen(QPen(QColor(0, 0, 0, 50), 3)) painter.drawRoundedRect(pixrect, 2, 2) painter.setRenderHint(QPainter.SmoothPixmapTransform) source = QRectF(QPointF(0, 0), QSizeF(self._pixmap.size())) painter.drawPixmap(pixrect, self._pixmap, source) painter.restore()
def __startInternalDrag(self, frame, hotSpot=None): drag = QDrag(self) pixmap = QPixmap(frame.size()) frame.render(pixmap) transparent = QPixmap(pixmap.size()) transparent.fill(Qt.transparent) painter = QPainter(transparent) painter.setOpacity(0.35) painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap) painter.end() drag.setPixmap(transparent) if hotSpot is not None: drag.setHotSpot(hotSpot) mime = QMimeData() mime.setData("application/x-internal-move", b"") drag.setMimeData(mime) return drag.exec_(Qt.MoveAction)
def __startInternalDrag(self, frame, hotSpot=None): drag = QDrag(self) pixmap = QPixmap(frame.size()) frame.render(pixmap) transparent = QPixmap(pixmap.size()) transparent.fill(Qt.transparent) painter = QPainter(transparent) painter.setOpacity(0.35) painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap) painter.end() drag.setPixmap(transparent) if hotSpot is not None: drag.setHotSpot(hotSpot) mime = QMimeData() mime.setData("application/x-internal-move", b"") drag.setMimeData(mime) return drag.exec(Qt.MoveAction)
class Preview(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__pixmap = QPixmap() # Flag indicating if the widget was resized as a result of user # initiated window resize. When false the widget will automatically # resize/re-position based on pixmap size. self.__hasExplicitSize = False self.__inUpdateWindowGeometry = False def setPixmap(self, pixmap): if self.__pixmap != pixmap: self.__pixmap = QPixmap(pixmap) self.__updateWindowGeometry() self.update() self.updateGeometry() def pixmap(self): return QPixmap(self.__pixmap) def resizeEvent(self, event): super().resizeEvent(event) if self.isVisible() and self.isWindow() and \ not self.__inUpdateWindowGeometry: # mark that we have an explicit user provided size self.__hasExplicitSize = True def __updateWindowGeometry(self): if not self.isWindow() or self.__hasExplicitSize: return def framemargins(widget): frame, geom = widget.frameGeometry(), widget.geometry() return QMargins(geom.left() - frame.left(), geom.top() - frame.top(), geom.right() - frame.right(), geom.bottom() - frame.bottom()) def fitRect(rect, targetrect): size = rect.size().boundedTo(targetgeom.size()) newrect = QRect(rect.topLeft(), size) dx, dy = 0, 0 if newrect.left() < targetrect.left(): dx = targetrect.left() - newrect.left() if newrect.top() < targetrect.top(): dy = targetrect.top() - newrect.top() if newrect.right() > targetrect.right(): dx = targetrect.right() - newrect.right() if newrect.bottom() > targetrect.bottom(): dy = targetrect.bottom() - newrect.bottom() return newrect.translated(dx, dy) margins = framemargins(self) minsize = QSize(120, 120) pixsize = self.__pixmap.size() available = QApplication.desktop().availableGeometry(self) available = available.adjusted(margins.left(), margins.top(), -margins.right(), -margins.bottom()) # extra adjustment so the preview does not cover the whole desktop available = available.adjusted(10, 10, -10, -10) targetsize = pixsize.boundedTo(available.size()).expandedTo(minsize) pixsize.scale(targetsize, Qt.KeepAspectRatio) if not self.testAttribute(Qt.WA_WState_Created) or \ self.testAttribute(Qt.WA_WState_Hidden): center = available.center() else: center = self.geometry().center() targetgeom = QRect(QPoint(0, 0), pixsize) targetgeom.moveCenter(center) if not available.contains(targetgeom): targetgeom = fitRect(targetgeom, available) self.__inUpdateWindowGeometry = True self.setGeometry(targetgeom) self.__inUpdateWindowGeometry = False def sizeHint(self): return self.__pixmap.size() def paintEvent(self, event): if self.__pixmap.isNull(): return sourcerect = QRect(QPoint(0, 0), self.__pixmap.size()) pixsize = QSizeF(self.__pixmap.size()) rect = self.contentsRect() pixsize.scale(QSizeF(rect.size()), Qt.KeepAspectRatio) targetrect = QRectF(QPointF(0, 0), pixsize) targetrect.moveCenter(QPointF(rect.center())) painter = QPainter(self) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(targetrect, self.__pixmap, QRectF(sourcerect)) painter.end()
def __init__(self, parent=None, filename=None): super(MainForm, self).__init__(parent) self.view = GraphicsView() background = QPixmap(filename) # assume screnshots were taken on the same system stamper is being used on # DPI check might be more robust, can be added if needed background.setDevicePixelRatio(self.devicePixelRatioF()) self.filename = os.path.splitext(filename)[0] if ("-%s" % ORG) in self.filename: self.filename = self.filename[:-len(ORG)-5] + ".png" # self.view.setBackgroundBrush(QBrush(background)) # self.view.setCacheMode(QGraphicsView.CacheBackground) # self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.scene = QGraphicsScene(self) self.scene.addPixmap(background) global scene scene = self.scene self.view.dialog = self self.view.setScene(self.scene) self.prevPoint = QPoint() self.lastStamp = -1 buttonLayout = QVBoxLayout() for text, slot in ( ("&Tag", self.addTag), ("Align &bottom", self.alignBottom), ("Align &left", self.alignLeft), ("&Save", self.save), ("&Quit", self.accept)): button = QPushButton(text) button.clicked.connect(slot) if not MAC: button.setFocusPolicy(Qt.NoFocus) self.lineedit.returnPressed.connect(self.updateUi) if text == "&Save": buttonLayout.addStretch(5) if text == "&Quit": buttonLayout.addStretch(1) buttonLayout.addWidget(button) buttonLayout.addStretch() size = background.size() / background.devicePixelRatioF() self.view.resize(size.width(), size.height()) self.scene.setSceneRect(0, 0, size.width(), size.height()) self.view.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout = QHBoxLayout() layout.addWidget(self.view, 1) layout.addLayout(buttonLayout) self.setLayout(layout) self.setWindowTitle(AppName) info_name = self.filename + "-" + TAG + ".txt" if os.path.exists(info_name): for tag, x, y in [line.strip().split("\t") for line in open(info_name, "rt").readlines()]: self.addTag(int(tag), QPointF(int(x), int(y)), adjust_position=False) global Dirty; Dirty=False self.show() self.raise_()
class GraphicsPixmapWidget(QGraphicsWidget): """ A QGraphicsWidget displaying a QPixmap """ def __init__(self, pixmap=None, parent=None): super().__init__(parent) self.setCacheMode(QGraphicsItem.ItemCoordinateCache) self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap() self._keepAspect = True self._crop = False self._subset = True self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) def setPixmap(self, pixmap): self._pixmap = QPixmap(pixmap) self.updateGeometry() self.update() def pixmap(self): return QPixmap(self._pixmap) def setKeepAspectRatio(self, keep): if self._keepAspect != keep: self._keepAspect = bool(keep) self.update() def keepAspectRatio(self): return self._keepAspect def crop(self): return self._crop def setCrop(self, crop): if self._crop != crop: self._crop = bool(crop) self.update() def setSubset(self, in_subset): if self._subset != in_subset: self._subset = bool(in_subset) self.update() def setGeometry(self, rect): self.prepareGeometryChange() super().setGeometry(rect) def sizeHint(self, which, constraint=QSizeF()): if which == Qt.PreferredSize: return QSizeF(self._pixmap.size()) else: return QGraphicsWidget.sizeHint(self, which, constraint) def paint(self, painter, option, widget=0): if self._pixmap.isNull(): return rect = self.contentsRect() pixsize = QSizeF(self._pixmap.size()) aspectmode = (Qt.KeepAspectRatio if self._keepAspect else Qt.IgnoreAspectRatio) if self._crop: height, width = pixsize.height(), pixsize.width() diff = abs(height - width) if height > width: y, x = diff / 2, 0 h, w = height - diff, width else: x, y = diff / 2, 0 w, h = width - diff, height source = QRectF(x, y, w, h) pixrect = QRectF(QPointF(0, 0), rect.size()) else: source = QRectF(QPointF(0, 0), pixsize) pixsize.scale(rect.size(), aspectmode) pixrect = QRectF(QPointF(0, 0), pixsize) if self._subset: painter.setOpacity(1.0) else: painter.setOpacity(0.35) pixrect.moveCenter(rect.center()) painter.save() painter.setPen(QPen(QColor(0, 0, 0, 50), 3)) painter.drawRoundedRect(pixrect, 2, 2) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(pixrect, self._pixmap, source) painter.restore()
def init_style_option( delegate: QStyledItemDelegate, option: QStyleOptionViewItem, index: QModelIndex, data: Mapping[int, Any], roles: Optional[Container[int]] = None, ) -> None: """ Like `QStyledItemDelegate.initStyleOption` but fill in the fields from `data` mapping. If `roles` is not `None` init the `option` for the specified `roles` only. """ # pylint: disable=too-many-branches option.styleObject = None option.index = index if roles is None: roles = data features = 0 if Qt.DisplayRole in roles: value = data.get(Qt.DisplayRole) if value is not None: option.text = delegate.displayText(value, option.locale) features |= _QStyleOptionViewItem_HasDisplay if Qt.FontRole in roles: value = data.get(Qt.FontRole) font = cast_(QFont, value) if font is not None: font = font.resolve(option.font) option.font = font option.fontMetrics = QFontMetrics(option.font) if Qt.ForegroundRole in roles: value = data.get(Qt.ForegroundRole) foreground = cast_(QBrush, value) if foreground is not None: option.palette.setBrush(QPalette.Text, foreground) if Qt.BackgroundRole in roles: value = data.get(Qt.BackgroundRole) background = cast_(QBrush, value) if background is not None: option.backgroundBrush = background if Qt.TextAlignmentRole in roles: value = data.get(Qt.TextAlignmentRole) alignment = cast_(int, value) if alignment is not None: alignment = alignment & _AlignmentMask option.displayAlignment = _AlignmentCache[alignment] if Qt.CheckStateRole in roles: state = data.get(Qt.CheckStateRole) if state is not None: features |= _QStyleOptionViewItem_HasCheckIndicator state = cast_(int, state) if state is not None: option.checkState = state if Qt.DecorationRole in roles: value = data.get(Qt.DecorationRole) if value is not None: features |= _QStyleOptionViewItem_HasDecoration if isinstance(value, QIcon): option.icon = value elif isinstance(value, QColor): pix = QPixmap(option.decorationSize) pix.fill(value) option.icon = QIcon(pix) elif isinstance(value, QPixmap): option.icon = QIcon(value) option.decorationSize = (value.size() / value.devicePixelRatio()).toSize() elif isinstance(value, QImage): pix = QPixmap.fromImage(value) option.icon = QIcon(value) option.decorationSize = (pix.size() / pix.devicePixelRatio()).toSize() option.features |= features
class GraphicsPixmapWidget(QGraphicsWidget): def __init__(self, parent: Optional[QGraphicsItem] = None, pixmap: Optional[QPixmap] = None, scaleContents=False, aspectMode=Qt.KeepAspectRatio, **kwargs) -> None: self.__scaleContents = scaleContents self.__aspectMode = aspectMode self.__pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap() super().__init__(None, **kwargs) self.setFlag(QGraphicsWidget.ItemUsesExtendedStyleOption, True) self.setContentsMargins(0, 0, 0, 0) if parent is not None: self.setParentItem(parent) def setPixmap(self, pixmap: QPixmap) -> None: self.prepareGeometryChange() self.__pixmap = QPixmap(pixmap) self.updateGeometry() def pixmap(self) -> QPixmap: return QPixmap(self.__pixmap) def setAspectRatioMode(self, mode: Qt.AspectRatioMode) -> None: if self.__aspectMode != mode: self.__aspectMode = mode sp = self.sizePolicy() sp.setHeightForWidth(self.__aspectMode != Qt.IgnoreAspectRatio and self.__scaleContents) self.setSizePolicy(sp) self.updateGeometry() def aspectRatioMode(self) -> Qt.AspectRatioMode: return self.__aspectMode def setScaleContents(self, scale: bool) -> None: if self.__scaleContents != scale: self.__scaleContents = bool(scale) sp = self.sizePolicy() sp.setHeightForWidth(self.__aspectMode != Qt.IgnoreAspectRatio and self.__scaleContents) self.setSizePolicy(sp) self.updateGeometry() def scaleContents(self) -> bool: return self.__scaleContents def sizeHint(self, which, constraint=QSizeF(-1, -1)) -> QSizeF: if which == Qt.PreferredSize: sh = QSizeF(self.__pixmap.size()) if self.__scaleContents: sh = scaled(sh, constraint, self.__aspectMode) return sh elif which == Qt.MinimumSize: if self.__scaleContents: return QSizeF(0, 0) else: return QSizeF(self.__pixmap.size()) elif which == Qt.MaximumSize: if self.__scaleContents: return QSizeF() else: return QSizeF(self.__pixmap.size()) else: # Qt.MinimumDescent return QSizeF() def pixmapTransform(self) -> QTransform: if self.__pixmap.isNull(): return QTransform() pxsize = QSizeF(self.__pixmap.size()) crect = self.contentsRect() transform = QTransform() transform = transform.translate(crect.left(), crect.top()) if self.__scaleContents: csize = scaled(pxsize, crect.size(), self.__aspectMode) else: csize = pxsize xscale = csize.width() / pxsize.width() yscale = csize.height() / pxsize.height() return transform.scale(xscale, yscale) def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: Optional[QWidget] = None) -> None: if self.__pixmap.isNull(): return pixmap = self.__pixmap crect = self.contentsRect() exposed = option.exposedRect exposedcrect = crect.intersected(exposed) pixmaptransform = self.pixmapTransform() # map exposed rect to exposed pixmap coords assert pixmaptransform.type() in (QTransform.TxNone, QTransform.TxTranslate, QTransform.TxScale) pixmaptransform, ok = pixmaptransform.inverted() if not ok: painter.drawPixmap(crect, pixmap, QRectF(QPointF(0, 0), QSizeF(pixmap.size()))) else: exposedpixmap = pixmaptransform.mapRect(exposed) painter.drawPixmap(exposedcrect, pixmap, exposedpixmap)