def __save_atlas(self) -> None: """Save function as same as type synthesis widget.""" count = self.collection_list.count() if count < 1: return lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1) if not ok: return file_name = self.output_to("atlas image", qt_image_format) if not file_name: return icon_size = self.collection_list.iconSize() width = icon_size.width() image = self.collection_list.item(0).icon().pixmap(icon_size).toImage() image_main = QImage( QSize(lateral if count > lateral else count, (count // lateral) + bool(count % lateral)) * width, image.format()) image_main.fill(Qt.transparent) painter = QPainter(image_main) for row in range(count): image = self.collection_list.item(row).icon().pixmap( icon_size).toImage() painter.drawImage( QPointF(row % lateral, row // lateral) * width, image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(file_name) self.save_reply_box("Atlas", file_name)
def paintEvent(self, event): self.makeCurrent() gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glUseProgram(self.shaders_program) gl.glUniform1i(self.colormap_location, 0) gl.glActiveTexture(gl.GL_TEXTURE0 + 0) gl.glBindTexture(gl.GL_TEXTURE_1D, self.colormap_id) gl.glBegin(gl.GL_QUAD_STRIP) bar_start = -1 + self.text_height / self.height() * 2 bar_height = (1 - 2 * self.text_height / self.height()) * 2 steps = 40 for i in range(steps + 1): y = i * (1 / steps) # gl.glColor(y, 0, 0) gl.glVertex(-0.5, (bar_height * y + bar_start), y) gl.glVertex(0.5, (bar_height * y + bar_start), y) gl.glEnd() p = QPainter(self) p.drawText((self.width() - self.vmax_width) / 2, self.text_ascent, self.vmax_str) p.drawText((self.width() - self.vmin_width) / 2, self.height() - self.text_height + self.text_ascent, self.vmin_str) p.end()
def borderPath(self, rect): """ Calculate the painter path for a styled or rounded border When the canvas has no styled background or rounded borders the painter path is empty. :param QRect rect: Bounding rectangle of the canvas :return: Painter path, that can be used for clipping """ if self.testAttribute(Qt.WA_StyledBackground): recorder = QwtStyleSheetRecorder(rect.size()) painter = QPainter(recorder) opt = QStyleOption() opt.initFrom(self) opt.rect = rect self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self) painter.end() if not recorder.background.path.isEmpty(): return recorder.background.path if len(recorder.border.rectList) > 0: return qwtCombinePathList(rect, recorder.border.pathlist) elif self.__data.borderRadius > 0.0: fw2 = self.frameWidth() * 0.5 r = QRectF(rect).adjusted(fw2, fw2, -fw2, -fw2) path = QPainterPath() path.addRoundedRect(r, self.__data.borderRadius, self.__data.borderRadius) return path return QPainterPath()
def paintEvent(self, e): """Paint star on frame.""" qp = QPainter() qp.begin(self) self.drawStar(qp) qp.end()
def render_image(scene): image = QImage(scene.sceneRect().size().toSize(), QImage.Format_ARGB32) image.fill(Qt.transparent) painter = QPainter(image) scene.render(painter) painter.end() return image
def paintEvent(self, e): if self.points is None: return painter = QPainter(self) pen = QPen() # creates a default pen pen.setWidth(2) pen.setCapStyle(Qt.RoundCap) pen.setJoinStyle(Qt.RoundJoin) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing) # to avoid zero division m = max(max(self.points), 10) for i, v in enumerate(self.points): pen.setBrush(self.colors[min(v * len(self.colors) // m, len(self.colors) - 1)]) painter.setPen(pen) painter.drawLine( 40 + 5 * i, self.height() // 2 - min(v, self.height()) // 2, 40 + 5 * i, self.height() // 2 + min(v, self.height()) // 2, ) painter.end()
def paintEvent(self, event): # this puts the line numbers in the margin painter = QPainter(self) painter.fillRect(event.rect(), self.background) block = self.parent.firstVisibleBlock() font = self.parent.font() while block.isValid(): block_num = block.blockNumber() block_top = self.parent.blockBoundingGeometry(block).translated( self.parent.contentOffset()).top() # if the block is not visible stop wasting time if not block.isVisible() or block_top >= event.rect().bottom(): break if block_num == self.parent.textCursor().blockNumber(): font.setBold(True) painter.setFont(font) painter.setPen(self.highlight_color) background = self.highlight_background else: font.setBold(False) painter.setFont(font) painter.setPen(self.color) background = self.background text_rec = QRect(0, block_top, self.width(), self.parent.fontMetrics().height()) painter.fillRect(text_rec, background) painter.drawText(text_rec, Qt.AlignRight, str(block_num + 1)) block = block.next() painter.end() QWidget.paintEvent(self, event)
def findAscent(self, font): dummy = "E" white = QColor(Qt.white) fm = self.fontmetrics(font) pm = QPixmap(fm.width(dummy), fm.height()) pm.fill(white) p = QPainter(pm) p.setFont(font) p.drawText(0, 0, pm.width(), pm.height(), 0, dummy) p.end() img = pm.toImage() w = pm.width() linebytes = w * 4 for row in range(img.height()): if PYSIDE2: line = bytes(img.scanLine(row)) else: line = img.scanLine(row).asstring(linebytes) for col in range(w): color = struct.unpack("I", line[col * 4:(col + 1) * 4])[0] if color != white.rgb(): return fm.ascent() - row + 1 return fm.ascent()
def __save_atlas(self) -> None: """Saving all the atlas to image file. We should turn transparent background to white first. Then using QImage class to merge into one image. """ count = self.structure_list.count() if count < 1: return lateral = self.__save_atlas_ask() if not lateral: return file_name = self.output_to("atlas image", qt_image_format) if not file_name: return width = self.structure_list.iconSize().width() image_main = QImage(QSize( lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width ), self.__atlas_image(0).format()) image_main.fill(Qt.transparent) painter = QPainter(image_main) for row in range(count): image = self.__atlas_image(row) painter.drawImage(QPointF(row % lateral, row // lateral) * width, image) painter.end() pixmap = QPixmap.fromImage(image_main) pixmap.save(file_name) self.save_reply_box("Atlas", file_name)
def paintEvent(self, event): painter = QPainter(self) painter.setClipRegion(event.region()) if ( self.testPaintAttribute(self.BackingStore) and self.__data.backingStore is not None ): bs = self.__data.backingStore if QT_MAJOR_VERSION >= 5: pixelRatio = bs.devicePixelRatio() else: pixelRatio = 1.0 if bs.size() != self.size() * pixelRatio: bs = QwtPainter.backingStore(self, self.size()) if self.testAttribute(Qt.WA_StyledBackground): p = QPainter(bs) qwtFillBackground(p, self) self.drawCanvas(p, True) else: p = QPainter() if self.__data.borderRadius <= 0.0: # print('**DEBUG: QwtPlotCanvas.paintEvent') QwtPainter.fillPixmap(self, bs) p.begin(bs) self.drawCanvas(p, False) else: p.begin(bs) qwtFillBackground(p, self) self.drawCanvas(p, True) if self.frameWidth() > 0: self.drawBorder(p) p.end() painter.drawPixmap(0, 0, self.__data.backingStore) else: if self.testAttribute(Qt.WA_StyledBackground): if self.testAttribute(Qt.WA_OpaquePaintEvent): qwtFillBackground(painter, self) self.drawCanvas(painter, True) else: self.drawCanvas(painter, False) else: if self.testAttribute(Qt.WA_OpaquePaintEvent): if self.autoFillBackground(): qwtFillBackground(painter, self) qwtDrawBackground(painter, self) else: if self.borderRadius() > 0.0: clipPath = QPainterPath() clipPath.addRect(self.rect()) clipPath = clipPath.subtracted(self.borderPath(self.rect())) painter.save() painter.setClipPath(clipPath, Qt.IntersectClip) qwtFillBackground(painter, self) qwtDrawBackground(painter, self) painter.restore() self.drawCanvas(painter, False) if self.frameWidth() > 0: self.drawBorder(painter) if self.hasFocus() and self.focusIndicator() == self.CanvasFocusIndicator: self.drawFocusIndicator(painter)
def setData( self, x, height, width=0.8, bottom=None, *, align="center", fillcolor=None, edgecolor=None, ) -> None: # assume vertical cbook._check_in_list(["center", "edge"], align=align) y = bottom if y is None: y = 0 x, height, width, y = np.broadcast_arrays(np.atleast_1d(x), height, width, y) if align == "center": try: left = x - width / 2 except TypeError as e: raise TypeError( f"the dtypes of parameters x ({x.dtype}) " f"and width ({width.dtype}) " f"are incompatible" ) from e elif align == "edge": left = x else: raise RuntimeError(f"unknown align mode {align}") bottom = y # prepare to draw if edgecolor is None: edgecolor = (128, 128, 128) # getConfigOption("foreground") pen = mkPen(edgecolor) if fillcolor is None: fillcolor = (128, 128, 128) brush = mkBrush(fillcolor) self.qpicture = QPicture() self.path = QPainterPath() p = QPainter(self.qpicture) p.setPen(pen) p.setBrush(brush) # draw rects = zip(left, bottom, width, height) for l, b, w, h in rects: rect = QRectF(l, b, w, h) p.drawRect(rect) self.path.addRect(rect) p.end() self.prepareGeometryChange()
def paintEvent(self, event): """Qt method override to paint a custom image on the Widget.""" super(FigureCanvas, self).paintEvent(event) # Prepare the rect on which the image is going to be painted. fw = self.frameWidth() rect = QRect(0 + fw, 0 + fw, self.size().width() - 2 * fw, self.size().height() - 2 * fw) if self.fig is None or self._blink_flag: return # Prepare the scaled qpixmap to paint on the widget. if (self._qpix_scaled is None or self._qpix_scaled.size().width() != rect.width()): if self.fmt in ['image/png', 'image/jpeg']: self._qpix_scaled = self._qpix_orig.scaledToWidth( rect.width(), mode=Qt.SmoothTransformation) elif self.fmt == 'image/svg+xml': self._qpix_scaled = QPixmap(svg_to_image( self.fig, rect.size())) if self._qpix_scaled is not None: # Paint the image on the widget. qp = QPainter() qp.begin(self) qp.drawPixmap(rect, self._qpix_scaled) qp.end()
def paintEvent(self, event): """Qt method override to paint a custom image on the Widget.""" super(FigureCanvas, self).paintEvent(event) # Prepare the rect on which the image is going to be painted : fw = self.frameWidth() rect = QRect(0 + fw, 0 + fw, self.size().width() - 2 * fw, self.size().height() - 2 * fw) if self.fig is None or self._blink_flag: return # Check/update the qpixmap buffer : qpix2paint = None for qpix in self._qpix_buffer: if qpix.size().width() == rect.width(): qpix2paint = qpix break else: if self.fmt in ['image/png', 'image/jpeg']: qpix2paint = self._qpix_orig.scaledToWidth( rect.width(), mode=Qt.SmoothTransformation) elif self.fmt == 'image/svg+xml': qpix2paint = QPixmap(svg_to_image(self.fig, rect.size())) self._qpix_buffer.append(qpix2paint) if qpix2paint is not None: # Paint the image on the widget : qp = QPainter() qp.begin(self) qp.drawPixmap(rect, qpix2paint) qp.end()
class PyDMBitIndicator(QWidget): """ A QWidget which draws a colored circle or rectangle Parameters ---------- parent : QWidget The parent widget for the Label """ def __init__(self, parent=None, circle=False): super(PyDMBitIndicator, self).__init__(parent) self.setAutoFillBackground(True) self.circle = circle self._painter = QPainter() self._brush = QBrush(Qt.SolidPattern) self._pen = QPen(Qt.SolidLine) def paintEvent(self, event): """ Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved. Parameters ---------- event : QPaintEvent """ self._painter.begin(self) opt = QStyleOption() opt.initFrom(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, self._painter, self) self._painter.setRenderHint(QPainter.Antialiasing) self._painter.setBrush(self._brush) self._painter.setPen(self._pen) if self.circle: rect = event.rect() w = rect.width() h = rect.height() r = min(w, h) / 2.0 - 2.0 * max(self._pen.widthF(), 1.0) self._painter.drawEllipse(QPoint(w / 2.0, h / 2.0), r, r) else: self._painter.drawRect(event.rect()) self._painter.end() def setColor(self, color): """ Property for the color to be used when drawing Parameters ---------- QColor """ self._brush.setColor(color) self.update() def minimumSizeHint(self): fm = QFontMetrics(self.font()) return QSize(fm.height(), fm.height())
def paintEvent(self, evt): # get the widget dimensions orig_width = self.width() orig_height = self.height() # fill perc % of the widget perc = 1 width = int(orig_width * perc) height = int(orig_height * perc) # get the starting origin x_orig = int((orig_width - width) / 2) # we want to start at the bottom and draw up. y_orig = orig_height - int((orig_height - height) / 2) # a running x-position running_pos = x_orig # calculate to number of bars nbars = len(self.counts) # calculate the bar widths, this compilcation is # necessary because integer trunction severly cripples # the layout. remainder = width % nbars bar_width = [int(width / nbars)] * nbars for i in range(remainder): bar_width[i] += 1 paint = QPainter() paint.begin(self) # determine the scaling factor max_val = np.max(self.counts) scale = 1. * height / max_val # determine if we have a colormap and drop into the appopriate # loop. if hasattr(self.colormap[0], '__iter__'): # assume we have a colormap for i in range(len(self.counts)): bar_height = self.counts[i] r, g, b = self.colormap[i] paint.setPen(QColor(r, g, b)) paint.setBrush(QColor(r, g, b)) paint.drawRect(running_pos, y_orig, bar_width[i], -bar_height) running_pos += bar_width[i] else: # we have a tuple r, g, b = self.colormap paint.setPen(QColor(r, g, b)) paint.setBrush(QColor(r, g, b)) for i in range(len(self.counts)): bar_height = self.counts[i] * scale paint.drawRect(running_pos, y_orig, bar_width[i], -bar_height) running_pos += bar_width[i] paint.end()
class PyDMBitIndicator(QWidget): """ A QWidget which draws a colored circle or rectangle Parameters ---------- parent : QWidget The parent widget for the Label """ def __init__(self, parent=None, circle=False): super(PyDMBitIndicator, self).__init__(parent) self.setAutoFillBackground(True) self.circle = circle self._painter = QPainter() self._brush = QBrush(Qt.SolidPattern) self._pen = QPen(Qt.SolidLine) def paintEvent(self, event): """ Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved. Parameters ---------- event : QPaintEvent """ self._painter.begin(self) opt = QStyleOption() opt.initFrom(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, self._painter, self) self._painter.setRenderHint(QPainter.Antialiasing) self._painter.setBrush(self._brush) self._painter.setPen(self._pen) if self.circle: rect = self.rect() w = rect.width() h = rect.height() r = min(w, h) / 2.0 - 2.0 * max(self._pen.widthF(), 1.0) self._painter.drawEllipse(QPoint(w / 2.0, h / 2.0), r, r) else: self._painter.drawRect(self.rect()) self._painter.end() def setColor(self, color): """ Property for the color to be used when drawing Parameters ---------- QColor """ self._brush.setColor(color) self.update() def minimumSizeHint(self): fm = QFontMetrics(self.font()) return QSize(fm.height(), fm.height())
def toImage(self, *args): """ .. py:method:: toImage() :noindex: Convert the graphic to a `QImage` All pixels of the image get initialized by 0 ( transparent ) before the graphic is scaled and rendered on it. The format of the image is `QImage.Format_ARGB32_Premultiplied`. The size of the image is the default size ( ceiled to integers ) of the graphic. :return: The graphic as image in default size .. py:method:: toImage(size, [aspectRatioMode=Qt.IgnoreAspectRatio]) :noindex: Convert the graphic to a `QImage` All pixels of the image get initialized by 0 ( transparent ) before the graphic is scaled and rendered on it. The format of the image is `QImage.Format_ARGB32_Premultiplied`. :param QSize size: Size of the image :param `Qt.AspectRatioMode` aspectRatioMode: Aspect ratio how to scale the graphic :return: The graphic as image .. seealso:: :py:meth:`toPixmap()`, :py:meth:`render()` """ if len(args) == 0: if self.isNull(): return QImage() sz = self.defaultSize() w = np.ceil(sz.width()) h = np.ceil(sz.height()) image = QImage(w, h, QImage.Format_ARGB32) image.fill(0) r = QRect(0, 0, sz.width(), sz.height()) painter = QPainter(image) self.render(painter, r, Qt.KeepAspectRatio) painter.end() return image elif len(args) in (1, 2): size = args[0] aspectRatioMode = Qt.IgnoreAspectRatio if len(args) == 2: aspectRatioMode = args[-1] image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(0) r = QRect(0, 0, size.width(), size.height()) painter = QPainter(image) self.render(painter, r, aspectRatioMode) return image
def paintEvent(self, paintEvent): pen1 = QPen() pen1.setColor(self.color) painter = QPainter(self) painter.setPen(pen1) painter.begin(self) painter.drawRoundedRect(self.boundingRect(), 10, 10) # 绘制函数 painter.end()
def qwtPathGraphic(path, pen, brush): graphic = QwtGraphic() graphic.setRenderHint(QwtGraphic.RenderPensUnscaled) painter = QPainter(graphic) painter.setPen(pen) painter.setBrush(brush) painter.drawPath(path) painter.end() return graphic
def paintEvent(self, e): """Paint triangle on frame.""" qp = QPainter() qp.begin(self) self.drawTriangle(qp) perc = (self._value - self._min_value) / (self._max_value - self._min_value) self.drawLine(qp, self.rect().width() * perc) qp.end()
def get(self): """Override AbstractDataSetWidget method""" value = self.item.get() if value is not None: color = QColor(value) self.picture = QPicture() painter = QPainter() painter.begin(self.picture) painter.fillRect(QRect(0, 0, 60, 20), QBrush(color)) painter.end() self.group.setPicture(self.picture)
def square_pixmap(size): """Create a white/black hollow square pixmap. For use as labels cursor.""" pixmap = QPixmap(QSize(size, size)) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setPen(Qt.white) painter.drawRect(0, 0, size - 1, size - 1) painter.setPen(Qt.black) painter.drawRect(1, 1, size - 3, size - 3) painter.end() return pixmap
def render_to_svggen(scene, svg_gen): svg_gen.setSize(QSize(scene.width(), scene.height())) svg_gen.setViewBox(QRect(0, 0, scene.width(), scene.height())) svg_gen.setTitle("Hierarchic Component Drawing") svg_gen.setDescription("A Hierarchic Component Drawing created by " "Hildegard.") painter = QPainter() painter.begin(svg_gen) painter.setRenderHint(QPainter.Antialiasing) scene.render(painter) painter.end()
def _to_qimage(self): t = self._to_qgraphicstextitem() rect = t.boundingRect() height = rect.height() width = rect.width() pixmap = QPixmap(width, height) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) t.paint(painter, QStyleOptionGraphicsItem(), None) painter.end() return pixmap.toImage()
def paintEvent(self, event): painter = QPainter() x = 0 y = 0 if self._alignment & Qt.AlignLeft: x = 0 elif self._alignment & Qt.AlignRight: x = self.width() - self._diameter elif self._alignment & Qt.AlignHCenter: x = (self.width() - self._diameter) / 2 elif self._alignment & Qt.AlignJustify: x = 0 if self._alignment & Qt.AlignTop: y = 0 elif self._alignment & Qt.AlignBottom: y = self.height() - self._diameter elif self._alignment & Qt.AlignVCenter: y = (self.height() - self._diameter) / 2 gradient = QRadialGradient(x + self._diameter / 2, y + self._diameter / 2, self._diameter * 0.3, self._diameter * 0.1, self._diameter * 0.1) gradient.setColorAt(0, Qt.white) # ensure the border/halo is same color as gradient draw_color = QColor(self._color) if not self._state: # cut to black @ 70% for darker effect draw_color = QColor(Qt.black) if not self.isEnabled(): draw_color.setAlpha(30) pen_color = draw_color gradient.setColorAt(0.7, draw_color) painter.begin(self) brush = QBrush(gradient) painter.setPen(pen_color) painter.setRenderHint(QPainter.Antialiasing, True) painter.setBrush(brush) painter.drawEllipse(x + 1, y + 1, self._diameter - 2, self._diameter - 2) if self._flashRate > 0 and self._flashing: self._timer.start(self._flashRate) else: self._timer.stop() painter.end()
def circle_pixmap(size: int): """Create a white/black hollow circle pixmap. For use as labels cursor.""" size = max(int(size), 1) pixmap = QPixmap(QSize(size, size)) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setPen(Qt.white) painter.drawEllipse(0, 0, size - 1, size - 1) painter.setPen(Qt.black) painter.drawEllipse(1, 1, size - 3, size - 3) painter.end() return pixmap
def setData(self, x: np.ndarray = None, y: np.ndarray = None, z: np.ndarray = None): self.x, self.y, self.z = validate(x, y, z) shapeChanged = False if self.qpicture is None: shapeChanged = True elif (x is None) and (y is None) and (z is not None): if (z.shape[0] != self.x[:, 1][-1]) or (z.shape[1] != self.y[0][-1]): shapeChanged = True elif (x is not None) and (y is not None) and (z is not None): if np.any(self.x != x) or np.any(self.y != y): shapeChanged = True # initialize painting self.qpicture = QPicture() p = QPainter(self.qpicture) p.setPen( mkPen( self.edgecolors if self.edgecolors is not None else QColor(0, 0, 0, 0) ) ) if self.antialiasing: p.setRenderHint(QPainter.HighQualityAntialiasing) # transform self.z = np.ma.masked_array(self.z, mask=~np.isfinite(self.z)) norm = self.z - self.z.min() norm /= norm.max() norm *= len(self.lut) - 1 norm = norm.astype(int) # plot for yi in range(norm.shape[0]): for xi in range(norm.shape[1]): if norm.mask[yi, xi]: continue # TODO: support bad colors c = self.lut[norm[yi, xi]] p.setBrush(mkBrush(c)) rect = QRectF( QPointF(self.x[yi + 1, xi + 1], self.y[yi + 1, xi + 1]), QPointF(self.x[yi, xi], self.y[yi, xi]), ) p.drawRect(rect) # finish painting p.end() self.update() self.prepareGeometryChange() if shapeChanged: self.informViewBoundsChanged()
def qwtFillBackground(*args): if len(args) == 2: painter, canvas = args rects = [] if canvas.testAttribute(Qt.WA_StyledBackground): recorder = QwtStyleSheetRecorder(canvas.size()) p = QPainter(recorder) qwtDrawStyledBackground(canvas, p) p.end() if recorder.background.brush.isOpaque(): rects = recorder.clipRects else: rects += [canvas.rect()] else: r = canvas.rect() radius = canvas.borderRadius() if radius > 0.0: sz = QSizeF(radius, radius) rects += [ QRectF(r.topLeft(), sz), QRectF(r.topRight() - QPointF(radius, 0), sz), QRectF(r.bottomRight() - QPointF(radius, radius), sz), QRectF(r.bottomLeft() - QPointF(0, radius), sz), ] qwtFillBackground(painter, canvas, rects) elif len(args) == 3: painter, widget, fillRects = args if not fillRects: return if painter.hasClipping(): clipRegion = painter.transform().map(painter.clipRegion()) else: clipRegion = widget.contentsRect() bgWidget = qwtBackgroundWidget(widget.parentWidget()) for fillRect in fillRects: rect = QRectF(fillRect).toAlignedRect() if clipRegion.intersects(rect): pm = QPixmap(rect.size()) QwtPainter.fillPixmap( bgWidget, pm, widget.mapTo(bgWidget, rect.topLeft()) ) painter.drawPixmap(rect, pm) else: raise TypeError( "%s() takes 2 or 3 argument(s) (%s given)" % ("qwtFillBackground", len(args)) )
def paintEvent(self, event): QPushButton.paintEvent(self, event) qp = QPainter() qp.begin(self) font = qp.font() font.setPixelSize(self.font().pixelSize() * 0.6) font.setWeight(QFont.Normal) qp.setFont(font) #qp.drawText(event.rect().translated(2, 2), str(self._atomic_number)) qp.end()
def paintEvent(self, event): QPushButton.paintEvent(self, event) color = self.color() padding = self.padding() rect = event.rect() painter = QPainter() painter.begin(self) painter.setBrush(QBrush(color)) painter.setPen(Qt.NoPen) rect.adjust(padding, padding, -1 - padding, -1 - padding) painter.drawRect(rect) painter.end()
def paintEvent(self, event): painter = QPainter() x = 0 y = 0 if self._alignment & Qt.AlignLeft: x = 0 elif self._alignment & Qt.AlignRight: x = self.width() - self._diameter elif self._alignment & Qt.AlignHCenter: x = (self.width() - self._diameter) / 2 elif self._alignment & Qt.AlignJustify: x = 0 if self._alignment & Qt.AlignTop: y = 0 elif self._alignment & Qt.AlignBottom: y = self.height() - self._diameter elif self._alignment & Qt.AlignVCenter: y = (self.height() - self._diameter) / 2 # get the fill draw color set from QTDesigner draw_color = QColor(self._color) # set the pen color, we want to use this even if the state is OFF pen_color = draw_color if not self._state: # LED state is OFF, set fill draw_color = QColor(Qt.black) # dim if control is not enabled if not self.isEnabled(): draw_color.setAlpha(30) # Start actual painting process painter.begin(self) brush = QBrush(draw_color) painter.setPen(pen_color) painter.setRenderHint(QPainter.Antialiasing, True) painter.setBrush(brush) painter.drawEllipse(x + 1, y + 1, self._diameter - 2, self._diameter - 2) # Does flashing make sense for Monokrom style? if self._flashRate > 0 and self._flashing: self._timer.start(self._flashRate) else: self._timer.stop() painter.end()
def paintEvent(self, event): scaled_background = self.background_pixmap.scaled(self.rescale_w(self.background_pixmap.width()), self.rescale_h(self.background_pixmap.height()), Qt.KeepAspectRatio, Qt.SmoothTransformation) scaled_mantid = self.mantid_pixmap.scaled(self.rescale_w(self.mantid_pixmap.width()), self.rescale_h(self.mantid_pixmap.height()), Qt.KeepAspectRatio, Qt.SmoothTransformation) qp = QPainter() qp.begin(self) qp.drawPixmap(0, 0, scaled_background) qp.drawPixmap(self.width() - scaled_mantid.width(), self.height()-scaled_mantid.height(), scaled_mantid) qp.end()
def drawColorBar(self, painter, colorMap, interval, scaleMap, orientation, rect): """ Draw a color bar into a rectangle :param QPainter painter: Painter :param qwt.color_map.QwtColorMap colorMap: Color map :param qwt.interval.QwtInterval interval: Value range :param qwt.scalemap.QwtScaleMap scaleMap: Scale map :param Qt.Orientation orientation: Orientation :param QRectF rect: Target rectangle """ colorTable = [] if colorMap.format() == QwtColorMap.Indexed: colorTable = colorMap.colorTable(interval) c = QColor() devRect = rect.toAlignedRect() pixmap = QPixmap(devRect.size()) pixmap.fill(Qt.transparent) pmPainter = QPainter(pixmap) pmPainter.translate(-devRect.x(), -devRect.y()) if orientation == Qt.Horizontal: sMap = QwtScaleMap(scaleMap) sMap.setPaintInterval(rect.left(), rect.right()) for x in range(devRect.left(), devRect.right() + 1): value = sMap.invTransform(x) if colorMap.format() == QwtColorMap.RGB: c.setRgba(colorMap.rgb(interval, value)) else: c = colorTable[colorMap.colorIndex(interval, value)] pmPainter.setPen(c) pmPainter.drawLine( QLineF(x, devRect.top(), x, devRect.bottom())) else: sMap = QwtScaleMap(scaleMap) sMap.setPaintInterval(rect.bottom(), rect.top()) for y in range(devRect.top(), devRect.bottom() + 1): value = sMap.invTransform(y) if colorMap.format() == QwtColorMap.RGB: c.setRgba(colorMap.rgb(interval, value)) else: c = colorTable[colorMap.colorIndex(interval, value)] pmPainter.setPen(c) pmPainter.drawLine( QLineF(devRect.left(), y, devRect.right(), y)) pmPainter.end() self.drawPixmap(painter, rect, pixmap)
class QScale(QFrame): """ A bar-shaped indicator for scalar value. Configurable features include indicator type (bar/pointer), scale tick marks and orientation (horizontal/vertical). Parameters ---------- parent : QWidget The parent widget for the Scale """ def __init__(self, parent=None): super(QScale, self).__init__(parent) self._value = 1 self._lower_limit = -5 self._upper_limit = 5 self.position = None # unit: pixel self._bg_color = QColor('darkgray') self._bg_size_rate = 0.8 # from 0 to 1 self._indicator_color = QColor('black') self._pointer_width_rate = 0.05 self._barIndicator = False self._num_divisions = 10 self._show_ticks = True self._tick_pen = QPen() self._tick_color = QColor('black') self._tick_width = 0 self._tick_size_rate = 0.1 # from 0 to 1 self._painter = QPainter() self._painter_rotation = None self._painter_translation_y = None self._painter_translation_x = None self._painter_scale_x = None self._flip_traslation_y = None self._flip_scale_y = None self._widget_width = self.width() self._widget_height = self.height() self._orientation = Qt.Horizontal self._inverted_appearance = False self._flip_scale = False self._scale_height = 35 self._origin_at_zero = False self._origin_position = 0 self.set_position() def adjust_transformation(self): """ This method sets parameters for the widget transformations (needed to for orientation, flipping and appearance inversion). """ self.setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) # Unset fixed size if self._orientation == Qt.Horizontal: self._widget_width = self.width() self._widget_height = self.height() self._painter_translation_y = 0 self._painter_rotation = 0 self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.setFixedHeight(self._scale_height) elif self._orientation == Qt.Vertical: # Invert dimensions for paintEvent() self._widget_width = self.height() self._widget_height = self.width() self._painter_translation_y = self._widget_width self._painter_rotation = -90 self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.setFixedWidth(self._scale_height) if self._inverted_appearance: self._painter_translation_x = self._widget_width self._painter_scale_x = -1 else: self._painter_translation_x = 0 self._painter_scale_x = 1 if self._flip_scale: self._flip_traslation_y = self._widget_height self._flip_scale_y = -1 else: self._flip_traslation_y = 0 self._flip_scale_y = 1 def set_tick_pen(self): """ Define pen style for drawing scale tick marks. """ self._tick_pen.setColor(self._tick_color) self._tick_pen.setWidth(self._tick_width) def draw_ticks(self): """ Draw tick marks on the scale. """ if not self._show_ticks: return self.set_tick_pen() self._painter.setPen(self._tick_pen) division_size = self._widget_width / self._num_divisions tick_y0 = self._widget_height tick_yf = (1 - self._tick_size_rate)*self._widget_height for i in range(self._num_divisions+1): x = i*division_size self._painter.drawLine(x, tick_y0, x, tick_yf) # x1, y1, x2, y2 def draw_bar(self): """ Draw a bar as indicator of current value. """ self.set_origin() self.set_position() if self.position < 0 or self.position > self._widget_width: return self._painter.setPen(Qt.transparent) self._painter.setBrush(self._indicator_color) bar_width = self.position - self._origin_position bar_height = self._bg_size_rate * self._widget_height self._painter.drawRect(self._origin_position, 0, bar_width, bar_height) def draw_pointer(self): """ Draw a pointer as indicator of current value. """ self.set_position() if self.position < 0 or self.position > self._widget_width: return self._painter.setPen(Qt.transparent) self._painter.setBrush(self._indicator_color) pointer_width = self._pointer_width_rate * self._widget_width pointer_height = self._bg_size_rate * self._widget_height points = [ QPoint(self.position, 0), QPoint(self.position + 0.5*pointer_width, 0.5*pointer_height), QPoint(self.position, pointer_height), QPoint(self.position - 0.5*pointer_width, 0.5*pointer_height) ] self._painter.drawPolygon(QPolygon(points)) def draw_indicator(self): """ Draw the selected indicator for current value. """ if self._barIndicator: self.draw_bar() else: self.draw_pointer() def draw_background(self): """ Draw the background of the scale. """ self._painter.setPen(Qt.transparent) self._painter.setBrush(self._bg_color) bg_width = self._widget_width bg_height = self._bg_size_rate * self._widget_height self._painter.drawRect(0, 0, bg_width, bg_height) def paintEvent(self, event): """ Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved. Parameters ---------- event : QPaintEvent """ self.adjust_transformation() self._painter.begin(self) self._painter.translate(0, self._painter_translation_y) # Draw vertically if needed self._painter.rotate(self._painter_rotation) self._painter.translate(self._painter_translation_x, 0) # Invert appearance if needed self._painter.scale(self._painter_scale_x, 1) self._painter.translate(0, self._flip_traslation_y) # Invert scale if needed self._painter.scale(1, self._flip_scale_y) self._painter.setRenderHint(QPainter.Antialiasing) self.draw_background() self.draw_ticks() self.draw_indicator() self._painter.end() def calculate_position_for_value(self, value): """ Calculate the position (pixel) in which the pointer should be drawn for a given value. """ if value < self._lower_limit or value > self._upper_limit or \ self._upper_limit - self._lower_limit == 0: proportion = -1 # Invalid else: proportion = (value - self._lower_limit) / (self._upper_limit - self._lower_limit) position = int(proportion * self._widget_width) return position def set_origin(self): """ Set the position (pixel) in which the origin should be drawn. """ if self._origin_at_zero: self._origin_position = self.calculate_position_for_value(0) else: self._origin_position = 0 def set_position(self): """ Set the position (pixel) in which the pointer should be drawn. """ self.position = self.calculate_position_for_value(self._value) def update_indicator(self): """ Update the position and the drawing of indicator. """ self.set_position() self.repaint() def set_value(self, value): """ Set a new current value for the indicator. """ self._value = value self.update_indicator() def set_upper_limit(self, new_limit): """ Set the scale upper limit. Parameters ---------- new_limit : float The upper limit of the scale. """ self._upper_limit = new_limit def set_lower_limit(self, new_limit): """ Set the scale lower limit. Parameters ---------- new_limit : float The lower limit of the scale. """ self._lower_limit = new_limit def get_show_ticks(self): return self._show_ticks def set_show_ticks(self, checked): if self._show_ticks != bool(checked): self._show_ticks = checked self.repaint() def get_orientation(self): return self._orientation def set_orientation(self, orientation): self._orientation = orientation self.adjust_transformation() self.repaint() def get_flip_scale(self): return self._flip_scale def set_flip_scale(self, checked): self._flip_scale = bool(checked) self.adjust_transformation() self.repaint() def get_inverted_appearance(self): return self._inverted_appearance def set_inverted_appearance(self, inverted): self._inverted_appearance = inverted self.adjust_transformation() self.repaint() def get_bar_indicator(self): return self._barIndicator def set_bar_indicator(self, checked): if self._barIndicator != bool(checked): self._barIndicator = checked self.repaint() def get_background_color(self): return self._bg_color def set_background_color(self, color): self._bg_color = color self.repaint() def get_indicator_color(self): return self._indicator_color def set_indicator_color(self, color): self._indicator_color = color self.repaint() def get_tick_color(self): return self._tick_color def set_tick_color(self, color): self._tick_color = color self.repaint() def get_background_size_rate(self): return self._bg_size_rate def set_background_size_rate(self, rate): if rate >= 0 and rate <=1 and self._bg_size_rate != rate: self._bg_size_rate = rate self.repaint() def get_tick_size_rate(self): return self._tick_size_rate def set_tick_size_rate(self, rate): if rate >= 0 and rate <=1 and self._tick_size_rate != rate: self._tick_size_rate = rate self.repaint() def get_num_divisions(self): return self._num_divisions def set_num_divisions(self, divisions): if isinstance(divisions, int) and divisions > 0 and self._num_divisions != divisions: self._num_divisions = divisions self.repaint() def get_scale_height(self): return self._scale_height def set_scale_height(self, value): self._scale_height = int(value) self.adjust_transformation() self.repaint() def get_origin_at_zero(self): return self._origin_at_zero def set_origin_at_zero(self, checked): if self._origin_at_zero != bool(checked): self._origin_at_zero = checked self.repaint()
class PyDMSymbol(QWidget, PyDMWidget): """ PyDMSymbol will render an image (symbol) for each value of a channel. Parameters ---------- parent : QWidget The parent widget for the Label init_channel : str, optional The channel to be used by the widget. """ def __init__(self, parent=None, init_channel=None): QWidget.__init__(self, parent) PyDMWidget.__init__(self, init_channel=init_channel) if 'Index' not in PyDMSymbol.RULE_PROPERTIES: PyDMSymbol.RULE_PROPERTIES = PyDMWidget.RULE_PROPERTIES.copy() PyDMSymbol.RULE_PROPERTIES.update( {'Index': ['set_current_key', object]}) self.app = QApplication.instance() self._current_key = 0 self._state_images_string = "" self._state_images = {} # Keyed on state values (ints), values are (filename, qpixmap or qsvgrenderer) tuples. self._aspect_ratio_mode = Qt.KeepAspectRatio self._sizeHint = self.minimumSizeHint() self._painter = QPainter() def init_for_designer(self): """ Method called after the constructor to tweak configurations for when using the widget with the Qt Designer """ self.value = 0 self._current_key = 0 def set_current_key(self, current_key): """ Change the image being displayed for the one given by `current_key`. Parameters ---------- current_key : object The current_key parameter can be of any type as long as it matches the type used as key for the imageFiles dictionary. """ if self._current_key != current_key: self._current_key = current_key self.update() @Property(str) def imageFiles(self): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Returns ------- str """ if not self._state_images: return self._state_images_string return json.dumps({str(state): val[0] for (state, val) in self._state_images.items()}) @imageFiles.setter def imageFiles(self, new_files): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Parameters ---------- new_files : str """ self._state_images_string = str(new_files) try: new_file_dict = json.loads(self._state_images_string) except Exception: self._state_images = {} return self._sizeHint = QSize(0, 0) for (state, filename) in new_file_dict.items(): if is_pydm_app(): try: file_path = self.app.get_path(filename) except Exception as e: logger.exception("Couldn't get file with path %s", filename) file_path = filename else: file_path = filename # First, lets try SVG. We have to try SVG first, otherwise # QPixmap will happily load the SVG and turn it into a raster image. # Really annoying: We have to try to load the file as SVG, # and we expect it will fail often (because many images aren't SVG). # Qt prints a warning message to stdout any time SVG loading fails. # So we have to temporarily silence Qt warning messages here. qInstallMessageHandler(self.qt_message_handler) svg = QSvgRenderer() svg.repaintNeeded.connect(self.update) if svg.load(file_path): self._state_images[int(state)] = (filename, svg) self._sizeHint = self._sizeHint.expandedTo(svg.defaultSize()) qInstallMessageHandler(None) continue qInstallMessageHandler(None) # SVG didn't work, lets try QPixmap image = QPixmap(file_path) if not image.isNull(): self._state_images[int(state)] = (filename, image) self._sizeHint = self._sizeHint.expandedTo(image.size()) continue # If we get this far, the file specified could not be loaded at all. logger.error("Could not load image: {}".format(filename)) self._state_images[int(state)] = (filename, None) @Property(Qt.AspectRatioMode) def aspectRatioMode(self): """ Which aspect ratio mode to use. Returns ------- Qt.AspectRatioMode """ return self._aspect_ratio_mode @aspectRatioMode.setter def aspectRatioMode(self, new_mode): """ Which aspect ratio mode to use. Parameters ----------- new_mode : Qt.AspectRatioMode """ if new_mode != self._aspect_ratio_mode: self._aspect_ratio_mode = new_mode self.update() def connection_changed(self, connected): """ Callback invoked when the connection state of the Channel is changed. This callback acts on the connection state to enable/disable the widget and also trigger the change on alarm severity to ALARM_DISCONNECTED. Parameters ---------- connected : int When this value is 0 the channel is disconnected, 1 otherwise. """ super(PyDMSymbol, self).connection_changed(connected) self.update() def value_changed(self, new_val): """ Callback invoked when the Channel value is changed. Parameters ---------- new_val : int The new value from the channel. """ super(PyDMSymbol, self).value_changed(new_val) self._current_key = new_val self.update() def sizeHint(self): """ This property holds the recommended size for the widget. Returns ------- QSize """ return self._sizeHint def minimumSizeHint(self): """ This property holds the recommended minimum size for the widget. Returns ------- QSize """ return QSize(10, 10) # This is totally arbitrary, I just want *some* visible nonzero size def paintEvent(self, event): """ Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved. At PyDMSymbol this method handles the alarm painting with parameters from the stylesheet and draws the proper image. Parameters ---------- event : QPaintEvent """ self._painter.begin(self) opt = QStyleOption() opt.initFrom(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, self._painter, self) # self._painter.setRenderHint(QPainter.Antialiasing) if self._current_key is None: self._painter.end() return image_to_draw = self._state_images.get(self._current_key, (None, None))[1] if image_to_draw is None: self._painter.end() return if isinstance(image_to_draw, QPixmap): w = float(image_to_draw.width()) h = float(image_to_draw.height()) if self._aspect_ratio_mode == Qt.IgnoreAspectRatio: scale = (event.rect().width() / w, event.rect().height() / h) elif self._aspect_ratio_mode == Qt.KeepAspectRatio: sf = min(event.rect().width() / w, event.rect().height() / h) scale = (sf, sf) elif self._aspect_ratio_mode == Qt.KeepAspectRatioByExpanding: sf = max(event.rect().width() / w, event.rect().height() / h) scale = (sf, sf) self._painter.scale(scale[0], scale[1]) self._painter.drawPixmap(event.rect().x(), event.rect().y(), image_to_draw) elif isinstance(image_to_draw, QSvgRenderer): draw_size = QSizeF(image_to_draw.defaultSize()) draw_size.scale(QSizeF(event.rect().size()), self._aspect_ratio_mode) image_to_draw.render(self._painter, QRectF(0.0, 0.0, draw_size.width(), draw_size.height())) self._painter.end() def qt_message_handler(self, msg_type, *args): # Intentionally suppress all qt messages. Make sure not to leave this handler installed. pass