def paintEvent(self, event=None): font = QFont(self.font()) font.setPointSize(font.pointSize() - 1) fm = QFontMetricsF(font) fracWidth = fm.width(FractionSlider.WSTRING) indent = fm.boundingRect("9").width() / 2.0 if not X11: fracWidth *= 1.5 span = self.width() - (FractionSlider.XMARGIN * 2) value = self.__numerator / float(self.__denominator) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) painter.setPen(self.palette().color(QPalette.Mid)) painter.setBrush(self.palette().brush(QPalette.AlternateBase)) painter.drawRect(self.rect()) segColor = QColor(Qt.green).darker(120) segLineColor = segColor.darker() painter.setPen(segLineColor) painter.setBrush(segColor) painter.drawRect(FractionSlider.XMARGIN, FractionSlider.YMARGIN, span, fm.height()) textColor = self.palette().color(QPalette.Text) segWidth = span / self.__denominator segHeight = fm.height() * 2 nRect = fm.boundingRect(FractionSlider.WSTRING) x = FractionSlider.XMARGIN yOffset = segHeight + fm.height() for i in range(self.__denominator + 1): painter.setPen(segLineColor) painter.drawLine(x, FractionSlider.YMARGIN, x, segHeight) painter.setPen(textColor) y = segHeight rect = QRectF(nRect) rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) # painter.drawText(rect, Qt.AlignCenter, # QString.number(i)) painter.drawText(rect, Qt.AlignCenter, str(i)) y = yOffset rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) painter.drawText(rect, Qt.AlignCenter, str(self.__denominator)) painter.drawLine(QPointF(rect.left() + indent, y), QPointF(rect.right() - indent, y)) x += segWidth span = int(span) y = FractionSlider.YMARGIN - 0.5 triangle = [ QPointF(value * span, y), QPointF((value * span) + (2 * FractionSlider.XMARGIN), y), QPointF((value * span) + FractionSlider.XMARGIN, fm.height()) ] painter.setPen(Qt.yellow) painter.setBrush(Qt.darkYellow) painter.drawPolygon(QPolygonF(triangle))
def _drawSuffixIon(self, qp: QPainter, index_reverse: int, metrics_ion: QFontMetricsF, pos_end: QPointF, pos_right: QPointF) -> None: """ Draws existing suffix ion(s) and the right line at this position. Parameters ---------- qp : QPainter The QPainter class provides functions required to paint within the widget index_reverse: int The position of the suffix ion(s) within the peptide. The positions are in reverse order compared to the prefix ion(s) metrics_ion : QFontMetricsF The font metrics of the ion(s) for the given font pos_end : QPointF The start position of the right line pos_right : QPointF The end position of the right line """ qp.setPen(self._getPen(self.colors["red"])) suffix_ions = sorted(self.suffix[index_reverse], reverse=True) blank_ion: int = 5 for ion in suffix_ions: height_ion: float = metrics_ion.boundingRect(ion).height() pos_ion = QPointF(pos_end.x() + 2.5, pos_right.y() - blank_ion) qp.drawText(pos_ion, ion) blank_ion += height_ion
def _drawPrefixIon(self, qp: QPainter, index: int, metrics_ion: QFontMetricsF, pos_left: QPointF) -> None: """ Draws existing prefix ion(s) and the left line at this position. Parameters ---------- qp : QPainter The QPainter class provides functions required to paint within the widget index: int The position of the prefix ion(s) within the peptide metrics_ion : QFontMetricsF The font metrics of the ion(s) for the given font pos_left : QPointF The coordination of the left line provided for the prefix ion(s) """ qp.setPen(self._getPen(self.colors["blue"])) prefix_ions = sorted(self.prefix[index]) blank_ion: int = 10 for ion in prefix_ions: height_ion: float = metrics_ion.boundingRect(ion).height() pos_ion = QPointF(pos_left.x(), pos_left.y() + blank_ion) qp.drawText(pos_ion, ion) blank_ion += height_ion
def reposition(self): fm = QFontMetricsF(self._font, self) rect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter, str(self._value)) self._xpos = -rect.width() / 2.0 self._ypos = rect.height() / 2.0 - fm.descent() self.update()
def rescale(self): fm = QFontMetricsF(self._font, self) maxRect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter, str(self._maximum)) xscale = float(self.width()) / maxRect.width() yscale = float(self.height()) / maxRect.height() self._scale = min(xscale, yscale)
def reposition(self): fm = QFontMetricsF(self._font, self) rect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter, str(self._value)) self._xpos = -rect.width()/2.0 self._ypos = rect.height()/2.0 - fm.descent() self.update()
def rescale(self): fm = QFontMetricsF(self._font, self) maxRect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter, str(self._maximum)) xscale = float(self.width())/maxRect.width() yscale = float(self.height())/maxRect.height() self._scale = min(xscale, yscale)
def __outline_rect(self): """:rtype QRectF""" padding = 8 metrics = QFontMetricsF() rect = metrics.boundingRect(self.text) """:type rect: QRectF""" rect.adjust(-padding, -padding, padding, padding) rect.translate(-rect.center()) return rect
def _drawGridDivs_x(self, painter: QPainter, step: float): """отрисовка значений делений на оси X""" if len(self._charts) > 0: logger.debug(self._drawGridDivs_x.__doc__) axis: Axis = self._charts[self._base_chart].getAxis('x') fm = QFontMetricsF(self._style['grid']['font']) for i, div in axis.generateDivSteps(): text = str(round(div, 8)) offset_x = self._margins[0] - fm.boundingRect(text).width() / 2.0 offset_y = self.height() - self._margins[3] + fm.height() + 5 painter.drawText(QPointF(offset_x + i * step, offset_y), text)
def _drawGridDivs_x(self, painter: QPainter, step: float): """отрисовка значений делений на оси X""" if not self._grid_divs['x0'].is_ready: return # logger.debug(self._drawGridDivs_x.__doc__) f_m = QFontMetricsF(self._style['grid']['font']) divs = self._grid_divs['x0'].divs pen = painter.pen() painter.setPen(self._style['grid']['border']) for i, div in enumerate(divs): text = str(div) offset_x = self._margins[0] - f_m.boundingRect(text).width() / 2.0 offset_y = self.height() - self._margins[3] + f_m.height() + 5 painter.drawText(QPointF(offset_x + i * step, offset_y), text) painter.setPen(pen)
def _draw_volume_axes(self, painter): painter.save() metrics = QFontMetricsF(painter.font()) scale_factor = decompose_matrix(self._model)[0] pen = QPen() origin = self._project([0] * 3) for i in range(3): pt = [0] * 3 pt[i] = 1 # axis line color = [0] * 3 color[i] = 255 pen.setColor(QColor(*color)) painter.setPen(pen) brush = QBrush(QColor(*color), Qt.SolidPattern) painter.setBrush(brush) pt = self._project(pt) painter.drawLine(QPointF(*origin), QPointF(*pt)) circle = QRectF(-1.5, -1.5, 3, 3) circle.translate(*pt) painter.drawEllipse(circle) # axis label pen.setColor(QColor(255, 255, 255)) painter.setPen(pen) text = f'{self._state.cropped_shape_mm[::-1][i]:.2f} mm\n{self._state.cropped_shape_vx[::-1][i]} vx' if abs(scale_factor[::-1][i] - 1) > 1e-2: text += f'\n({scale_factor[::-1][i]:.2f}x)' bounds = metrics.boundingRect(QRectF(-100, -100, 200, 200), Qt.AlignCenter, text) eps = 1e-6 norm = (pt - origin) / (numpy.linalg.norm(pt - origin) + eps) shift = numpy.abs([bounds.width(), bounds.height()] / (norm + eps) / 2) bounds.translate(*(pt + (min(shift) + 5) * norm)) painter.drawText(bounds, Qt.AlignCenter, text) painter.restore()
def syncWithMapObject(self, renderer): nameVisible = self.mObject.isVisible() and self.mObject.name()!='' self.setVisible(nameVisible) if (not nameVisible): return metrics = QFontMetricsF(QGuiApplication.font()) boundingRect = metrics.boundingRect(self.mObject.name()) boundingRect.translate(-boundingRect.width() / 2, -labelDistance) boundingRect.adjust(-labelMargin*2, -labelMargin, labelMargin*2, labelMargin) pixelPos = renderer.pixelToScreenCoords_(self.mObject.position()) bounds = objectBounds(self.mObject, renderer) # Adjust the bounding box for object rotation transform = QTransform() transform.translate(pixelPos.x(), pixelPos.y()) transform.rotate(self.mObject.rotation()) transform.translate(-pixelPos.x(), -pixelPos.y()) bounds = transform.mapRect(bounds) # Center the object name on the object bounding box pos = QPointF((bounds.left() + bounds.right()) / 2, bounds.top()) self.setPos(pos + self.mObject.objectGroup().offset()) if (self.mBoundingRect != boundingRect): self.prepareGeometryChange() self.mBoundingRect = boundingRect
def syncWithMapObject(self, renderer): nameVisible = self.mObject.isVisible() and self.mObject.name() != '' self.setVisible(nameVisible) if (not nameVisible): return metrics = QFontMetricsF(QGuiApplication.font()) boundingRect = metrics.boundingRect(self.mObject.name()) boundingRect.translate(-boundingRect.width() / 2, -labelDistance) boundingRect.adjust(-labelMargin * 2, -labelMargin, labelMargin * 2, labelMargin) pixelPos = renderer.pixelToScreenCoords_(self.mObject.position()) bounds = objectBounds(self.mObject, renderer) # Adjust the bounding box for object rotation transform = QTransform() transform.translate(pixelPos.x(), pixelPos.y()) transform.rotate(self.mObject.rotation()) transform.translate(-pixelPos.x(), -pixelPos.y()) bounds = transform.mapRect(bounds) # Center the object name on the object bounding box pos = QPointF((bounds.left() + bounds.right()) / 2, bounds.top()) self.setPos(pos + self.mObject.objectGroup().offset()) if (self.mBoundingRect != boundingRect): self.prepareGeometryChange() self.mBoundingRect = boundingRect
def _fragmentPeptide(self, qp: QPainter) -> None: """ The sequence will be generated stepwise by drawing each aa of the sequence separately and adding in each step lines and existing ions. The procedure can be described in two steps: 1. Check if sequence is given, if so then transform seq into a dictionary (with the indices representing the positions of the chars). 2. For each char in the sequence: Firstly, calculate start position of char (be aware that the char rect is created at the left bottom corner of the char, meaning we have to add the height of the Font & possible suffixes to the starting height position to move it into the center of the window). Secondly, calculate the center point for the vertical Line. The Line consists of a point start and point end. The starting line xPos yield in the start_point + blank - (SPACE/2), where blank represents the additional space from the starting point after each new char. Third, if prefix or suffix ions are given, then distinguish between suffix and prefix to draw the vertical line with either left or right line or both. Because of changing the fonts for the ions, the fonts needs to be reset. Parameters ---------- qp : QPainter The QPainter class provides functions required to paint within the widget """ blankspace: int = 8 if self.sequence != "": seq = list(self.sequence) dict_seq = {i: seq[i] for i in range(0, len(seq))} metrics = QFontMetricsF(self.getFont_Pep()) blank: int = 0 for i, s in dict_seq.items(): i_rev = self._getReverseIndex(i, dict_seq) width = metrics.boundingRect(s).width() height = metrics.boundingRect(s).height() start_point = 0 # position of char with center indent position = QPointF(start_point + blank, SequenceIonsWidget.SUFFIX_HEIGHT + height) qp.drawText(position, s) # position lines for possible ions centerOfLine = \ ( SequenceIonsWidget.SUFFIX_HEIGHT + height - height / 4 ) - 1 start_linePos = QPointF(start_point + blank - (blankspace / 2), centerOfLine - height / 2 - 2.5) end_linePos = QPointF(start_linePos.x(), centerOfLine + height / 2 + 2.5) qp.setFont(self.getFont_Ion()) metrics_ion = QFontMetricsF(self.getFont_Ion()) if i in self.prefix: left_linePos = self._drawIonsLines(qp, start_linePos, end_linePos, blankspace, "prefix") self._drawPrefixIon(qp, i, metrics_ion, left_linePos) # for given line of existing prefix, expand with given suffix if i in self.prefix and i_rev in self.suffix: right_linePos = self._drawIonsLines( qp, start_linePos, end_linePos, blankspace, "suffix") self._drawSuffixIon(qp, i_rev, metrics_ion, end_linePos, right_linePos) elif i_rev in self.suffix and i not in self.prefix: right_linePos = self._drawIonsLines( qp, start_linePos, end_linePos, blankspace, "suffix") self._drawSuffixIon(qp, i_rev, metrics_ion, start_linePos, right_linePos) blank += width + blankspace qp.setPen(self._getPen(self.colors["black"])) qp.setFont(self.getFont_Pep())
def paintEvent(self, e): # ref: https://forums.khronos.org/showthread.php/62124 # self._projection = perspective(30 * self.height() / 512, self.width() / self.height(), 0.01, 100) s = 1 / tan(radians(self._state.projection_fov) / 2) self._projection = perspective2(s * 512 / self.height(), s * 512 / self.width(), 0.01, 100) self._viewport = viewport(0, self.height(), self.width(), -self.height()) self._crop_corners = list(product(*self._state.volume_crop)) pts = [self._project(c) for c in self._crop_corners] top_left = [ min([c[i] - self._screen_bounds_padding for c in pts]) for i in range(2) ] bottom_right = [ max([c[i] + self._screen_bounds_padding for c in pts]) for i in range(2) ] self._screen_bounds_render = [[ quantized_floor(x, self._scale_render) for x in top_left ], [quantized_ceil(x, self._scale_render) for x in bottom_right]] self._screen_bounds_display = [[ quantized_floor(x, self._scale_display) for x in top_left ], [quantized_ceil(x, self._scale_display) for x in bottom_right]] self._resolution_render = ( (numpy.array(self._screen_bounds_render[1]) - self._screen_bounds_render[0]) // self._scale_render).astype( numpy.intp) painter = QPainter(self) # background if self._transparency: painter.fillRect(self.rect(), Qt.magenta) else: painter.fillRect(self.rect(), Qt.black) # volume self._draw_volume(painter) # annotations if self._annotations > 0: painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) self._draw_volume_axes(painter) self._draw_volume_bounding_box(painter) metrics = QFontMetricsF(painter.font()) pen = QPen() pen.setColor(QColor(255, 255, 255)) painter.setPen(pen) dt = numpy.mean(self._render_times or [0]) self._render_times = self._render_times[-10:] lines = [ (2, f'{self._state.display_volume.renderer.type} {1e3*dt:6.1f} ms {1/(dt+1e-6):6.1f} fps'), (2, f'{self._resolution_display[0]} \u00d7 {self._resolution_display[1]} px'.ljust(15) \ + f'{self._state.display_volume.shape[0]} \u00d7 {self._state.display_volume.shape[1]} \u00d7 {self._state.display_volume.shape[2]} vx'), (1, f'{self._state.volume_position+1} of {self._state.volume_count}'), (1, f'{self._resolution_render[0]} \u00d7 {self._resolution_render[1]} px'), (2, f'{self._state.acquired_shape_mm[0]:.2f} \u00d7 {self._state.acquired_shape_mm[1]:.2f} \u00d7 {self._state.acquired_shape_mm[2]:.2f} mm'), (2, f'{self._state.acquired_shape_vx[0]} \u00d7 {self._state.acquired_shape_vx[1]} \u00d7 {self._state.acquired_shape_vx[2]} vx'), (1, self._state.filename), ] i = 0 for (lvl, line) in reversed(lines): if self._annotations >= lvl: painter.drawText( 3, self.height() - i * metrics.height() - metrics.descent() - 2, line) i += 1 scale_factor, _, angles, translation, _ = decompose_matrix( self._view * self._model) lines = [ (1, f'{degrees(angles[0]):+6.1f}\u00b0 {degrees(angles[1]):+6.1f}\u00b0 {degrees(angles[2]):+6.1f}\u00b0' ), ] i = 0 for (lvl, line) in reversed(lines): if self._annotations >= lvl: painter.drawText( self.width() - 3 - metrics.boundingRect(line).width(), self.height() - i * metrics.height() - metrics.descent() - 2, line) i += 1 if self._annotations >= 2: if self._status_text: rect = metrics.boundingRect(self._status_text) painter.drawText(self.width() - rect.width() - 3, rect.height(), self._status_text)
def paintEvent(self, event=None): font = QFont(self.font()) font.setPointSize(font.pointSize() - 1) # Returns -1 if the font size was specified in pixels. fm = QFontMetricsF(font) fracWidth = fm.width(FractionSlider.WSTRING) # 一个字母所占的宽度 indent = fm.boundingRect("9").width() / 2.0 # 半个字母的宽度 # Returns the bounding rectangle of the characters in the string specified by text. if not X11: fracWidth *= 1.5 span = self.width() - (FractionSlider.XMARGIN * 2) # 尺子的宽度 value = self.__numerator / float(self.__denominator) # 当前滑块的值 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿 painter.setRenderHint(QPainter.TextAntialiasing) # 设置字体抗锯齿 painter.setPen(self.palette().color(QPalette.Midlight)) # setPen 可以接受Pen、PenStyle、Color对象 这里指的是Color # painter.setPen(QColor(220,100,100)) # 这里设置的是QWidght的边框 painter.setBrush(self.palette().brush( QPalette.AlternateBase)) # setBrush() : Sets the brush for the given color role to the specified brush for all groups in the palette. # [Color Role] QPalette.AlternateBase : Used as the alternate background color in views with alternating row colors # self.palette() This property holds the widget's palette 其会和默认的调色版混合呈现,但是其一般不能传递到窗口,需要特殊设置,推荐使用CSS painter.drawRect(self.rect()) segColor = QColor(Qt.gray).lighter(80) # 尺度条颜色:lighter(factor) 150表示50%亮,对于darker(factor) 300表示3倍暗 segLineColor = segColor.darker() # 默认200 lighter默认 150 painter.setPen(segLineColor) painter.setBrush(segColor) painter.drawRect(FractionSlider.XMARGIN, FractionSlider.YMARGIN, span, fm.height()) textColor = self.palette().color(QPalette.Text) segWidth = span / self.__denominator segHeight = fm.height() * 2 nRect = fm.boundingRect(FractionSlider.WSTRING) x = FractionSlider.XMARGIN yOffset = segHeight + fm.height() for i in range(self.__denominator + 1): painter.setPen(segLineColor) # 设置线的颜色作为Pen painter.drawLine(x, FractionSlider.YMARGIN, x, segHeight) # 划竖线,从(x,ymargin)开始,到(x,segheight)为止。 painter.setPen(textColor) y = segHeight rect = QRectF(nRect) rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) #painter.drawText(rect, Qt.AlignCenter, #QString.number(i)) painter.drawText(rect, Qt.AlignCenter,str(i)) y = yOffset rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) painter.drawText(rect, Qt.AlignCenter, str(self.__denominator)) painter.drawLine(QPointF(rect.left() + indent, y), QPointF(rect.right() - indent, y)) x += segWidth span = int(span) y = FractionSlider.YMARGIN - 0.5 triangle = [QPointF(value * span, y), QPointF((value * span) + (2 * FractionSlider.XMARGIN), y), QPointF((value * span) + FractionSlider.XMARGIN, fm.height())] triangledict = (QPointF(value * span, y), QPointF((value * span) + (2 * FractionSlider.XMARGIN), y), QPointF((value * span) + FractionSlider.XMARGIN, fm.height())) painter.setPen(QColor(Qt.yellow).darker(100)) # painter.setBrush(Qt.darkYellow) painter.setBrush(QColor(Qt.yellow).darker(200)) painter.drawPolygon(QPolygonF(triangle))