def paint(self, canvas, is_secondary_color=False, additional_flag=False): pen = QPen() if is_secondary_color: pen.setColor(self.data_singleton.secondary_color) else: pen.setColor(self.data_singleton.primary_color) painter = QPainter(canvas.image) painter.setRenderHint(QPainter.Antialiasing) pen.setWidth(self.data_singleton.pen_size) pen.setStyle(Qt.SolidLine) pen.setCapStyle(Qt.RoundCap) pen.setJoinStyle(Qt.RoundJoin) painter.setPen(pen) if is_secondary_color: painter.setBrush(self.data_singleton.primary_color) else: painter.setBrush(self.data_singleton.secondary_color) if self._start_point != self._end_point: painter.drawRect(QRect(self._start_point, self._end_point)) painter.end() canvas.edited = True canvas.update()
def _draw_serie(self, painter, ndx_serie, color): serie = self.data[ndx_serie] #mainlog.debug(serie) fill_color = QColor(color) fill_color.setAlpha(64) brush = QBrush(fill_color) pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) qp = QPainterPath() painter.setPen(pen) for i in range(len(serie)): x, y_top, y_below = self._item_coordinates(i) h = max(1, float(y_top - y_below - 1)) qp.addRect( x, float(self.y_base-y_top), float(self.bar_width), h) painter.fillPath(qp,brush) painter.drawPath(qp) #mainlog.debug("Drawing peak values, juste before {}".format(self._peak_values)) if self._peak_values: #mainlog.debug("Drawing peak values") self._draw_peak_values(painter, self._peak_values )
def paintEvent(self, pe): # make an arrow polygon right in the middle painter = QPainter(self) painter.setPen(Qt.NoPen) # draw the background transparent rect painter.save() painter.setOpacity(self.BACKGROUND_OPACITY) # get the rectangle coordinates it should extend over the whole width with only a portion at the center painter.setBrush(Qt.black) empty_space_percent = 1 - self.BACKROUND_HEIGHT_PERCENT rect_top = empty_space_percent / 2 * self.height() rect_height = self.BACKROUND_HEIGHT_PERCENT * self.height() painter.drawRect(0, rect_top, self.width(), rect_height) painter.restore() painter.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(self.ARROW_LINE_WIDTH) pen.setCapStyle(Qt.RoundCap) if self._mouse_inside: pen.setColor(self._hover_color) else: pen.setColor(self._normal_color) # get the arrow coords painter.setPen(pen) self_center = QPointF(self.width() / 2, self.height() / 2) # use this as the arrow tip for now if self._direction == self.LEFT: h_shift = self._arrow_width elif self._direction == self.RIGHT: h_shift = - self._arrow_width v_shift = self._arrow_height / 2 top_point = self_center + QPointF(h_shift, - v_shift) bottom_point = self_center + QPointF(h_shift, v_shift) painter.drawLine(top_point, self_center) painter.drawLine(self_center, bottom_point)
def paintEvent(self, pe): if not self._hover_rect: super(TrackerWebView, self).paintEvent(pe) else: super(TrackerWebView, self).paintEvent(pe) hover_rect = self._hover_rect self._fixRectForScroll(hover_rect) painter = QPainter(self) painter.save() pen = QPen(Qt.red) pen.setWidth(2) painter.setPen(pen) painter.drawRect(hover_rect) painter.restore() # draw green rects around the similar elements pen = QPen() pen.setWidth(2) for field_info in self._fields_info: painter.save() web_elements = field_info.web_elements color = field_info.color pen.setColor(color) painter.setPen(pen) for elem in web_elements: elem_rect = elem.absoluteGeometry() painter.drawRoundedRect(self._fixRectForScroll(elem_rect), 2, 2) painter.restore()
def draw(self, painter, scale): if self.point: pen = QPen() pen.setColor(QColor(255, 0, 0)) painter.setPen(pen) painter.drawEllipse(self.point, Figure.CTRL_RADIUS + 4, Figure.CTRL_RADIUS + 4)
def _draw_serie(self, painter, ndx_serie, color): serie = self.data[ndx_serie] if not serie: return qp = QPainterPath() # qp.addRect(2,2,total_width-4,total_height-4) x = float(0) * self.x_factor y = serie[0] * self.y_factor qp.moveTo(self.x_centers[0],self.y_base - y) # print y_base for i in range(1,len(serie)): x = float(i) * self.x_factor y = float(serie[i]) * self.y_factor qp.lineTo(self.x_centers[i], self.y_base-y) pen = QPen() pen.setColor(color) if ndx_serie == self.ndx_best_serie: pen.setWidth(6) else: pen.setWidth(2) painter.setPen(pen) painter.drawPath(qp)
def _draw_horizontal_ruler(self, painter, text, y_value, color): y = y_value * self.y_factor pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) qp = QPainterPath() r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(self.x_base,self.y_base - y - bb.height(), bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(128) brush = QBrush(fill_color) painter.fillRect(bb,brush) qp.moveTo(self.x_base,self.y_base - y) qp.lineTo(self.total_width + self.x_base, self.y_base - y) painter.setPen(pen) painter.drawPath(qp) text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(color) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.drawText(self.x_base,self.y_base - y - 5,text)
def paintEvent(self, pe): p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setColor(Qt.GlobalColor.black) pen.setWidth(2) pen.setJoinStyle(Qt.MiterJoin) p.setPen(pen) h = self.associated_label.sizeHint().height() w = h pw = pen.width() b = self.italic_block(pw+0,w,h) p.translate(self.shadow_size,self.shadow_size) p.fillPath(b, QBrush(Qt.gray)) p.translate(-self.shadow_size,-self.shadow_size) p.fillPath(b, QBrush(self.Colors[self.step])) p.drawPath(b) b = self.italic_block(pw+w*1.25,w*0.75,h) p.translate(self.shadow_size,self.shadow_size) p.fillPath(b, QBrush(Qt.gray)) p.translate(-self.shadow_size,-self.shadow_size) p.fillPath(b, QBrush(self.Colors[self.step+1])) p.drawPath(b) b = self.italic_block(pw+w*2.25,w*0.4,h) p.translate(self.shadow_size,self.shadow_size) p.fillPath(b, QBrush(Qt.gray)) p.translate(-self.shadow_size,-self.shadow_size) p.fillPath(b, QBrush(self.Colors[self.step+2])) p.drawPath(b)
def paintEvent(self, pe): if self._drop_zones_shown: painter = QPainter(self.viewport( )) # See documentation to know why I draw on the viewport painter.setFont(self._titles_font) vr = self.rect() nb_drop_zones = len(self._drop_zones_titles) subr = QRect(vr) subr.setHeight(vr.height() / nb_drop_zones) for i in range(nb_drop_zones): c = self._drop_zones_colors[i] text_pen = QPen() text_pen.setColor(inverse_colors(c)) painter.setPen(text_pen) if i == self._selected_drop_zone: # mainlog.debug("selected drop zone is {}".format(i)) c = c.lighter(200) painter.setBrush(c) subr.moveTop(int(i * vr.height() / nb_drop_zones)) painter.drawRect(subr) painter.drawText( QPoint(10, int((i + 0.5) * vr.height() / nb_drop_zones)), self._drop_zones_titles[i]) return None else: return super(AnimatedTableView, self).paintEvent(pe)
def _draw_selected_items_in_series(self, painter): fm = painter.fontMetrics() pen = QPen() pen.setWidth(1) pen.setColor(Qt.GlobalColor.white) painter.setPen(pen) # We assume all series have the very same number of values # and all values on the same index are drawn on the same X # coordinate ndx_serie = self.best_serie_intra_ndx aesthetic_shift = 5 if ndx_serie is not None: to_draw = [] for i in range(len(self.data)): x, y = self._item_coordinates_lines(i, ndx_serie) #mainlog.debug("{} {}".format(ndx_serie,i)) v = self.data[i][ndx_serie] text = str(int(v)) to_draw.append( (self.y_base - y, text) ) last_y = 100000 for y, text in sorted( to_draw, key=lambda z : z[0], reverse=True): r = QRect(x + aesthetic_shift,0,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) if bb.right() > self.width(): x = x - bb.width() - 2*aesthetic_shift# left align if y + bb.height() > last_y: y = last_y - bb.height() fill_color = QColor(16, 16, 48) fill_color.setAlpha(196) brush = QBrush(fill_color) margin = 2 r = QRect(x + aesthetic_shift - margin, y - aesthetic_shift - bb.height() - margin, bb.width() + 2*margin, bb.height() + 2*margin) painter.fillRect(r, brush) painter.drawText(x + aesthetic_shift, y - aesthetic_shift, text) last_y = y x, y = self._item_coordinates_lines(0, ndx_serie) qp = QPainterPath() qp.moveTo(x, self.y_base) qp.lineTo(x, self.y_base - self.total_height) painter.drawPath(qp)
def draw_no_data(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(128, 128, 128)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect( self.margin, 0, self.width() - 2*self.margin, self.height()) painter.drawText(r, (Qt.AlignCenter | Qt.AlignLeft) + Qt.TextWordWrap, _("No data"))
def _draw_serie(self, painter, ndx_serie, color): last_item = len(self.data) - 1 serie = self.data[ndx_serie] serie_below = [0] * len(self.data[last_item]) if ndx_serie < len(self.data) - 1: serie_below = self.data[ ndx_serie + 1 ] qlp = QPainterPath() # The top line path qfp = QPainterPath() # the filled region path x = float(0) * self.x_factor y = serie[0] * self.y_factor qlp.moveTo(self.x_base + x,self.y_base - y) qfp.moveTo(self.x_base + x,self.y_base - y) for i in range(1,len(serie)): x = float(i) * self.x_factor y = float(serie[i]) * self.y_factor #print i,y qlp.lineTo(self.x_base + x, self.y_base-y) qfp.lineTo(self.x_base + x, self.y_base-y) for i in reversed(range(0,len(serie_below))): x = float(i) * self.x_factor y = float(serie_below[i]) * self.y_factor qfp.lineTo(self.x_base + x, self.y_base-y) qfp.closeSubpath() fill_color = QColor(color) fill_color.setAlpha(64) brush = QBrush(fill_color) painter.fillPath(qfp,brush) pen = QPen() pen.setColor(color) if ndx_serie == self.ndx_best_serie: pen.setWidth(6) else: pen.setWidth(2) painter.setPen(pen) painter.drawPath(qlp)
def draw_title(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect(self.margin,0,self.width() - 2*self.margin,self.height()) painter.drawText(r, Qt.AlignLeft + Qt.TextWordWrap, self.title)
def _draw_legend2(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) row = col = 0 self.legend_labels_bounding_boxes = [] for data_ndx, label in sorted( zip(range(len(labels)),labels), key=lambda a:a[1]): if label: # One can hide a series' legend by using a blank label x = self.margin + col * self.max_legend_label_width + 3 y = self.legend_y_start + row * self.text_height # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y-self.text_height+3, self.max_legend_label_width, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y+3,x+self.max_legend_label_width - 6,y + 3) painter.setPen(text_pen) painter.drawText(x,y, label) # Remember text bounding box r = QRect(x,y - self.text_height, self.max_legend_label_width, self.text_height) bb = painter.boundingRect(r,Qt.AlignLeft,label) # if label == 'TV': # painter.drawRect(r) self.legend_labels_bounding_boxes.append( (data_ndx,r) ) if not (col < self.legend_labels_per_line - 1): col = 0 row += 1 else: col += 1
def paint(self, painter, _, ___): ''' Draw the comment symbol ''' rect = self.boundingRect() pen = QPen() pen.setStyle(Qt.DashLine) pen.setColor(Qt.darkGray) painter.setPen(pen) x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height() if self.on_the_right: painter.drawLines([QPoint(w, y), QPoint(x, y), QPoint(x, y), QPoint(x, h), QPoint(x, h), QPoint(w, h)]) else: painter.drawLines([QPoint(x, y), QPoint(w, y), QPoint(w, y), QPoint(w, h), QPoint(w, h), QPoint(x, h)])
def __init__(self, parent, child): ''' Create a new connection between a parent and a child item ''' super(Connection, self).__init__(parent) self.parent = parent self.child = child self._start_point = None self._end_point = None self._middle_points = [] pen = QPen() pen.setColor(Qt.blue) pen.setCosmetic(False) self.setPen(pen) self.parent_rect = parent.sceneBoundingRect() self.childRect = child.sceneBoundingRect() # Activate cache mode to boost rendering by calling paint less often self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
def draw_uvs(self): self.img = QPixmap(QSize(self.w, self.h)) pen = QPen() pen.setWidth(int(self.pen_w.text())) pen.setBrush(QBrush(Qt.white)) pen.setColor(QColor('white')) painter = QPainter() painter.begin(self.img) painter.setPen(pen) coords = self.get_coords() for face in coords: for n in xrange(len(face) - 1): print face[n][0], face[n][1], face[n + 1][0], face[n + 1][1] painter.drawLine(face[n][0], face[n][1], face[n + 1][0], face[n + 1][1]) painter.end() self.view.scene().addPixmap(self.img)
def paintEvent(self, pe): # Those lines are from # http://stackoverflow.com/questions/18344135/why-do-stylesheets-not-work-when-subclassing-qwidget-and-using-q-object # the big idea is : According to the Qt help files, "Every widget displaying custom content must implement the paintEvent". o = QStyleOption() o.initFrom(self) p = QPainter(self) self.style().drawPrimitive(QStyle.PE_Widget, o, p, self) w = self.minimumWidth() pen = QPen() pen.setColor(QColor(128, 128, 192)) # pen.setWidth(1) p.setPen(pen) p.drawLine(0, 0, max(0, self.width() - 1), self.height() - 1)
def paintEvent(self, event): painter = QtGui.QPainter(self) painter.setFont(self.font) # painter.setPen(QColor(200, 0, 100))#light grey painter.fillRect(event.rect(), self.background_color) p = QPen() p.setColor(QColor(100, 100, 100)) painter.setPen(p) rect = event.rect() rect.adjust(0, -1, self.adjust_width, 1) painter.drawRect(rect) cw = self.parent() block = cw.firstVisibleBlock() blocknum = block.blockNumber() top = cw.blockBoundingGeometry(block).translated( cw.contentOffset()).top() bottom = top + int(cw.blockBoundingRect(block).height()) lineno = self.start while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): if blocknum > 0: text = block.text() if not text.startswith(self.anti_tag): painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, str(lineno)) lineno += 1 else: painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, '...') block = block.next() top = bottom bottom = top + int(cw.blockBoundingRect(block).height()) blocknum += 1
def _draw_y_axis(self,painter, y_base, width, height, steps): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) if self.rounded_step_size < 1: fmt = "{:.1f}" else: fmt = "{:.0f}" if self.rounded_step_size > 0: for i in range(int(self.maxi / self.rounded_step_size) + 1): y = y_base - self.rounded_step_size * i * self.y_factor painter.drawText(self.margin,y, fmt.format(self.rounded_step_size * i))
def paintEvent(self, event): painter = QtGui.QPainter(self) painter.setFont(self.font) # painter.setPen(QColor(200, 0, 100))#light grey painter.fillRect(event.rect(), self.background_color) p=QPen() p.setColor(QColor(100,100,100)) painter.setPen(p) rect=event.rect() rect.adjust(0,-1, self.adjust_width,1) painter.drawRect(rect) cw = self.parent() block = cw.firstVisibleBlock() blocknum = block.blockNumber() top = cw.blockBoundingGeometry(block).translated( cw.contentOffset()).top() bottom = top + int(cw.blockBoundingRect(block).height()) lineno=self.start while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): if blocknum>0: text=block.text() if not text.startswith(self.anti_tag): painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, str(lineno)) lineno+=1 else: painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, '...') block = block.next() top = bottom bottom = top + int(cw.blockBoundingRect(block).height()) blocknum += 1
def paintEvent(self, pe): if self.left_view and self.right_view and self.right_view.model(): vr = self.left_view.visualRect(self.left_view.currentIndex()) self.left_top = self.mapFromGlobal( self.left_view.viewport().mapToGlobal(vr.topRight())).y() self.left_bottom = self.mapFromGlobal( self.left_view.viewport().mapToGlobal(vr.bottomRight())).y() vr_top = self.right_view.visualRect(self.right_view.model().index( 0, 0)) vr = self.right_view.visualRect(self.right_view.model().index( self.right_view.model().rowCount() - 1, 0)) self.right_top = self.mapFromGlobal( self.left_view.viewport().mapToGlobal(vr_top.topLeft())).y() self.right_bottom = self.mapFromGlobal( self.left_view.viewport().mapToGlobal(vr.bottomLeft())).y() w = self.minimumWidth() - 1 p = QPainter(self) p.setBrush(QBrush(QColor(210, 255, 210))) pen = QPen() pen.setColor(Qt.transparent) p.setPen(pen) poly = QPolygon() poly.append(QPoint(0, self.left_top)) poly.append(QPoint(w, self.right_top)) poly.append(QPoint(w, self.right_bottom)) poly.append(QPoint(0, self.left_bottom)) p.drawConvexPolygon(poly) p.setRenderHint(QPainter.Antialiasing) pen.setColor(Qt.GlobalColor.black) pen.setWidth(2) p.setPen(pen) p.drawLine(0, self.left_top, w, self.right_top) p.drawLine(0, self.left_bottom, w, self.right_bottom)
def drawLines(self, qp): pen = QPen(Qt.black, 2, Qt.SolidLine) qp.setPen(pen) qp.drawRect(self.rect().left(), self.rect().top(), self.rect().width(), self.rect().height()) qp.drawLine(self.dd.x() + 155, self.dd.y() + 5, self.dd.x() + 250, self.dd.y() + 5) pen.setStyle(Qt.DashLine) qp.setPen(pen) qp.drawLine(self.ud.x() + 155, self.ud.y() + 5, self.ud.x() + 250, self.ud.y() + 5) pen.setStyle(Qt.SolidLine) pen.setColor(Qt.red) qp.setPen(pen) qp.drawLine(self.unid.x() + 155, self.unid.y() + 5, self.unid.x() + 250, self.unid.y() + 5) pen.setColor(Qt.yellow) qp.setPen(pen) qp.drawRect(self.sel.x() + 155, self.sel.y(), 95, 20) pen.setColor(Qt.green) qp.setPen(pen) qp.drawRect(self.leaf.x() + 155, self.leaf.y(), 95, 20)
def _draw_peak_values(self, painter, labels): #mainlog.debug('_draw_peak_values : {}'.format(labels)) text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(Qt.GlobalColor.white) # alpha=255=fully opaque text_pen.setWidth(1) fm = painter.fontMetrics() rects = [] painter.setPen(text_pen) # The sort allow to draw the peak values which are lower first. # We do that to visually connect a peak value to its bar in a # (hopefully) better way for i in sorted( range(len(labels)), key=lambda i:self._item_coordinates(i)[1]): x, y_top, y_below = self._item_coordinates(i) label = labels[i] w = fm.boundingRect(label).width() h = fm.boundingRect(label).height() r = QRect(self.x_centers[i] - int(w/2), self.y_base-y_top - 5 - h, w, h) i = 0 while i < len(rects): old_r = rects[i] if r.intersect(old_r): i = 0 # Move r atop old_r r.translate(0, -(r.bottom() - old_r.y()) - 2) else: i += 1 rects.append(r) self._draw_box_under_text(painter, r.x(), r.y() + h,label) painter.drawText( r.x(), r.y() + h,label)
def paintEvent(self, pe): if not self.enlightened.isVisible() or not self.enabled: return g = self.enlightened.mapToGlobal(QPoint(0, 0)) pos = self.parent().mapFromGlobal(g) self.setGeometry( QRect(pos.x(), pos.y(), self.minimumWidth(), self.minimumHeight())) p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setColor(QColor(128, 128, 255)) pen.setWidth(2) p.setBrush(QBrush(QColor(225 + math.sin(self.progress) * 30, 225, 255))) self.progress += 0.09 * 2 self.progress2 += 0.109 * 2 p.setPen(pen) s = 10 sz = 7 w = s * 1.1 + sz p.drawEllipse(0 + s * math.sin(self.progress + 0.5) + w, s * math.cos(self.progress) + w, sz, sz) p.drawEllipse(s * 1.1 * math.sin(self.progress2) + w, s * math.cos(self.progress + 0.5) + w, sz - 2, sz - 2) p.drawEllipse( s * math.sin(self.progress + 1) + w, s * 1.1 * math.cos(self.progress2 / 2 + self.progress / 2) + w, sz - 4, sz - 4)
def _draw_grid(self,painter, y_base, width, height, steps): m = int(self.maxi / self.rounded_step_size) if self.timer.isActive(): self.gride_lines_number = self.timer_ticks if self.gride_lines_number >= m: self.timer.stop() else: self.gride_lines_number = m for i in range( self.gride_lines_number + 2): qp = QPainterPath() #mainlog.debug("self.rounded_step_size = {}, self.maxi={}".format(self.rounded_step_size, self.maxi)) y = y_base - self.rounded_step_size * i * self.y_factor qp.moveTo(0,y) # A bit of shuffle on y for visual effect qp.lineTo(width,y + (i % 3) - 1) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 25)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(30, 30, 30)) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp)
def paintEvent(self, event): painter = QPainter(self) # Фон painter_path = QPainterPath() painter_path.addRect(0, 0, self.width() - 1, self.height() - 1) painter.fillPath(painter_path, QBrush(QImage(':/main/background.png'))) if self.image: painter.drawText(10, 20, str(self.image.draw_scale)) painter.setTransform(QTransform().scale( self.image.draw_scale, self.image.draw_scale).translate(self.image.draw_offset.x(), self.image.draw_offset.y())) old_pen = painter.pen() new_pen = QPen() new_pen.setColor(QColor(0, 150, 0)) painter.setPen(new_pen) self.image.draw(painter) painter.setPen(old_pen)
def paintEvent(self, event): painter = QPainter(self) # Фон painter_path = QPainterPath() painter_path.addRect(0, 0, self.width() - 1, self.height() - 1) painter.fillPath(painter_path, QBrush(QImage(':/main/background.png'))) if self.image: painter.drawText(10, 20, str(self.image.draw_scale)) painter.setTransform(QTransform(). scale(self.image.draw_scale, self.image.draw_scale). translate(self.image.draw_offset.x(), self.image.draw_offset.y())) old_pen = painter.pen() new_pen = QPen() new_pen.setColor(QColor(0, 150, 0)) painter.setPen(new_pen) self.image.draw(painter) painter.setPen(old_pen)
class LinesChart(QFrame): graph_colors = [Qt.GlobalColor.white, Qt.GlobalColor.blue, Qt.GlobalColor.red, Qt.GlobalColor.darkRed, Qt.GlobalColor.green, Qt.GlobalColor.darkGreen, Qt.GlobalColor.yellow] def __init__(self,parent=None): super(LinesChart,self).__init__(parent) self.timer = QTimer(self) self.timer.timeout.connect(self.timer_tick) # timerUpdate) self.timer.start(400) self.timer_ticks = 0 self.gride_lines_number = 0 self._create_pens() self.stacked = False self.title = "Sic transit gloria mundi" self.title_font = self.thinfont = QFont("Arial",10,QFont.Bold) self.margin = 10 self.total_width = 0 self.legend_labels_bounding_boxes = [] self.ndx_best_serie = -1 self.best_serie_intra_ndx = None self.no_draw = True # Set to True if we can't draw (because of numerical problems or non initialized data for example) self.data = None # When set to true, if the x axis values are dates # then, they'll be shown as month (so intead of 31/12/2014, # you'll get something like 12/14) self.x_axis_as_months = False self.set_mini_maxi(None, None) self.set_horizontal_ruler(None,None) self.forced_maxi = None self.forced_mini = None def set_title(self,t): self.title = t def timer_tick(self): self.timer_ticks += 1 self.update() def set_data(self,x_legends, legends,data): """ Sets the data to draw. :param x_legends: Labels to write on the X axis :param series_legends: Name of the various series. :param data: a list of series; each serie is a list of tuples : (x_coordinate, value). :return: """ mainlog.debug("({}) line_chart : set_data".format(self.title)) mainlog.debug(data) if len(legends) != len(data): raise Exception("The number of legends for data series ({}) is different than the number of series ({})".format(len(legends),len(data))) self.legends = legends self.x_legends = x_legends self.original_data = self.data = data # Compute the smallest and greatest value of the dataset # if self.forced_maxi == None and self.forced_mini == None: self.mini = 9999999999 self.maxi = 0 for l in self.data: if l: # There can be some None in the list, or the list might # even by made only of None's ! filtered = [x or 0 for x in l] if filtered: self.mini = min(min( filtered),self.mini) self.maxi = max(max( filtered),self.maxi) self.mini, self.maxi = self.clip_mini_maxi( self.mini, self.maxi) # if self.mini == self.maxi and self.forced_mini != None and self.forced_maxi != None: # self.mini, self.maxi = self.forced_mini, self.forced_maxi # Compute the sum of each "column" of data summed = [0] * len( data[0] ) for l in data: if l: summed = [(x or 0) + (y or 0) for x,y in zip(summed,l)] self.summed = summed self.highlighted_serie = None def clip_mini_maxi(self, mini, maxi): mainlog.debug("({}) Clipping {} {}, forced:{} {}".format( self.title, type(mini), type(maxi), type(self.forced_mini), type(self.forced_maxi))) if self.forced_mini != None and self.forced_maxi != None: mainlog.debug("Clipping to forced values {} {}".format( self.forced_mini, self.forced_maxi)) mini, maxi = min( mini, self.forced_mini), max( maxi, self.forced_maxi) return mini, maxi else: mainlog.debug("Clipping no clipping :{} {}".format(mini, maxi)) return mini, maxi def sizeHint(self): # QSizePolicy.expanding doesn't exapand as much as I want, # so I push myself :-) return QSize(4000,300) def _compute_legend_lengths(self, painter, legends): self.max_legend_label_width = 0 fm = painter.fontMetrics() for label in legends: self.max_legend_label_width = max(fm.boundingRect(label).width(), self.max_legend_label_width) self.space_between_legend_labels = 10 self.max_legend_label_width += self.space_between_legend_labels # a bit of room self.legend_labels_per_line = int(self.total_width / self.max_legend_label_width) if self.total_width % self.max_legend_label_width > 0: self.legend_labels_per_line += 1 self.legend_lines = len(legends) / self.legend_labels_per_line if len(legends) % self.legend_labels_per_line > 0: self.legend_lines += 1 self.legend_height = self.text_height * self.legend_lines def _compute_x_centers(self, nb_x, available_width): # ----------------------------- 29 # __1__ __2__ __3__ __4__ __5__ # 29/5 = 5.8 # 2.9, 8.7, 14.5, 20.3, 26.1 # mainlog.debug("_compute_x_centers({}, {})".format(nb_x, available_width)) if nb_x == 0: return [] step_width = float(available_width) / float(nb_x) all_x = [] for i in range(nb_x): all_x.append( self.x_base + step_width/2 + i * step_width ) return all_x def _compute_screen_lengths(self,painter,mini,maxi,x_steps): """ :param painter: QPainter :param mini: Minimum value that will be displayed on the Y axis :param maxi: Maximum value that will be displayed on the Y axis :param x_steps: Number of steps on the X axis :return: """ if x_steps > 0: assert 0 <= mini <= maxi, "We should have 0 <= {} <= {}".format(mini, maxi) # Measure regular font height fm = painter.fontMetrics() h = fm.boundingRect("A9j").height() self.text_height = h # Measure y_axis labels max width self.y_axis_label_width = fm.boundingRect(str(int(self.maxi))+"M").width() # Measure title font height base_font = painter.font() painter.setFont(self.title_font) r = QRect(self.margin,0,self.width() - 2*self.margin,self.height()) bb = painter.boundingRect(r,Qt.AlignLeft+Qt.TextWordWrap,self.title) painter.setFont(base_font) self.total_width = self.width() - 2*self.margin - self.y_axis_label_width # Lengths of the legend self._compute_legend_lengths(painter, self.legends) self.legend_y_start = self.margin + bb.height() # Distance between top of widget and top of chart self.yoffset = self.margin + bb.height() + self.legend_height self.total_height = self.height() - self.yoffset - self.margin - self.text_height # print total_width,total_height # Go from actual value to a screen position (without offset, see x/y_base) d = max(maxi,maxi - mini) self.no_draw = self.total_width < 1 or self.total_height < 1 or d <= 0 if self.no_draw: mainlog.debug("No draw because d:{} (mini {}, maxi {}) total_width:{} total_height:{}".format(d, mini, maxi, self.total_width, self.total_height )) return self.y_factor = float(min(self.total_height,self.total_width)) / d self.y_factor = float(self.total_height) / d if x_steps <= 3: self.x_factor = float(self.total_width) / float(3-1) elif x_steps > 1: self.x_factor = float(self.total_width) / float(x_steps - 1) else: self.x_factor = 0 # self.x_axis_offset = max(0, (self.total_width - x_steps * self.x_factor)/2) self.x_axis_offset = 0 # print self.maxi,self.mini,self.y_factor # The axis positions self.y_base = float(maxi) * self.y_factor + self.yoffset self.x_base = self.margin + self.y_axis_label_width + self.x_axis_offset # Now we compute the vertical axis step size. # Remember the graph is fit in the window # First we want each step to display a human firendly # value (so, no 12.3462, 24.68... but 10, 20, 30...) # And we start with an arbitrary number of steps # if self.mini == self.maxi: # steps = 6 # self.rounded_step_size = int(10 ** round(math.log10(self.maxi / steps))) or 1 # else: # steps = min(6, self.maxi - self.mini) or 1 # self.rounded_step_size = int(10 ** round(math.log10( (self.maxi - self.mini) / steps))) or 1 # # # if self.rounded_step_size > 1: # # # MAke sure the step size is small enough to have "steps" steps. # # while int(self.maxi / self.rounded_step_size) < steps: # self.rounded_step_size = int(self.rounded_step_size / 2) # # # Second, make sure the step is tall enough to let the text in # # while h > self.rounded_step_size * self.y_factor: # # mainlog.debug("{} > {} * {}".format(h, self.rounded_step_size, self.y_factor)) # self.rounded_step_size = self.rounded_step_size * 2 # # if self.maxi > 0: # step_size = (10 ** int(math.log10(self.maxi - 0.00001))) or 1 # mainlog.debug("Maxi={} Actual {}, new {}".format(self.maxi,self.rounded_step_size,step_size)) # self.rounded_step_size = step_size # else: # mainlog.debug("zero") log10 = math.log10( self.maxi) # This fix to make sure there is more than one step # in case the maxi is aligned on a power of 10. # In this case there will be 10 steps. if log10 - int(log10) == 0: fix = -1 else: fix = 0 step_size = 10 ** int(math.floor(log10) + fix) # If we rely only on power of 10, we might end up # with a small number of steps (e.g. 2). That is # correct but unpleasant to look at. To avoid # this, I increase the size of steps to reach # a minimum number of steps. # Dividing by two a power of 10 make sure we'll keep # "human readable" steps (1/2, 1/4, 1/8,...) MINIMUM_NUMBER_OF_STEPS = 4 while self.maxi / step_size < MINIMUM_NUMBER_OF_STEPS: # number of steps < MINIMUM_NUMBER_OF_STEPS step_size = step_size / 2 # Second, make sure the step is tall enough to let the text in while h > step_size * self.y_factor: # mainlog.debug("{} > {} * {}".format(h, self.rounded_step_size, self.y_factor)) step_size = step_size * 2 self.rounded_step_size = step_size self.x_centers = self._compute_x_centers(len(self.data[0]), self.total_width) def _compute_lengths(self,painter): self._compute_screen_lengths(painter,self.mini,self.maxi,len(self.data[0])) def leaveEvent( self, q_leave_event): if self.ndx_best_serie: self.ndx_best_serie = -1 self.update() def leaveEvent(self, event): self.ndx_best_serie = None self.best_serie_intra_ndx = None self.update() def mouseMoveEvent ( self, q_mouse_event): if not self.data or self.no_draw: return p = q_mouse_event.pos() # No need to highlight a serie if there's only one # in the graph. self.ndx_best_serie = -1 self.best_serie_intra_ndx = None if len(self.data) >= 1: ndx,serie = self._locate_legend(p.x(), p.y()) if not serie: # mainlog.debug("Trying to locate on graph") serie,self.best_serie_intra_ndx = self.locate_serie(None, p.x(), p.y()) if serie: #mainlog.debug("Located serie : {}".format(serie)) ndx = self.data.index(serie) # 2014/04/14 13:45:43 [DEBUG] Locate legend data_ndx:2 TO 77481144 - 20 # 2014/04/14 13:45:43 [DEBUG] mouseMove : Highlighting another serie found ndx:1 locate_ndx:2 77481144 # 2014/04/14 13:45:43 [DEBUG] _draw_legend: Highlighting serie ndx=1 77481144 if serie and self.ndx_best_serie != ndx: self.ndx_best_serie = ndx # self.data.index(serie) # mainlog.debug("mouseMove : Highlighting another serie found ndx:{} locate_ndx:{} {} loacte:{}".format(self.ndx_best_serie, ndx, id(serie), id(self.data[ndx]))) self.update() def _locate_legend(self, x, y): for i in range(len(self.legend_labels_bounding_boxes)): data_ndx,bb = self.legend_labels_bounding_boxes[i] if bb.contains(x,y): # mainlog.debug(u"Locate legend data_ndx:{} {} {} - {}".format( data_ndx,self.legends[data_ndx], id(self.data[data_ndx]),i)) return data_ndx, self.data[data_ndx] return None,None def locate_serie(self, painter, x, y): """ Find the serie which is closes to the x,y point """ if len(self.x_legends) <= 1: return None, None # y = self.height() - y screen_x_step = float(self.total_width) / len(self.x_legends) # The x corrdinates can be outside the graph area. # So I use som min and max to have an index in the serie's range x_ndx = min(len(self.data[0])-1, int(max(0, (x - self.margin - self.y_axis_label_width) / screen_x_step))) x_ndx1 = min( len(self.data[0])-1, x_ndx+1) delta_x = x - self.margin - self.y_axis_label_width - (x_ndx * screen_x_step ) # print "{}-{} -> {} - {} d={}".format(x,y,x_ndx,x_ndx1,delta_x) best_d = 999999999 best_serie = None for serie in self.data: if serie[x_ndx] is not None and serie[x_ndx1] is not None: y0 = serie[x_ndx] * self.y_factor y1 = serie[x_ndx1] * self.y_factor # Screen slope slope = (y1 - y0) / screen_x_step sy = self.y_base - ( y0 + slope * delta_x) d = (sy - y ) ** 2 # print d if d < best_d: best_d = d best_serie = serie return best_serie,x_ndx def _item_coordinates_lines(self, ndx_serie, ndx_in_serie): assert ndx_serie >= 0 and ndx_serie < len(self.data), "Incorrect ndx_serie ({})".format(ndx_serie) serie = self.data[ndx_serie] x = self.x_centers[ndx_in_serie] y_top = float(serie[ndx_in_serie]) * self.y_factor return x, y_top def _draw_selected_items_in_series(self, painter): fm = painter.fontMetrics() pen = QPen() pen.setWidth(1) pen.setColor(Qt.GlobalColor.white) painter.setPen(pen) # We assume all series have the very same number of values # and all values on the same index are drawn on the same X # coordinate ndx_serie = self.best_serie_intra_ndx aesthetic_shift = 5 if ndx_serie is not None: to_draw = [] for i in range(len(self.data)): x, y = self._item_coordinates_lines(i, ndx_serie) #mainlog.debug("{} {}".format(ndx_serie,i)) v = self.data[i][ndx_serie] text = str(int(v)) to_draw.append( (self.y_base - y, text) ) last_y = 100000 for y, text in sorted( to_draw, key=lambda z : z[0], reverse=True): r = QRect(x + aesthetic_shift,0,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) if bb.right() > self.width(): x = x - bb.width() - 2*aesthetic_shift# left align if y + bb.height() > last_y: y = last_y - bb.height() fill_color = QColor(16, 16, 48) fill_color.setAlpha(196) brush = QBrush(fill_color) margin = 2 r = QRect(x + aesthetic_shift - margin, y - aesthetic_shift - bb.height() - margin, bb.width() + 2*margin, bb.height() + 2*margin) painter.fillRect(r, brush) painter.drawText(x + aesthetic_shift, y - aesthetic_shift, text) last_y = y x, y = self._item_coordinates_lines(0, ndx_serie) qp = QPainterPath() qp.moveTo(x, self.y_base) qp.lineTo(x, self.y_base - self.total_height) painter.drawPath(qp) def _draw_serie(self, painter, ndx_serie, color): serie = self.data[ndx_serie] if not serie: return qp = QPainterPath() # qp.addRect(2,2,total_width-4,total_height-4) x = float(0) * self.x_factor y = serie[0] * self.y_factor qp.moveTo(self.x_centers[0],self.y_base - y) # print y_base for i in range(1,len(serie)): x = float(i) * self.x_factor y = float(serie[i]) * self.y_factor qp.lineTo(self.x_centers[i], self.y_base-y) pen = QPen() pen.setColor(color) if ndx_serie == self.ndx_best_serie: pen.setWidth(6) else: pen.setWidth(2) painter.setPen(pen) painter.drawPath(qp) # self.max_legend_label_width = 0 # fm = painter.fontMetrics() # for label in legends: # self.max_legend_label_width = max(fm.boundingRect(label).width(), # self.max_legend_label_width) # self.max_legend_label_width += 10 # a bit of room # self.legend_labels_per_line = int(self.total_width / self.max_legend_label_width) # self.legend_lines = len(legends) / self.legend_labels_per_line # if len(legends) % self.legend_labels_per_line > 0: # self.legend_lines += 1 # self.legend_height = self.text_height * self.legend_lines def _draw_legend2(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) row = col = 0 self.legend_labels_bounding_boxes = [] for data_ndx, label in sorted( zip(range(len(labels)),labels), key=lambda a:a[1]): if label: # One can hide a series' legend by using a blank label x = self.margin + col * self.max_legend_label_width + 3 y = self.legend_y_start + row * self.text_height # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y-self.text_height+3, self.max_legend_label_width, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y+3,x+self.max_legend_label_width - 6,y + 3) painter.setPen(text_pen) painter.drawText(x,y, label) # Remember text bounding box r = QRect(x,y - self.text_height, self.max_legend_label_width, self.text_height) bb = painter.boundingRect(r,Qt.AlignLeft,label) # if label == 'TV': # painter.drawRect(r) self.legend_labels_bounding_boxes.append( (data_ndx,r) ) if not (col < self.legend_labels_per_line - 1): col = 0 row += 1 else: col += 1 def _draw_legend(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) max_width = 0 fm = painter.fontMetrics() for label in labels: max_width = max(fm.boundingRect(label).width(), max_width) y_room = int(self.height() * 0.5 / self.text_height) nb_columns = int( len(labels) / y_room) if len(labels) % y_room > 0: nb_columns += 1 y_room = y_room * self.text_height x = self.margin + self.total_width - nb_columns * (max_width + 10) # 100 / 20 = 5 entry per column # 17 / 5 = 3 => 4 columns # print self.height() * 0.5, " ", len(labels), " ", nb_columns, " y_room:", y_room y = 0 i = 0 y_offset = self.yoffset self.legend_labels_bounding_boxes = [] # Draw a background rectanlge behin the legend fill_color = QColor(16,16,48) fill_color.setAlpha(196) brush = QBrush(fill_color) h = y_room w = nb_columns * (max_width + 10) if nb_columns == 1: h = len(labels) * self.text_height r = QRect(x-3, y_offset - self.text_height , w, h + 6) painter.fillRect(r,brush) sorted_labels = sorted( zip( range(len(labels)), labels, map(id,self.data)), lambda a,b:cmp(a[1],b[1])) # mainlog.debug( sorted_labels) # We sort labels on their names (but keep the indices right) for data_ndx, label in sorted( zip(range(len(labels)),labels), lambda a,b:cmp(a[1],b[1])): # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y_offset+ y-self.text_height+3, max_width + 6, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y_offset+y+3,x+max_width,y_offset+y + 3) painter.setPen(text_pen) painter.drawText(x,y_offset+y,label) # Remember text bounding box r = QRect(x,y_offset+y - self.text_height,max_width,self.text_height) # if label == "TO": # painter.drawRect(r) bb = painter.boundingRect(r,Qt.AlignLeft,label) # bb.adjust(-5,-5,+5,+5) # print label,label_ndx,r.x(), r.y(), r.width(), r.height() self.legend_labels_bounding_boxes.append( (data_ndx,bb) ) if y >= y_room - self.text_height: y = 0 x += max_width + 10 else: y += self.text_height i += 1 def _create_pens(self): self.axis_text_pen = QPen() self.axis_text_pen.setCapStyle(Qt.RoundCap) self.axis_text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque self.axis_text_pen.setWidth(1) def _draw_x_axis_dates(self, painter, l): def months_between(a,b): """ Nb of months, inclusive. """ if a > b: a,b = b,a if a.year == b.year: return b.month - a.month + 1 else: m = (12 - a.month + 1) + (b.month + 1) my = (b.year - a.year - 1) * 12 return m + my if not l or len(l) <= 2: return l fm = painter.fontMetrics() char_width = fm.boundingRect("9").width() nbchars = self.total_width / char_width nb_days = (l[-1] - l[0]).days if nb_days <= 10 and not self.x_axis_as_months: return l # mainlog.debug("Too many days") nb_months = months_between(l[0], l[-1]) if nb_months < (nbchars / len("MM/YY")): old_d = l[0] nl = [short_my(old_d)] # Will have the same length as l # print l[1:-1] for d in l[1:len(l)]: if d.month != old_d.month: if d.year != old_d.year: nl.append(short_my(d)) else: nl.append(str(d.month)) old_d = d else: nl.append("") if len(l) != len(nl): mainlog.error("something is wrong") return nl mainlog.debug("Too many months") nb_years = l[-1].year - l[0].year + 1 old_d = l[0] nl = [short_my(old_d)] # Will have the same length as l for d in l[1:len(l)]: if d.year != old_d.year: nl.append(short_my(d)) old_d = d else: nl.append("") return nl def _draw_x_axis(self, painter, labels): if not labels: return if isinstance(labels[0],date): # In this case we expect to have, for example, a label per day # Of course that's too many to draw, hence this "dithering" dithered_labels = [] # 12 expresses a "density" which allows us to switch between days and month # steps. Ideally we should generalize that to weeks, years... if len(labels) > 12: dithered_labels.append(labels[0]) for i in range(1,len(labels)): if labels[i].month != labels[i-1].month: dithered_labels.append(labels[i]) else: dithered_labels.append(None) labels = dithered_labels # mainlog.debug(labels) def short_my(d): if d: return u"{}/{:0>02}".format(d.month,d.year % 100) else: return "" # labels = self._draw_x_axis_dates(painter, labels) # labels = [short_my(l) for l in labels] old_d = labels[0] nl = [short_my(old_d)] # Will have the same length as l for d in labels[1:len(labels)]: if d and d.month != old_d.month: if d.year != old_d.year: nl.append(short_my(d)) else: nl.append(str(d.month)) old_d = d else: nl.append("") # Dithering == cleraing unwanted values labels = nl max_height = 0 total_label_width = 0 fm = painter.fontMetrics() for label in labels: br = fm.boundingRect(str(label)) max_height = max(br.height(), max_height) total_label_width += br.width() painter.setPen(self.axis_text_pen) last_x = -1 last_label = None for i in range(len(labels)): label = str(labels[i]) w = fm.boundingRect(label).width() x = self.x_centers[i] - w / 2 # Somehow, the width of an empty string is not 0 :-) if label and last_label != label and x > last_x: # Avoid that this label overlaps the previous one painter.drawText(x, self.y_base + max_height, label) last_x = x + w - 1 last_label = label if label: painter.drawLine(self.x_centers[i], self.y_base + 2, self.x_centers[i], self.y_base - 2) # else: # mainlog.debug("Skipping label={} x={} last_x={}".format(label, x, last_x)) def _draw_over_grid(self,painter): # painter.setRenderHint(QPainter.Antialiasing, False) line_color = QColor(60, 20, 200, 255) flat_structure = QColor(20,20,255,128) line_color = flat_structure w = min(self.height(), self.width()) / 20 m = self.margin / 2 x0 = m x1 = m + w x15 = m + 9*w x2 = self.width() - m - w x3 = self.width() - m y0 = m y1 = m + w y15 = m + 5*w y2 = self.height() - m - w y3 = self.height() - m # ---------------------------------------------------------------------- d = w / 4 p = [ (x0,y15+d), (x0,y1), (x1,y0), (x15+2*d,y0), # / (x15+d,y0+d), # ____/ (x1,y0+d), # / (x0+d,y1), # | (x0+d,y15), # | (x0,y15+d) # _| ] qp = QPainterPath() qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) qp.closeSubpath() painter.fillPath(qp,QBrush(QColor(20,20,255,128))) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) # --------------------------------------------------------- qp = QPainterPath() p = [ (x0,y1), (x1,y0), (x2,y0), (x3,y1), (x3,y2), (x2,y3), (x1,y3), (x0,y2), (x0,y1)] qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 80, 196)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) def _draw_grid(self,painter, y_base, width, height, steps): m = int(self.maxi / self.rounded_step_size) if self.timer.isActive(): self.gride_lines_number = self.timer_ticks if self.gride_lines_number >= m: self.timer.stop() else: self.gride_lines_number = m for i in range( self.gride_lines_number + 2): qp = QPainterPath() #mainlog.debug("self.rounded_step_size = {}, self.maxi={}".format(self.rounded_step_size, self.maxi)) y = y_base - self.rounded_step_size * i * self.y_factor qp.moveTo(0,y) # A bit of shuffle on y for visual effect qp.lineTo(width,y + (i % 3) - 1) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 25)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(30, 30, 30)) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) def _draw_y_axis(self,painter, y_base, width, height, steps): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) if self.rounded_step_size < 1: fmt = "{:.1f}" else: fmt = "{:.0f}" if self.rounded_step_size > 0: for i in range(int(self.maxi / self.rounded_step_size) + 1): y = y_base - self.rounded_step_size * i * self.y_factor painter.drawText(self.margin,y, fmt.format(self.rounded_step_size * i)) def draw_title(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect(self.margin,0,self.width() - 2*self.margin,self.height()) painter.drawText(r, Qt.AlignLeft + Qt.TextWordWrap, self.title) def draw_no_data(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(128, 128, 128)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect( self.margin, 0, self.width() - 2*self.margin, self.height()) painter.drawText(r, (Qt.AlignCenter | Qt.AlignLeft) + Qt.TextWordWrap, _("No data")) def paintEvent(self,event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) base_font = painter.font() self._compute_lengths(painter) if self.no_draw: self.draw_title(painter) self.draw_no_data(painter) return self._draw_grid(painter, self.y_base, self.width(), self.total_height, 6) # self._draw_over_grid(painter) self._draw_legend2(painter, self.legends) self._draw_x_axis(painter, self.x_legends) self._draw_y_axis(painter, self.y_base, self.width(), self.total_height, 6) self.draw_title(painter) painter.setFont(base_font) if self.data: for i in range(len(self.data)): self._draw_serie(painter, i, self.graph_colors[i % len(self.graph_colors)]) if self._horizontal_ruler_y_value != None: self._draw_horizontal_ruler(painter, self._horizontal_ruler_text, self._horizontal_ruler_y_value, self._horizontal_ruler_color) self._draw_selected_items_in_series(painter) # def compute_mini_maxi(self, delta_min): # if self.data: # mini = 99999999999 # maxi = 0 # for l in self.data: # if l: # mini = min(min(l),mini) # maxi = max(max(l),maxi) # # if maxi - mini < delta_min: # # mainlog.debug("* "*20 + str(delta_min) ) # maxi = mini + delta_min # # self.mini, self.maxi = mini, maxi # # assert 0 <= self.mini <= self.maxi, "0 <= {} <= {}".format(self.mini, self.maxi) def set_mini_maxi(self,mini,maxi): """ Set mini/maxi Y values. That's useful to have, for example, the 0 value on the graph. If mini and maxi are None, the their value will be guessed from the data drawn. :param mini: Minimum value that will be displayed on the Y axis :param maxi: Maximum value that will be displayed on the Y axis :return: """ assert (mini == None and maxi == None) or (0 <= mini <= maxi), "0 <= {} <= {}".format( mini, maxi) self.forced_maxi = maxi self.forced_mini = mini def set_horizontal_ruler(self, text, y_value, color = Qt.GlobalColor.green): self._horizontal_ruler_text = text self._horizontal_ruler_y_value = y_value self._horizontal_ruler_color = color def _draw_box_under_text(self,painter,x,y,text): r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(x,y - bb.height() +2 , bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(170) brush = QBrush(fill_color) painter.fillRect(bb,brush) def _draw_horizontal_ruler(self, painter, text, y_value, color): y = y_value * self.y_factor pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) qp = QPainterPath() r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(self.x_base,self.y_base - y - bb.height(), bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(128) brush = QBrush(fill_color) painter.fillRect(bb,brush) qp.moveTo(self.x_base,self.y_base - y) qp.lineTo(self.total_width + self.x_base, self.y_base - y) painter.setPen(pen) painter.drawPath(qp) text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(color) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.drawText(self.x_base,self.y_base - y - 5,text)
class BaseObject(QGraphicsPathItem): """ Subclass of `QGraphicsPathItem`_ TOWRITE """ Type = OBJ_TYPE_BASE def __init__(self, parent=None): """ Default class constructor. :param `parent`: Pointer to a parent widget instance. :type `parent`: `QGraphicsItem`_ """ super(BaseObject, self).__init__(parent) qDebug("BaseObject Constructor()") self.objPen = QPen() # QPen objPen; self.lwtPen = QPen() # QPen lwtPen; self.objLine = QLineF() # QLineF objLine; self.objRubberMode = int() # int objRubberMode; self.objRubberPoints = {} # QHash<QString, QPointF> objRubberPoints; self.objRubberTexts = {} # QHash<QString, QString> objRubberTexts; self.objID = int() # qint64 objID; self.objPen.setCapStyle(Qt.RoundCap) self.objPen.setJoinStyle(Qt.RoundJoin) self.lwtPen.setCapStyle(Qt.RoundCap) self.lwtPen.setJoinStyle(Qt.RoundJoin) self.objID = QDateTime.currentMSecsSinceEpoch() def __del__(self): """Class destructor.""" qDebug("BaseObject Destructor()") def type(self): """ TOWRITE :return: TOWRITE :rtype: int """ return self.Type def setObjectColor(self, color): """ TOWRITE :param `color`: TOWRITE :type `color`: `QColor`_ """ self.objPen.setColor(color) self.lwtPen.setColor(color) def setObjectColorRGB(self, rgb): """ TOWRITE :param `rgb`: TOWRITE :type `rgb`: `QRgb`_ """ self.objPen.setColor(QColor(rgb)) self.lwtPen.setColor(QColor(rgb)) def setObjectLineType(self, lineType): """ TOWRITE :param `rgb`: TOWRITE :type `rgb`: Qt.PenStyle """ self.objPen.setStyle(lineType) self.lwtPen.setStyle(lineType) def setObjectLineWeight(self, lineWeight): """ TOWRITE :param `lineWeight`: TOWRITE :type `lineWeight`: qreal """ self.objPen.setWidthF(0) # NOTE: The objPen will always be cosmetic if lineWeight < 0: if lineWeight == OBJ_LWT_BYLAYER: self.lwtPen.setWidthF(0.35) # TODO: getLayerLineWeight elif lineWeight == OBJ_LWT_BYBLOCK: self.lwtPen.setWidthF(0.35) # TODO: getBlockLineWeight else: QMessageBox.warning(0, QObject.tr("Error - Negative Lineweight"), QObject.tr("Lineweight: %f" % lineWeight)) qDebug("Lineweight cannot be negative! Inverting sign.") self.lwtPen.setWidthF(-lineWeight) else: self.lwtPen.setWidthF(lineWeight) def objectRubberPoint(self, key): """ TOWRITE :param `key`: TOWRITE :type `key`: QString :rtype: `QPointF`_ """ if key in self.objRubberPoints: # if(objRubberTexts.contains(key)) return self.objRubberPoints[key] # return objRubberTexts.value(key); gscene = self.scene() # QGraphicsScene* gscene = scene() if gscene: return self.scene().property("SCENE_QSNAP_POINT") # .toPointF() return QPointF() def objectRubberText(self, key): """ TOWRITE :param `key`: TOWRITE :type `key`: QString :rtype: QString """ if key in self.objRubberTexts: # if(objRubberTexts.contains(key)) return self.objRubberTexts[key] # return objRubberTexts.value(key); return "" # QString() def boundingRect(self): """ TOWRITE :rtype: `QRectF`_ """ # If gripped, force this object to be drawn even if it is offscreen if self.objectRubberMode() == OBJ_RUBBER_GRIP: return self.scene().sceneRect() return self.path().boundingRect() def drawRubberLine(self, rubLine, painter=None, colorFromScene=''): """ TOWRITE :param `rubLine`: TOWRITE :type `rubLine`: `QLineF`_ :param `painter`: TOWRITE :type `painter`: `QPainter`_ :param `colorFromScene`: TOWRITE :type `colorFromScene`: str """ if painter: objScene = self.scene() # QGraphicsScene* objScene = scene(); if not objScene: return colorPen = self.objPen # QPen colorPen = objPen colorPen.setColor(QColor(objScene.property(colorFromScene))) # .toUInt())) painter.setPen(colorPen) painter.drawLine(rubLine) painter.setPen(self.objPen) def realRender(self, painter, renderPath): # TODO/PORT: Still needs work. """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ :param `renderPath`: TOWRITE :type `renderPath`: `QPainterPath`_ """ color1 = self.objectColor() #QColor # lighter color color2 = color1.darker(150) #QColor # darker color # If we have a dark color, lighten it darkness = color1.lightness() #int threshold = 32 #int #TODO: This number may need adjusted or maybe just add it to settings. if darkness < threshold: color2 = color1 if not darkness: color1 = QColor(threshold, threshold, threshold) # lighter() does not affect pure black else : color1 = color2.lighter(100 + threshold) count = renderPath.elementCount() # int for i in range(0, count - 1): # for(int i = 0; i < count-1; ++i); elem = renderPath.elementAt(i) # QPainterPath::Element next = renderPath.elementAt(i + 1) # QPainterPath::Element if next.isMoveTo(): continue elemPath = QPainterPath() elemPath.moveTo(elem.x, elem.y) elemPath.lineTo(next.x, next.y) renderPen = QPen(QColor(0, 0, 0, 0)) renderPen.setWidthF(0) painter.setPen(renderPen) stroker = QPainterPathStroker() stroker.setWidth(0.35) stroker.setCapStyle(Qt.RoundCap) stroker.setJoinStyle(Qt.RoundJoin) realPath = stroker.createStroke(elemPath) # QPainterPath painter.drawPath(realPath) grad = QLinearGradient(elemPath.pointAtPercent(0.5), elemPath.pointAtPercent(0.0)) grad.setColorAt(0, color1) grad.setColorAt(1, color2) grad.setSpread(QGradient.ReflectSpread) painter.fillPath(realPath, QBrush(grad)) def objectID(self): """ TOWRITE :return: TOWRITE :rtype: int """ return self.objID def objectPen(self): """ TOWRITE :return: TOWRITE :rtype: `QPen`_ """ return self.objPen def objectColor(self): """ TOWRITE :return: TOWRITE :rtype: `QColor`_ """ return self.objPen.color() def objectColorRGB(self): """ TOWRITE :return: TOWRITE :rtype: int """ return self.objPen.color().rgb() def objectLineType(self): """ TOWRITE :return: TOWRITE :rtype: Qt.PenStyle """ return self.objPen.style() def objectLineWeight(self): """ TOWRITE :return: TOWRITE :rtype: float """ return self.lwtPen.widthF() def objectPath(self): """ TOWRITE :return: TOWRITE :rtype: `QPainterPath`_ """ return self.path() def objectRubberMode(self): """ TOWRITE :return: TOWRITE :rtype: int """ return self.objRubberMode def rect(self): """ TOWRITE :return: TOWRITE :rtype: `QRectF`_ """ return self.path().boundingRect() # pythonic setRect overload @signature(QPointF) def setRectFromRect(self, r): """ TOWRITE :param `r`: TOWRITE :type `r`: QPointF """ p = QPainterPath() p.addRect(r) self.setPath(p) # pythonic setRect overload @signature(float, float, float, float) def setRectFromXYWH(self, x, y, w, h): """ TOWRITE :param `x`: TOWRITE :type `x`: qreal :param `y`: TOWRITE :type `y`: qreal :param `w`: TOWRITE :type `w`: qreal :param `h`: TOWRITE :type `h`: qreal """ p = QPainterPath() p.addRect(x, y, w, h) self.setPath(p) @overloaded(setRectFromRect, setRectFromXYWH) def setRect(self, *args): """ TOWRITE """ pass def line(self): """ TOWRITE :return: TOWRITE :rtype: `QLineF`_ """ return self.objLine # pythonic setLine overload @signature(QPointF) def setLineFromLine(self, li): """ TOWRITE :param `li`: TOWRITE :type `li`: QPointF """ p = QPainterPath() p.moveTo(li.p1()) p.lineTo(li.p2()) self.setPath(p) self.objLine = li # pythonic setLine overload @signature(float, float, float, float) def setLineFromXXYY(self, x1, y1, x2, y2): """ TOWRITE :param `x1`: TOWRITE :type `x1`: qreal :param `y1`: TOWRITE :type `y1`: qreal :param `x2`: TOWRITE :type `x2`: qreal :param `y2`: TOWRITE :type `y2`: qreal """ p = QPainterPath() p.moveTo(x1, y1) p.lineTo(x2, y2) self.setPath(p) self.objLine.setLine(x1, y1, x2, y2) @overloaded(setLineFromLine, setLineFromXXYY) def setLine(self, *args): """ TOWRITE """ pass def setObjectPath(self, p): """ TOWRITE :param `p`: TOWRITE :type `p`: `QPainterPath`_ """ self.setPath(p) def setObjectRubberMode(self, mode): """ TOWRITE :param `mode`: TOWRITE :type `mode`: int """ self.objRubberMode = mode def setObjectRubberPoint(self, key, point): """ TOWRITE :param `key`: TOWRITE :type `key`: str :param `point`: TOWRITE :type `point`: `QPointF`_ """ self.objRubberPoints[key] = point # .insert(key, point) def setObjectRubberText(self, key, txt): """ TOWRITE :param `key`: TOWRITE :type `key`: str :param `txt`: TOWRITE :type `txt`: str """ self.objRubberTexts[key] = txt # .insert(key, txt) def shape(self): """ TOWRITE :return: TOWRITE :rtype: `QPainterPath`_ """ return self.path() def vulcanize(self): """ TOWRITE """ raise NotImplementedError def mouseSnapPoint(self, mousePoint): """ TOWRITE :param `mousePoint`: TOWRITE :type `mousePoint`: `QPointF`_ :return: TOWRITE :rtype: `QPointF`_ """ raise NotImplementedError def allGripPoints(self): """ TOWRITE :return: TOWRITE :rtype: list[`QPointF`_] """ raise NotImplementedError def gripEdit(self, before, after): """ TOWRITE :param `before`: TOWRITE :type `before`: `QPointF`_ :param `after`: TOWRITE :type `after`: `QPointF`_ """ raise NotImplementedError def lineWeightPen(self): """ TOWRITE :return: TOWRITE :rtype: `QPen`_ """ return self.lwtPen
def paintEvent(self, event): cX = self.parent.lytLeftMargin + self.scaleMarkLen cY = self.parent.lytTopMargin + self.scaleMarkLen worldX = self.parent.presenter.showChunkX*16 worldZ = self.parent.presenter.showChunkZ*16 painter = QPainter() path = QPainterPath() painter.begin(self) painter.save() #painter.setFont(QFont('Arial Narrow', 8)) #QFont.Bold # draw scale x = cX y = cY painter.rotate(-90) for i in range(16): fr = QRectF(-y, x, self.scaleMarkLen, self.edgeLen) painter.drawText(fr, Qt.AlignHCenter | Qt.AlignVCenter, str(worldX)) #painter.drawRect(fr) #fr = QRectF(-y - 16*self.edgeLen - self.scaleMarkLen, x, self.scaleMarkLen, self.edgeLen) #painter.drawText(fr, Qt.AlignHCenter | Qt.AlignVCenter, '-5555') #painter.drawRect(fr) x += self.edgeLen worldX += 1 painter.rotate(90) x = self.parent.lytLeftMargin y = cY for i in range(16): fr = QRectF(x, y, self.scaleMarkLen, self.edgeLen) painter.drawText(fr, Qt.AlignHCenter | Qt.AlignVCenter, str(worldZ)) #painter.drawRect(fr) #fr = QRectF(x + self.scaleMarkLen + 16*self.edgeLen, y, self.scaleMarkLen, self.edgeLen) #painter.drawText(fr, Qt.AlignHCenter | Qt.AlignVCenter, '-5555') #painter.drawRect(fr) y += self.edgeLen worldZ += 1 x = cX y = cY for i in range(16): for j in range(16): path.addRect(x, y, self.edgeLen, self.edgeLen) #fr = QRectF(x, y, self.edgeLen, self.edgeLen) #painter.drawText(fr, Qt.AlignHCenter | Qt.AlignVCenter, '-5555') x += self.edgeLen x = cX y += self.edgeLen painter.drawPath(path) slice_ = self.parent.presenter.getSlice(self.parent.presenter.elevation) x = cX y = cY bru = QBrush() #path1 = QPainterPath() for i in range(16): for j in range(16): if slice_[i][j] in self.parent.selectedMinerals.list_: lePen = painter.pen() newPen = QPen(bru, 3) newPen.setColor(self.parent.selectedMinerals.getColor(slice_[i][j])) painter.setPen(newPen) painter.drawRect(x, y, self.edgeLen, self.edgeLen) painter.setPen(lePen) x += self.edgeLen x = cX y += self.edgeLen painter.restore() painter.end() del painter
def drawLines(self, qp): pen = QPen(Qt.black, 2, Qt.SolidLine) qp.setPen(pen) # Can be used to test drawing lines between specific actions. Keep for now. #ifrom = self.mapToTree(self.needsLine[0][0]) #ito = self.mapToTree(self.needsLine[0][1]) #qp.drawLine(ifrom.x(), ifrom.y(), ito.x(), ito.y()) alternate = True #print self.op.lastButtonPressed if self.op.lastButtonPressed is not None: pen.setColor(Qt.yellow) qp.setPen(pen) qp.drawRect( self.mapToTree(self.op.lastButtonPressed).x(), self.mapToTree(self.op.lastButtonPressed).y(), self.buttons[self.op.lastButtonPressed].rect().width(), self.buttons[self.op.lastButtonPressed].rect().height()) pen.setColor(Qt.black) qp.setPen(pen) for line in self.needsLine: width0 = self.buttons[line[0]].rect().width() height0 = self.buttons[line[0]].rect().height() width1 = self.buttons[line[1]].rect().width() height1 = self.buttons[line[1]].rect().height() ifrom = self.mapToTree(line[0]) ito = self.mapToTree(line[1]) if len(self.table[line[0]]) == 1 or len(self.table[line[1]]) == 1: pen.setColor(Qt.green) qp.setPen(pen) if len(self.table[line[0]]) == 1: if line[0] in self.op.subtree or line[ 0] == self.op.lastButtonPressed: qp.drawRect(ifrom.x() - 2, ifrom.y() - 2, width0 + 4, height0 + 4) else: qp.drawRect(ifrom.x(), ifrom.y(), width0, height0) if len(self.table[line[1]]) == 1: if line[1] in self.op.subtree: qp.drawRect(ito.x() - 2, ito.y() - 2, width1 + 4, height1 + 4) else: qp.drawRect(ito.x(), ito.y(), width1, height1) pen.setColor(Qt.black) qp.setPen(pen) if line[0] in self.op.subtree or line[1] in self.op.subtree: pen.setColor(Qt.red) qp.setPen(pen) if line[0] in self.op.subtree and line[ 0] != self.op.lastButtonPressed: # and len(self.table[line[0]])>1: qp.drawRect(ifrom.x(), ifrom.y(), width0, height0) if line[1] in self.op.subtree and line[ 1] != self.op.lastButtonPressed: # and len(self.table[line[1]])>1: qp.drawRect(ito.x(), ito.y(), width1, height1) if self.op.needsRefresh: self.update() self.op.needsRefresh = False if self.mapped[line[0]] <= self.mapped[line[1]]: qp.drawLine(ifrom.x() + (width0 / 2), ifrom.y() + (height0 / 2), ito.x() + (width1 / 2), ito.y() + (height1 / 2)) else: pen.setStyle(Qt.DashLine) qp.setPen(pen) qp.drawLine(ifrom.x() + (width0 / 2), ifrom.y() + (height0 / 2), ito.x() + (width1 / 2), ito.y() + (height1 / 2)) #if alternate: # qp.drawArc(QRectF(ito.x(), ito.y()+1, width0, ifrom.y()-ito.y()), 90*16, 180*16) # alternate=False #else: # qp.drawArc(QRectF(ito.x(), ito.y()+1, width0, ifrom.y()-ito.y()), 270*16, 180*16) # alternate=True pen.setStyle(Qt.SolidLine) pen.setColor(Qt.black) qp.setPen(pen)
class SelectBox(QRubberBand): """ Subclass of `QRubberBand`_ TOWRITE """ def __init__(self, s, parent=None): """ Default class constructor. :param `s`: TOWRITE :type `s`: QRubberBand.Shape :param `parent`: Pointer to a parent widget instance. :type `parent`: `QWidget`_ """ super(SelectBox, self).__init__(parent) # private self._leftBrushColor = QColor() self._rightBrushColor = QColor() self._leftPenColor = QColor() self._rightPenColor = QColor() self._alpha = 255 # quint8 #: TODO: what is the initial int? self._dirBrush = QBrush() self._leftBrush = QBrush() self._rightBrush = QBrush() self._dirPen = QPen() self._leftPen = QPen() self._rightPen = QPen() self._boxDir = False #: TODO: is this initial bool value right? # Default values self.setColors(QColor(Qt.darkGreen), QColor(Qt.green), QColor(Qt.darkBlue), QColor(Qt.blue), 32) def setDirection(self, dir): """ TOWRITE :param `dir`: TOWRITE :type `dir`: int """ if not dir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self._boxDir = dir def setColors(self, colorL, fillL, colorR, fillR, newAlpha): """ TOWRITE :param `colorL`: TOWRITE :type `colorL`: `QColor`_ :param `fillL`: TOWRITE :type `fillL`: `QColor`_ :param `colorR`: TOWRITE :type `colorR`: `QColor`_ :param `fillR`: TOWRITE :type `fillR`: `QColor`_ :param `newAlpha`: TOWRITE :type `newAlpha`: int """ qDebug("SelectBox setColors()") self._alpha = newAlpha self._leftPenColor = colorL # TODO: allow customization self._leftBrushColor = QColor(fillL.red(), fillL.green(), fillL.blue(), alpha) self._rightPenColor = colorR # TODO: allow customization self._rightBrushColor = QColor(fillR.red(), fillR.green(), fillR.blue(), alpha) self._leftPen.setColor(self._leftPenColor) self._leftPen.setStyle(Qt.DashLine) self._leftBrush.setStyle(Qt.SolidPattern) self._leftBrush.setColor(self._leftBrushColor) self._rightPen.setColor(self._rightPenColor) self._rightPen.setStyle(Qt.SolidLine) self._rightBrush.setStyle(Qt.SolidPattern) self._rightBrush.setColor(self._rightBrushColor) if not self._boxDir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self.forceRepaint() def paintEvent(self, event): """ Handles the ``paintEvent`` event for :class:`SelectBox`. :param `event`: A `QPaintEvent`_ to be processed. """ painter = QPainter(self) painter.setPen(self._dirPen) width, height = self.width(), self.height() painter.fillRect(0, 0, width - 1, height - 1, self._dirBrush) painter.drawRect(0, 0, width - 1, height - 1) def forceRepaint(self): """ Force repaint the rubberband. .. NOTE:: HACK: Take that QRubberBand! """ # HACK: Take that QRubberBand! hack = self.size() # QSize self.resize(hack + QSize(1, 1)) self.resize(hack)
class SelectBox(QRubberBand): """ Subclass of `QRubberBand`_ TOWRITE """ def __init__(self, s, parent=None): """ Default class constructor. :param `s`: TOWRITE :type `s`: QRubberBand.Shape :param `parent`: Pointer to a parent widget instance. :type `parent`: `QWidget`_ """ super(SelectBox, self).__init__(s, parent) # private self._leftBrushColor = QColor() self._rightBrushColor = QColor() self._leftPenColor = QColor() self._rightPenColor = QColor() self._alpha = 255 # quint8 #: TODO: what is the initial int? self._dirBrush = QBrush() self._leftBrush = QBrush() self._rightBrush = QBrush() self._dirPen = QPen() self._leftPen = QPen() self._rightPen = QPen() self._boxDir = False #: TODO: is this initial bool value right? # Default values self.setColors(QColor(Qt.darkGreen), QColor(Qt.green), QColor(Qt.darkBlue), QColor(Qt.blue), 32) def paintEvent(self, event): """ Handles the ``paintEvent`` event for :class:`SelectBox`. :param `event`: A `QPaintEvent`_ to be processed. """ painter = QPainter(self) painter.setPen(self._dirPen) width, height = self.width(), self.height() painter.fillRect(0, 0, width - 1, height - 1, self._dirBrush) painter.drawRect(0, 0, width - 1, height - 1) def forceRepaint(self): """ Force repaint the rubberband. .. NOTE:: HACK: Take that QRubberBand! """ # HACK: Take that QRubberBand! hack = self.size() # QSize self.resize(hack + QSize(1, 1)) self.resize(hack) # Slots ------------------------------------------------------------------ @Slot(int) def setDirection(self, dir): """ TOWRITE :param `dir`: TOWRITE :type `dir`: int """ if not dir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self._boxDir = dir @Slot(QColor, QColor, QColor, QColor, int) def setColors(self, colorL, fillL, colorR, fillR, newAlpha): """ TOWRITE :param `colorL`: TOWRITE :type `colorL`: `QColor`_ :param `fillL`: TOWRITE :type `fillL`: `QColor`_ :param `colorR`: TOWRITE :type `colorR`: `QColor`_ :param `fillR`: TOWRITE :type `fillR`: `QColor`_ :param `newAlpha`: TOWRITE :type `newAlpha`: int """ qDebug("SelectBox setColors()") self._alpha = newAlpha self._leftPenColor = colorL # TODO: allow customization self._leftBrushColor = QColor(fillL.red(), fillL.green(), fillL.blue(), self._alpha) self._rightPenColor = colorR # TODO: allow customization self._rightBrushColor = QColor(fillR.red(), fillR.green(), fillR.blue(), self._alpha) self._leftPen.setColor(self._leftPenColor) self._leftPen.setStyle(Qt.DashLine) self._leftBrush.setStyle(Qt.SolidPattern) self._leftBrush.setColor(self._leftBrushColor) self._rightPen.setColor(self._rightPenColor) self._rightPen.setStyle(Qt.SolidLine) self._rightBrush.setStyle(Qt.SolidPattern) self._rightBrush.setColor(self._rightBrushColor) if not self._boxDir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self.forceRepaint()
def paintEvent( self, event ): painter = QPainter() painter.begin(self) painter.setRenderHint(painter.Antialiasing) font = painter.font() font.setBold(True) painter.setFont(font) x = self.rect().x() y = self.rect().y() w = self.rect().width() - 1 h = self.rect().height() - 1 r = 8 # draw a rounded style if self._rolloutStyle == 2: # draw the text painter.drawText(x + 33, y + 3, w, 16, Qt.AlignLeft | Qt.AlignTop, self.title()) # draw the triangle self.__drawTriangle(painter, x, y) # draw the borders pen = QPen(self.palette().color(QPalette.Light)) pen.setWidthF(0.6) painter.setPen(pen) painter.drawRoundedRect(x + 1, y + 1, w - 1, h - 1, r, r) pen.setColor(self.palette().color(QPalette.Shadow)) painter.setPen(pen) painter.drawRoundedRect(x, y, w - 1, h - 1, r, r) # draw a square style if self._rolloutStyle == 3: # draw the text painter.drawText(x + 33, y + 3, w, 16, Qt.AlignLeft | Qt.AlignTop, self.title()) self.__drawTriangle(painter, x, y) # draw the borders pen = QPen(self.palette().color(QPalette.Light)) pen.setWidthF(0.6) painter.setPen(pen) painter.drawRect(x + 1, y + 1, w - 1, h - 1) pen.setColor(self.palette().color(QPalette.Shadow)) painter.setPen(pen) painter.drawRect(x, y, w - 1, h - 1) # draw a Maya style if self._rolloutStyle == 4: # draw the text painter.drawText(x + 33, y + 3, w, 16, Qt.AlignLeft | Qt.AlignTop, self.title()) painter.setRenderHint(QPainter.Antialiasing, False) self.__drawTriangle(painter, x, y) # draw the borders - top headerHeight = 20 headerRect = QRect(x + 1, y + 1, w - 1, headerHeight) headerRectShadow = QRect(x - 1, y - 1, w + 1, headerHeight + 2) # Highlight pen = QPen(self.palette().color(QPalette.Light)) pen.setWidthF(0.4) painter.setPen(pen) painter.drawRect(headerRect) painter.fillRect(headerRect, QColor(255, 255, 255, 18)) # Shadow pen.setColor(self.palette().color(QPalette.Dark)) painter.setPen(pen) painter.drawRect(headerRectShadow) if not self.isCollapsed(): # draw the lover border pen = QPen(self.palette().color(QPalette.Dark)) pen.setWidthF(0.8) painter.setPen(pen) offSet = headerHeight + 3 bodyRect = QRect(x, y + offSet, w, h - offSet) bodyRectShadow = QRect(x + 1, y + offSet, w + 1, h - offSet + 1) painter.drawRect(bodyRect) pen.setColor(self.palette().color(QPalette.Light)) pen.setWidthF(0.4) painter.setPen(pen) painter.drawRect(bodyRectShadow) # draw a boxed style elif self._rolloutStyle == 1: if self.isCollapsed(): arect = QRect(x + 1, y + 9, w - 1, 4) brect = QRect(x, y + 8, w - 1, 4) text = '+' else: arect = QRect(x + 1, y + 9, w - 1, h - 9) brect = QRect(x, y + 8, w - 1, h - 9) text = '-' # draw the borders pen = QPen(self.palette().color(QPalette.Light)) pen.setWidthF(0.6) painter.setPen(pen) painter.drawRect(arect) pen.setColor(self.palette().color(QPalette.Shadow)) painter.setPen(pen) painter.drawRect(brect) painter.setRenderHint(painter.Antialiasing, False) painter.setBrush(self.palette().color(QPalette.Window).darker(120)) painter.drawRect(x + 10, y + 1, w - 20, 16) painter.drawText(x + 16, y + 1, w - 32, 16, Qt.AlignLeft | Qt.AlignVCenter, text) painter.drawText(x + 10, y + 1, w - 20, 16, Qt.AlignCenter, self.title()) if self.dragDropMode(): rect = self.dragDropRect() # draw the lines l = rect.left() r = rect.right() cy = rect.center().y() for y in (cy - 3, cy, cy + 3): painter.drawLine(l, y, r, y) painter.end()
def paintEvent(self, event): # print self.height() s = (self.target_angle - self.angle) * 0.09 self.angle += s if math.fabs(self.angle - self.target_angle) < 0.001: self.angle = self.target_angle self.timer.stop() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) qp = QPainterPath() width = min(self.height(), (self.width() / 2)) height = self.height() # center x = self.width() / 2 big_radius = 1000 y = big_radius + 10 small_radius = big_radius - 15 ac = math.atan(float(self.width()) / 2.0 / float(big_radius)) / math.pi * 180.0 * 0.95 qp.arcMoveTo(x - big_radius, y - big_radius, 2 * big_radius, 2 * big_radius, 90 - ac) qp.arcTo(x - big_radius, y - big_radius, 2 * big_radius, 2 * big_radius, 90 - ac, 2 * ac) qp.arcTo(x - small_radius, y - small_radius, 2 * small_radius, 2 * small_radius, 90 + ac, -2 * ac) qp.arcTo(x - big_radius, y - big_radius, 2 * big_radius, 2 * big_radius, 90 - ac, 0) # qp.lineTo(x+big_radius,y) grange = ac * 2.0 / 360.0 # Centered on 0, starting at angle 90-ac, counterclockwise self.gradient = QConicalGradient(0, 0, 90 - ac - 1) if self.gradient_type == 1: self.gradient.setColorAt(0, Qt.GlobalColor.red) self.gradient.setColorAt(0.1, Qt.GlobalColor.yellow) self.gradient.setColorAt(0.2, Qt.GlobalColor.green) self.gradient.setColorAt(0.5, Qt.GlobalColor.green) self.gradient.setColorAt(0.5, Qt.GlobalColor.green) elif self.gradient_type == 2: self.gradient.setColorAt(0, Qt.GlobalColor.green) self.gradient.setColorAt(0.6 * grange, Qt.GlobalColor.yellow) self.gradient.setColorAt(1 * grange, Qt.GlobalColor.red) elif self.gradient_type == 3: self.gradient.setColorAt(0 * grange, Qt.GlobalColor.red) self.gradient.setColorAt(0.05 * grange, Qt.GlobalColor.yellow) self.gradient.setColorAt(0.1 * grange, Qt.GlobalColor.green) self.gradient.setColorAt(0.4 * grange, Qt.GlobalColor.green) self.gradient.setColorAt(0.45 * grange, Qt.GlobalColor.yellow) self.gradient.setColorAt(0.5 * grange, Qt.GlobalColor.red) self.gradient.setCenter(x, y) painter.fillPath(qp, QBrush(self.gradient)) pen = QPen() pen.setColor(Qt.GlobalColor.black) pen.setWidth(max(1, int(1 * self.width() / 300))) painter.setPen(pen) painter.drawPath(qp) qp = QPainterPath() #qp.moveTo(0,0) #qp.lineTo(x,y) #qp.lineTo(self.width(),0) angle = 0 ac = math.atan(float(self.width()) / 2.0 / float(big_radius)) * 0.95 if self.direction == self.UNIDIRECTIONAL: angle = math.pi / 2 + ac * (1 - 2 * self.angle) elif self.direction == self.BIDIRECTIONAL: angle = math.pi / 2 - self.angle * ac length = big_radius + 10 short_length = small_radius - 10 qp.moveTo(x + math.cos(angle) * short_length, y - math.sin(angle) * short_length) qp.lineTo(x + math.cos(angle) * length, y - math.sin(angle) * length) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(Qt.GlobalColor.black) pen.setWidth(max(3, int(3 * width / 300))) painter.setPen(pen) painter.drawPath(qp) qp = QPainterPath() delta = self.width() * 0.025 # print "{}-{} {} c:{}".format(x,y,delta,math.cos(angle)) qp.moveTo(x + delta + math.cos(angle) * short_length, y + delta - math.sin(angle) * short_length) qp.lineTo(x + delta + math.cos(angle) * length, y + delta - math.sin(angle) * length) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor.fromRgbF(0, 0, 0, 0.3)) pen.setWidth(max(3, int(3 * width / 300))) painter.setPen(pen) painter.drawPath(qp) qp = QPainterPath() qp.addRect(0, 0, self.width(), self.height()) painter.drawPath(qp)
def random(): pen = QPen() pen.setColor(QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))) point = Point(100. * random.random(), 100. * random.random()) size = Size(5 + 100. * random.random(), 5 + 100. * random.random()) return Rect(point, size, pen)
def _draw_over_grid(self,painter): # painter.setRenderHint(QPainter.Antialiasing, False) line_color = QColor(60, 20, 200, 255) flat_structure = QColor(20,20,255,128) line_color = flat_structure w = min(self.height(), self.width()) / 20 m = self.margin / 2 x0 = m x1 = m + w x15 = m + 9*w x2 = self.width() - m - w x3 = self.width() - m y0 = m y1 = m + w y15 = m + 5*w y2 = self.height() - m - w y3 = self.height() - m # ---------------------------------------------------------------------- d = w / 4 p = [ (x0,y15+d), (x0,y1), (x1,y0), (x15+2*d,y0), # / (x15+d,y0+d), # ____/ (x1,y0+d), # / (x0+d,y1), # | (x0+d,y15), # | (x0,y15+d) # _| ] qp = QPainterPath() qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) qp.closeSubpath() painter.fillPath(qp,QBrush(QColor(20,20,255,128))) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) # --------------------------------------------------------- qp = QPainterPath() p = [ (x0,y1), (x1,y0), (x2,y0), (x3,y1), (x3,y2), (x2,y3), (x1,y3), (x0,y2), (x0,y1)] qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 80, 196)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp)
def _draw_serie(self, painter, ndx_serie, color): last_item = len(self.data) - 1 serie = self.data[ndx_serie] serie_below = [0] * len(self.data[last_item]) if ndx_serie < len(self.data) - 1: serie_below = self.data[ndx_serie + 1] fill_color = QColor(color) fill_color.setAlpha(64) brush = QBrush(fill_color) pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) for i in range(len(serie)): x, y_top, y_below = self._item_coordinates(ndx_serie, i) qp = QPainterPath() h = float(y_top - y_below - 1) if h > 0: qp.addRect(x, float(self.y_base - y_top), float(self.bar_width), h) painter.fillPath(qp, brush) if self.ndx_best_serie == ndx_serie and ( self.best_serie_intra_ndx is None or (self.best_serie_intra_ndx >= 0 and self.best_serie_intra_ndx == i)): pen.setWidth(3) else: pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) if ndx_serie == self.ndx_best_serie: fm = painter.fontMetrics() pen.setWidth(1) painter.setPen(pen) serie_below = None if ndx_serie < len(self.data) - 1: serie_below = self.data[ndx_serie + 1] for i in range(len(serie)): if (self.best_serie_intra_ndx == i) or self.best_serie_intra_ndx is None: x, y_top, y_below = self._item_coordinates(ndx_serie, i) l_len = 15 v = serie[i] if serie_below: v = v - serie_below[i] v = str(int(v)) bb = fm.boundingRect(v) pen.setColor(color) y = 0 if i < len(serie) - 1: # small diagonal going top, right painter.drawLine(x + self.bar_width, self.y_base - y_top, x + self.bar_width + l_len, self.y_base - (y_top + l_len)) x = x + self.bar_width + l_len y = y_top + l_len else: # small diagonal going top, left painter.drawLine(x, self.y_base - y_top, x - l_len, self.y_base - (y_top - l_len)) x = x - l_len - bb.width() y = y_top - l_len bb.moveTo(int(x), int(self.y_base - y - bb.height())) brush = QBrush(Qt.GlobalColor.red) bb.adjust(-2, +2, +4, +4) bb.adjust(-2, -2, +2, +2) painter.fillRect(bb, brush) bb.adjust(+2, +2, -2, -2) painter.drawRect(bb) pen.setColor(Qt.GlobalColor.white) painter.setPen(pen) painter.drawText(x, self.y_base - y, str(int(v)))