def setText(self, text): self._text = text metrics = QFontMetrics(self._font) self._textRect = QRectF(metrics.boundingRect( QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text)) self._textRect.translate(5, 5) self.prepareGeometryChange() self._rect = self._textRect.adjusted(-5, -5, 5, 5)
def setText(self, text): self._text = text metrics = QFontMetrics(self._font) self._textRect = QRectF(metrics.boundingRect( QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text)) self._textRect.translate(5, 5) self.prepareGeometryChange() self._rect = self._textRect.adjusted(-5, -5, 5, 5)
def paint(self, painter, option, widget): rect = self.boundingRect() brush = QBrush() brush.setStyle(Qt.SolidPattern) brush.setColor(self.backColor) painter.setBrush(brush) painter.drawRect(QRectF(0, 0, self.width, self.height)) painter.setPen(QPen(Qt.red, 2)) # painter.drawLine(QPointF(self.width/2, 0), QPointF(self.width/2, self.height)) painter.drawLine(QPointF(0, self.height / 2), QPointF(self.width, self.height / 2)) font = painter.font() font.setPixelSize(12) font.setWeight(QFont.Bold) fontMetrics = QFontMetrics(font) painter.setFont(font) textRect = fontMetrics.boundingRect(str(self.currTime)) painter.drawText(QPointF(50 + 5, self.height / 2), str(self.currTime)) painter.setPen(self.linePen) # one line after 5 pixels startValue = self.currTime # origin = (self.width / 2) - (startValue * self.lineSpacing) # min = int(startValue - (self.width * .5) / self.lineSpacing) # max = int(startValue + (self.width * .5) / self.lineSpacing) origin = (self.height / 2) - (startValue * self.lineSpacing) min = int(startValue - (self.height * .5) / self.lineSpacing) max = int(startValue + (self.height * .5) / self.lineSpacing) for i in range(min, max): # x1 = x2 = origin + (i * self.lineSpacing) # y1 = self.height x1 = 0 y1 = y2 = origin + (i * self.lineSpacing) if i % 10 == 0: x2 = 40 if i >= 0: font.setWeight(QFont.Bold) font.setPixelSize(10) painter.setFont(font) painter.drawText(self.width - 20, y1, f'{i}') elif i % 5 == 0: x2 = 25 else: x2 = 13 if i >= 0: painter.drawLine(x1, y1, x2, y2) print(x2, y2)
def __init__(self, details, fonts, voter_num): contest = details.contest self.voter_header = QFontMetrics(fonts.voter_header).boundingRect( "Now Voting: {} ({}/{})".format(contest.voters[voter_num], voter_num, contest.num_voters)).width() self.contest_header = QFontMetrics(fonts.contest_header).boundingRect( "{} Results".format(details.title)).width() self.country = 0 self.entry_details = 0 country_fm = QFontMetrics(fonts.country) entry_fm = QFontMetrics(fonts.entry_details) for entry in details.contest.entries: current_country = entry_fm.boundingRect(entry.country).width() current_entry = country_fm.boundingRect("{} – {}".format( entry.artist, entry.song)).width() if current_country > self.country: self.country = current_country if current_entry > self.entry_details: self.entry_details = current_entry if details.display_flags: self.flag_offset = 24 * details.scaling else: self.flag_offset = 0 self.rectangle = max( self.country, self.entry_details) + self.flag_offset + 80 * details.scaling self.width = max( max(30 * details.scaling + 2 * self.rectangle, 48 * details.scaling + self.contest_header), 10 * details.scaling + self.voter_header) num_entries_in_left_column = int( contest.num_entries / 2) + contest.num_entries % 2 self.height = 10 * details.scaling + 35 * details.scaling * num_entries_in_left_column + 70 * details.scaling
def calc_size(cls, self): font = QFont(self.fontName) if self.fontSize: font.setPointSizeF(self.fontSize) if self.fontBold: font.setBold(True) if self.fontItalic: font.setItalic(True) fm = QFontMetrics(font) flags = cls.textFlags(self) r = fm.boundingRect(0, 0, self.width, 0, flags, self.text) self.height = r.height() + 4 return self.width, self.height
def set_text(self, text): self.text = text metrics = QFontMetrics(self.font) self.text_rect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft, self.text) self.text_rect.translate(5, 5) self.prepareGeometryChange() self.rect = QRectF(self.text_rect.adjusted(-5.0, -5.0, 5.0, 5.0))
def draw_monitor_label(self, painter: QPainter, rect: QRectF, txt: str): painter.save() font = self.monitor_label_font font_metrics = QFontMetrics(font, painter.device()) bounding_rect = font_metrics.boundingRect(rect.toRect(), 0, txt) x_factor = rect.width() / bounding_rect.width() y_factor = rect.height() / bounding_rect.height() factor = min(x_factor, y_factor) font.setPointSizeF(font.pointSizeF() * factor) painter.setFont(font) painter.setPen(self.monitor_label_font_color) painter.drawText(rect, Qt.AlignCenter, txt) painter.restore()
def compute_font_size(): screen_rect = QApplication.desktop().availableGeometry() font_size = 14 while True: font = QApplication.font() font.setPixelSize(font_size) fm = QFontMetrics(font) byte_height = fm.boundingRect("0").height() byte_view_height = byte_height * 64 if byte_view_height < screen_rect.height(): return font_size else: font_size -= 1
def paint(self, painter, option, widget): rect = self.boundingRect() brush = QBrush() brush.setStyle(Qt.SolidPattern) brush.setColor(Qt.lightGray) painter.setBrush(brush) painter.drawRect(QRectF(0, 0, self.width, self.height)) painter.setPen(QPen(Qt.red, 2)) painter.drawLine(QPointF(self.width / 2, 0), QPointF(self.width / 2, self.height)) font = painter.font() font.setPixelSize(12) font.setWeight(QFont.Bold) fontMetrics = QFontMetrics(font) painter.setFont(font) textRect = fontMetrics.boundingRect(str(self.currTime)) painter.drawText(self.width / 2 - (textRect.width() / 2), 65, str(self.currTime)) painter.setPen(QPen(Qt.black, 1)) # one line after 5 pixels startValue = self.currTime origin = (self.width / 2) - (startValue * self.lineDistance) min = int(startValue - (self.width * .5) / self.lineDistance) max = int(startValue + (self.width * .5) / self.lineDistance) for i in range(min, max): x1 = x2 = origin + (i * self.lineDistance) y1 = self.height if i % 10 == 0: y2 = 10 if i >= 0: font.setWeight(QFont.Bold) font.setPixelSize(10) painter.setFont(font) painter.drawText(x1, 10, f'{i}') elif i % 5 == 0: y2 = 25 else: y2 = 37 if i >= 0: painter.drawLine(x1, y1, x2, y2)
def paintEvent(self, _: QPaintEvent) -> None: """Qt Paint Event: ensures the title-bar text is elided properly and stays centered""" painter = QPainter() painter.begin(self) painter.setPen(self.__font_pen) # bold font for macOS window titles font = self.font() if sys.platform in ["darwin", "linux"]: font.setBold(True) font_metrics = QFontMetrics(font) # calculate text properties text_width: int = self.width( ) - self.__button_bar_width - self.__margin text: str = font_metrics.elidedText(self.__original_text, Qt.ElideRight, text_width) # calculate height br: QRect = font_metrics.boundingRect(text) if br.height() > 0: self.__br_height = br.height() py = self.__ofs_y - self.__br_height / 2.0 br_width = br.width() # calculate width px = (self.width() - br_width - WIDTH_PADDING_PX) / 2.0 if px < self.__button_bar_width: if self.__window_buttons_position == WINDOW_BUTTONS_RIGHT: if text != self.__original_text: px = self.__margin else: px = px - (self.__button_bar_width - px) else: px = self.__button_bar_width # draw title rect = QRectF(px, py, br_width + WIDTH_PADDING_PX, self.__br_height) painter.setFont(font) if DEBUG: painter.setBrush(QBrush(QColor('#ff0000'))) painter.drawRect(rect) painter.drawText(rect, Qt.AlignLeft, text)
def _drawWarning(self, painter, rect, item): warning = item.data(renderSetupRoles.NODE_WARNING) if warning and len(warning) > 0: fm = QFontMetrics(self.treeView().font()) if item.type() == renderSetup.RENDER_OVERRIDE_TYPE: left = self.getTextRect( rect, item).right() + baseDelegate.BaseDelegate.ACTION_BORDER else: left = self.getTextRect(rect, item).left() + fm.boundingRect( item.data(Qt.DisplayRole)).width( ) + baseDelegate.BaseDelegate.ACTION_BORDER top = rect.top() + baseDelegate.BaseDelegate.ICON_TOP_OFFSET painter.drawPixmap(left, top, baseDelegate.BaseDelegate.WARNING_IMAGE) iconRect = QRect(left, top, baseDelegate.BaseDelegate.WARNING_ICON_WIDTH, baseDelegate.BaseDelegate.WARNING_ICON_WIDTH) p = self.treeView().mapFromGlobal(QCursor.pos()) if iconRect.contains(p): item.setToolTip(warning)
def text_width(text: str, font: str = "Arial", fontsize: int = 10) -> int: font = QFont(font, fontsize) fm = QFontMetrics(font) points_wide = fm.boundingRect(text).width() return points_wide
def compute_byte_advance(self): fm = QFontMetrics(self.font) # return fm.horizontalAdvance("00") + 2*self.byte_padding + self.byte_margin return fm.boundingRect( "00").width() + 2 * self.byte_padding + self.byte_margin
def compute_byte_rect(self): fm = QFontMetrics(self.font) byte_rect = fm.boundingRect("00") byte_rect.moveTopLeft(QPoint()) return byte_rect.adjusted(-self.byte_padding, 0, self.byte_padding, 0)
class GraphicsView(QGraphicsView): def __init__(self, scene: QGraphicsScene, zoomable: bool = True): super().__init__() self.setScene(scene) self._zoomable = zoomable if self._zoomable: self.enable_zooming() self._cur_scale = self._calculate_scale() self._scale_font = QFont() self._scale_font.setPointSize(16) self._scale_font.setBold(True) self._scale_font_metrics = QFontMetrics(self._scale_font) self._scale_text_rect = QRect() self._viewport_anchors = None self._reset_viewport_anchors() self._viewport_anchoring = False self._viewport_anchoring_scheduled = False scene.sceneRectChanged.connect(self._reset_viewport_anchors) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # Without FullViewportUpdate mode, scale text will not be properly updated when scrolling, # Because QGraphicsView::scrollContentsBy contains scroll optimization to update only part of the viewport. # self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) # Now we override the scrollContentsBy method instead of changing the mode to FullViewportUpdate def enable_zooming(self): self.setTransformationAnchor(QGraphicsView.NoAnchor) self.setResizeAnchor(QGraphicsView.NoAnchor) view_smooth_zoom = _ViewSmoothZoom(self, self) view_smooth_zoom.zoom_finished.connect(self._on_zoom_finished) self.viewport().installEventFilter(view_smooth_zoom) def paintEvent(self, event: QPaintEvent): super().paintEvent(event) if self._viewport_anchoring_scheduled: self._anchor_viewport() self._viewport_anchoring_scheduled = False painter = QPainter(self.viewport()) painter.setRenderHint(QPainter.Antialiasing) painter.setBrush(QColor(123, 184, 234)) painter.setPen(QPen(Qt.white, 0.5)) scale_text = f'{self._cur_scale * 100:.0f}%' scale_text_bounding_rect = self._scale_font_metrics.boundingRect( scale_text) viewport_rect = self.viewport().rect() # Align the scale text to (Qt.AlignHCenter | Qt.AlignBottom) pad = 2 self._scale_text_rect = QRect(viewport_rect.width() / 2 - scale_text_bounding_rect.width() / 2, viewport_rect.height() - scale_text_bounding_rect.height() - 6, scale_text_bounding_rect.width(), scale_text_bounding_rect.height())\ .adjusted(-pad, -pad, pad, pad) # add pads to update when scrolling without artifacts # Use QPainterPath to draw text with outline path = QPainterPath() path.addText(self._scale_text_rect.bottomLeft(), self._scale_font, scale_text) painter.drawPath(path) def scrollContentsBy(self, dx: int, dy: int): super().scrollContentsBy(dx, dy) # Update old (to clear text) and new rectangles (to draw) with the scale text self.viewport().update(self._scale_text_rect) self.viewport().update(self._scale_text_rect.translated(dx, dy)) self._update_viewport_anchors() def _calculate_scale(self) -> float: cur_transform = self.transform() assert cur_transform.m11() == cur_transform.m22( ), 'Scaled without keeping aspect ratio' return cur_transform.m11() def _update_scale(self): self._cur_scale = self._calculate_scale() def _on_zoom_finished(self): self._update_scale() self._update_viewport_anchors() def _update_viewport_anchors(self): if self._viewport_anchoring: return viewport_rect = self.viewport().rect() top_left_viewport_point = self.mapToScene(viewport_rect.topLeft()) bottom_right_viewport_point = self.mapToScene( viewport_rect.bottomRight()) scene_rect = self.sceneRect() scene_size = np.array([scene_rect.width(), scene_rect.height()]) self._viewport_anchors[0] = np.array( [top_left_viewport_point.x(), top_left_viewport_point.y()]) / scene_size self._viewport_anchors[1] = \ np.array([bottom_right_viewport_point.x(), bottom_right_viewport_point.y()]) / scene_size def resizeEvent(self, resize_event: QResizeEvent): self._schedule_viewport_anchoring() def _schedule_viewport_anchoring(self): self._viewport_anchoring_scheduled = True def _reset_viewport_anchors(self): self._viewport_anchors = np.array([[0, 0], [1, 1]], dtype=np.float) self._schedule_viewport_anchoring() def _anchor_viewport(self): self._viewport_anchoring = True scene_rect = self.sceneRect() scene_size = np.array([scene_rect.width(), scene_rect.height()]) viewport_rect_angle_point_coords = self._viewport_anchors * scene_size viewport_rect = QRectF(QPointF(*viewport_rect_angle_point_coords[0]), QPointF(*viewport_rect_angle_point_coords[1])) self.fit_in_view(viewport_rect, Qt.KeepAspectRatio) self._viewport_anchoring = False def fit_in_view( self, rect: QRectF, aspect_ratio_mode: Qt.AspectRatioMode = Qt.IgnoreAspectRatio): self.fitInView(rect, aspect_ratio_mode) self._update_scale()
def __font_width(size, family, text): font = QFont() font.setPixelSize(size) font.setFamily(family) metrics = QFontMetrics(font) return metrics.boundingRect(text).width()