def draw(self, page, painter, key, tile, paperColor=None): """Draw a tile on the painter. The painter is already at the right position and rotation. For the Poppler page and renderer, draw() is only used for printing. (See AbstractPage.print().) """ source = self.map(key, page.pageRect()).mapRect( QRectF(*tile)).toRect() # rounded target = QRectF(0, 0, tile.w, tile.h) if key.rotation & 1: target.setSize(target.size().transposed()) doc = page.document p = doc.page(page.pageNumber) with self.setup(doc, self.printRenderBackend, paperColor): if self.printRenderBackend == popplerqt5.Poppler.Document.ArthurBackend: # Poppler's Arthur backend removes the current transform from # the painter (it sets a default CTM, instead of combining it # with the current transform). We let Poppler draw on a QPicture, # and draw that on our painter. pic = QPicture() p.renderToPainter(QPainter(pic), page.dpi, page.dpi, source.x(), source.y(), source.width(), source.height()) # our resolution could be different, scale accordingly painter.save() painter.scale( pic.logicalDpiX() / painter.device().logicalDpiX(), pic.logicalDpiY() / painter.device().logicalDpiY()) pic.play(painter) painter.restore() else: # Make an image exactly in the printer's resolution m = painter.transform() r = m.mapRect(source) # see where the source ends up w, h = r.width(), r.height() if m.m11() == 0: w, h = h, w # swap if rotation & 1 :-) # now we know the scale from our dpi to the paintdevice's logicalDpi! hscale = w / source.width() vscale = h / source.height() s = QTransform().scale(hscale, vscale).mapRect(source) dpiX = page.dpi * hscale dpiY = page.dpi * vscale img = p.renderToImage(dpiX, dpiY, s.x(), s.y(), s.width(), s.height()) painter.drawImage(target, img, QRectF(img.rect()))
def paintEvent(self, QPaintEvent): pic = QPicture() painter = QPainter(pic) getModuleAttrDict(Client.gameObject.module)['paintGame'](painter) painter.end() painter.begin(self) bRect = pic.boundingRect() self.sizeHint_ = bRect.size() painter.setWindow(bRect) painter.setViewTransformEnabled(True) width = self.width() height = self.height() if width * bRect.height() < height * bRect.width(): pheight = (width * bRect.height()) / bRect.width() painter.setViewport(0, (height - pheight) / 2, width, pheight) else: pwidth = (height * bRect.width()) / bRect.height() painter.setViewport((width - pwidth) / 2, 0, pwidth, height) self.invTrafo = painter.combinedTransform().inverted()[0] pic.play(painter)
class PictureWidget(QWidget): """ Generic widget using a QPicture as a paint buffer. """ def __init__(self, *args) -> None: super().__init__(*args) self._picture = QPicture() # Last saved picture rendering. def __enter__(self) -> QPicture: """ Reset the current picture, size it to match the widget, and return it for rendering. """ self._picture = picture = QPicture() rect = QRect() rect.setSize(self.size()) picture.setBoundingRect(rect) return picture def __exit__(self, *_) -> None: """ Repaint the widget after rendering is complete. """ self.update() def paintEvent(self, *_) -> None: """ Paint the saved picture on this widget when GUI repaint occurs. """ with QPainter(self) as p: self._picture.play(p) # should be inherited from a: """ Mixin to send a signal on a context menu request (right-click). """ contextMenuRequest = pyqtSignal([QPoint]) def contextMenuEvent(self, event:QContextMenuEvent) -> None: pos = event.globalPos() self.contextMenuRequest.emit(pos) # should be inherited from a: """ Mixin to send a signal on any widget size change. """ resized = pyqtSignal() def resizeEvent(self, *_) -> None: self.resized.emit()
class BarGraphItem(pg.PlotItem): """BarGraphItem""" def __init__(self, x=None, y=None, *, width=1.0, pen=None, brush=None, name=None, parent=None): """Initialization.""" super().__init__(name=name, parent=parent) self._x = None self._y = None if width > 1.0 or width <= 0: width = 1.0 self._width = width if pen is None and brush is None: self._pen = FColor.mkPen(None) self._brush = FColor.mkBrush('b') else: self._pen = FColor.mkPen(None) if pen is None else pen self._brush = FColor.mkBrush(None) if brush is None else brush self.setData(x, y) def setData(self, x, y): """Override.""" self._parseInputData(x, y) self.updateGraph() def data(self): """Override.""" return self._x, self._y def _prepareGraph(self): """Override.""" self._graph = QPicture() p = QPainter(self._graph) p.setPen(self._pen) p.setBrush(self._brush) x, y = self.transformedData() # Now it works for bar plot with equalized gaps # TODO: extend it if len(x) > 1: width = self._width * (x[1] - x[0]) else: width = self._width for px, py in zip(x, y): p.drawRect(QRectF(px - width / 2, 0, width, py)) p.end() def paint(self, p, *args): """Override.""" if self._graph is None: self._prepareGraph() self._graph.play(p) def boundingRect(self): """Override.""" return QRectF(super().boundingRect()) def drawSample(self, p): """Override.""" p.setBrush(self._brush) p.setPen(self._pen) # Legend sample has a bounding box of (0, 0, 20, 20) p.drawRect(QRectF(2, 2, 18, 18))
class BarGraphItem(pg.GraphicsObject): """BarGraphItem""" def __init__(self, x=None, y=None, *, width=1.0, pen=None, brush=None): """Initialization.""" super().__init__() self._picture = None self._x = None self._y = None if width > 1.0 or width <= 0: width = 1.0 self._width = width if pen is None and brush is None: self._pen = FColor.mkPen(None) self._brush = FColor.mkBrush('b') else: self._pen = FColor.mkPen(None) if pen is None else pen self._brush = FColor.mkBrush(None) if brush is None else brush self.setData(x, y) def setData(self, x, y): """PlotItem interface.""" self._x = [] if x is None else x self._y = [] if y is None else y if len(self._x) != len(self._y): raise ValueError("'x' and 'y' data have different lengths!") self._picture = None self.update() self.informViewBoundsChanged() def drawPicture(self): self._picture = QPicture() p = QPainter(self._picture) p.setPen(self._pen) p.setBrush(self._brush) # Now it works for bar plot with equalized gaps # TODO: extend it if len(self._x) > 1: width = self._width * (self._x[1] - self._x[0]) else: width = self._width for x, y in zip(self._x, self._y): p.drawRect(QRectF(x - width/2, 0, width, y)) p.end() self.prepareGeometryChange() def paint(self, painter, *args): """Override.""" if self._picture is None: self.drawPicture() self._picture.play(painter) def boundingRect(self): """Override.""" if self._picture is None: self.drawPicture() return QRectF(self._picture.boundingRect())