def _draw_bag_ends(self, painter): """ Draw markers to indicate the area the bag file represents within the current visible area. :param painter: allows access to paint functions,''QPainter'' """ x_start, x_end = self.map_stamp_to_x( self._start_stamp.to_sec()), self.map_stamp_to_x( self._end_stamp.to_sec()) painter.setBrush(QBrush(self._bag_end_color)) painter.drawRect(self._history_left, self._history_top, x_start - self._history_left, self._history_bottom - self._history_top) painter.drawRect(x_end, self._history_top, self._history_left + self._history_width - x_end, self._history_bottom - self._history_top) painter.setBrush(self._default_brush) painter.setPen(self._default_pen)
def __init__(self, track, text, starttime, duration): self._track = track super(TimelineClip, self).__init__(0.0, 0.0, duration, track.height, None, track.scene()) self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges) self.setFlag(QGraphicsItem.ItemIsMovable) self.setZValue(self._z) self.setBrush(QBrush(self._track._colors['item'])) self.setPen(QPen(self._track._colors['item'])) self._text = QGraphicsSimpleTextItem(text, self) self._text.setBrush(QColor(Qt.black)) self._text.setFont(QFont('sans', 12)) self._text.setPos(0.05, 0.05) self._text.setFlag(QGraphicsItem.ItemIgnoresTransformations) self.set_starttime(starttime) self.set_data([])
def enable_param_items(self): """ Create QStdItem per parameter and addColumn them to myself. :rtype: None if _dynreconf_client is not initiated. """ if not self._dynreconfclient_widget: return None paramnames = self._dynreconfclient_widget.get_treenode_names() paramnames_items = [] brush = QBrush(Qt.lightGray) for paramname in paramnames: item = ReadonlyItem(paramname) item.setBackground(brush) paramnames_items.append(item) rospy.logdebug('enable_param_items len of paramnames={}'.format( len(paramnames_items))) self.appendColumn(paramnames_items)
def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False, dashed=False): curve_id = str(curve_id) if curve_id in self._curves: return curve_object = Qwt.QwtPlotCurve(curve_name) curve_object.attach(self) curve_object.setPen(curve_color) if markers_on: curve_object.setSymbol( Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, QBrush(curve_color), QPen(Qt.black), QSize(4, 4))) self._curves[curve_id] = curve_object
def __init__(self, highlight_level, bounding_box, label, shape, color=None, parent=None, label_pos=None, tooltip=None): super(NodeItem, self).__init__(highlight_level, parent) self._default_color = self._COLOR_BLACK if color is None else color self._brush = QBrush(self._default_color) self._label_pen = QPen() self._label_pen.setColor(self._default_color) self._label_pen.setJoinStyle(Qt.RoundJoin) self._ellipse_pen = QPen(self._label_pen) self._ellipse_pen.setWidth(1) self._incoming_edges = set() self._outgoing_edges = set() if shape == 'box': self._graphics_item = QGraphicsRectItem(bounding_box) else: self._graphics_item = QGraphicsEllipseItem(bounding_box) self.addToGroup(self._graphics_item) self._label = QGraphicsSimpleTextItem(label) self._label.setFont(GraphItem._LABEL_FONT) label_rect = self._label.boundingRect() if label_pos is None: label_rect.moveCenter(bounding_box.center()) else: label_rect.moveCenter(label_pos) self._label.setPos(label_rect.x(), label_rect.y()) self.addToGroup(self._label) if tooltip is not None: self.setToolTip(tooltip) self.set_node_color() self.setAcceptHoverEvents(True) self.hovershape = None
def data(self, index, role=Qt.DisplayRole): column = index.column() row = index.row() if 0 <= row < self.rowCount() and 0 <= column < self.columnCount(): column = EntryModel.columns[index.column()] entry = self._entries[row] if role == Qt.DisplayRole: if column == "time": return entry.time_string() elif column == "entry": return entry.content if role == Qt.ForegroundRole and column == "entry" and entry.is_error: return QBrush(Qt.darkRed) return None
def _show_release_teleop_message(self, rtn): if rtn: QMessageBox.warning(self._widget, 'SUCCESS', "RELEASE!!!!", QMessageBox.Ok | QMessageBox.Ok) for k in self.robot_item_list.keys(): if self.robot_item_list[k] == self.current_captured_robot: k.setBackground(0, QBrush(Qt.NoBrush)) k.setBackgroundColor(0, QColor(0, 0, 0, 0)) robot_name = k.text(0) k.setText(0, robot_name[:robot_name.find(" (captured)")]) else: QMessageBox.warning(self._widget, 'FAIL', "FAIURE RELEASE!!!!", QMessageBox.Ok | QMessageBox.Ok) self._widget.setDisabled(False) self._widget.capture_teleop_btn.setEnabled(True) self._widget.release_teleop_btn.setEnabled(False) self.current_captured_robot = None
def __init__(self, scene, track_name, track_type, track_number, color=None): self._y = track_number * self.height super(TimelineTrack, self).__init__(self.starttime, self._y, self.length, self.height, None, scene) self._name = track_name self._type = track_type # if no color specified and non is assigned for this track type, assign next default color to this track type if color is None and self._type not in self._type_colors: color = self._default_colors[len(self._type_colors) % len(self._default_colors)] self._type_colors[self._type] = color self._colors = {} for part, alpha in self._color_alphas.items(): self._colors[part] = QColor(self._type_colors[self._type]) self._colors[part].setAlphaF(alpha) self.setBrush(QBrush(self._colors['track'])) self.setPen(QPen(Qt.NoPen))
def getComponentBrush(state): b = QBrush(QColor(0, 0, 255)) # unconfigured/preoperational if state == 'S': # stopped b = QBrush(QColor(255, 255, 255)) elif state == 'R': # running b = QBrush(QColor(0, 255, 0)) elif state == 'E': # error b = QBrush(QColor(255, 0, 0)) elif state == 'F': # fatal error b = QBrush(QColor(255, 127, 127)) elif state == 'X': # exception b = QBrush(QColor(0, 255, 255)) return b
def paintEvent(self, event): with self.lock: if self.status == 1: color = self._SUCCESS_COLOR elif self.status == 2: color = self._WARN_COLOR else: color = self._UNKNOWN_COLOR rect = event.rect() qp = QPainter() qp.begin(self) radius = min(rect.width(), rect.height()) - 100 qp.setFont(QFont('Helvetica', 100)) qp.setPen(QPen(QBrush(color), 50)) qp.setBrush(color) qp.drawEllipse((rect.width() - radius) / 2, (rect.height() - radius) / 2, radius, radius) qp.end() return
def _show_release_resource_message(self, rtn): if rtn: QMessageBox.warning(self, 'SUCCESS', "RELEASE!!!!", QMessageBox.Ok | QMessageBox.Ok) else: QMessageBox.warning(self, 'FAIL', "FAIURE RELEASE!!!!", QMessageBox.Ok | QMessageBox.Ok) self._lock.acquire() if rtn: for k in self.resource_item_list.keys(): if self.resource_item_list[k] == self.current_captured_resource: k.setBackground(0, QBrush(Qt.NoBrush)) k.setBackgroundColor(0, QColor(0, 0, 0, 0)) resource_name= k.text(0) k.setText(0, resource_name[:resource_name.find(" (captured)")]) self.setDisabled(False) self.capture_resource_btn.setEnabled(True) self.release_resource_btn.setEnabled(False) self.current_captured_resource= None self._lock.release()
def draw_scan(self, data): old_items = [] if len(self._scan_items): for item in self._scan_items: old_items.append(item) for pt in data: scan_item = self._scene.addRect(pt[0], pt[1], 1, 1, pen=QPen(QColor(0, 255, 0)), brush=QBrush(QColor(0, 255, 0))) # Everything must be mirrored self._mirror(scan_item) self._scan_items.append(scan_item) if len(old_items): for item in old_items: self._scene.removeItem(item) self._scan_items.remove(item)
def _draw_selected_region(self, painter): """ Draws a box around the selected region :param painter: allows access to paint functions,''QPainter'' """ if self._selected_left is None: return x_left = self.map_stamp_to_x(self._selected_left) if self._selected_right is not None: x_right = self.map_stamp_to_x(self._selected_right) else: x_right = self.map_stamp_to_x(self.playhead.to_sec()) left = x_left top = self._history_top - self._playhead_pointer_size[ 1] - 5 - self._time_font_size - 4 width = x_right - x_left height = self._history_top - top painter.setPen(self._selected_region_color) painter.setBrush(QBrush(self._selected_region_color)) painter.drawRect(left, top, width, height) painter.setPen(self._selected_region_outline_ends_color) painter.setBrush(Qt.NoBrush) painter.drawLine(left, top, left, top + height) painter.drawLine(left + width, top, left + width, top + height) painter.setPen(self._selected_region_outline_top_color) painter.setBrush(Qt.NoBrush) painter.drawLine(left, top, left + width, top) painter.setPen(self._selected_region_outline_top_color) painter.drawLine(left, self._history_top, left, self._history_bottom) painter.drawLine(left + width, self._history_top, left + width, self._history_bottom) painter.setBrush(self._default_brush) painter.setPen(self._default_pen)
def paintEvent(self, event): painter = QPainter(self) #painter.begin(self) # puts the arrow in the middle painter.translate(self.width() / 2, self.height() / 2) painter.rotate(self.angleRobo + self.angleVel) line = QLineF(0, 0, self.width() / 2 - 3, 0) headSize = min(self.width() / 20, 4) points = QPolygonF() points.append(QPointF(self.width() / 2 - headSize * 2, headSize)) points.append(QPointF(self.width() / 2 - headSize * 2, -headSize)) points.append(QPointF(self.width() / 2 - 3, 0)) pen = QPen(self.color, 2) painter.setPen(pen) brush = QBrush(self.color) painter.setBrush(brush) painter.drawLine(line) painter.drawConvexPolygon(points)
def _draw_playhead(self, painter): """ Draw a line and 2 triangles to denote the current position being viewed :param painter: ,''QPainter'' """ px = self.map_stamp_to_x(self.playhead.to_sec()) pw, ph = self._playhead_pointer_size # Line painter.setPen(QPen(self._playhead_color)) painter.setBrush(QBrush(self._playhead_color)) painter.drawLine(px, self._history_top - 1, px, self._history_bottom + 2) # Upper triangle py = self._history_top - ph painter.drawPolygon(QPolygonF([QPointF(px, py + ph), QPointF(px + pw, py), QPointF(px - pw, py)])) # Lower triangle py = self._history_bottom + 1 painter.drawPolygon(QPolygonF([QPointF(px, py), QPointF(px + pw, py + ph), QPointF(px - pw, py + ph)])) painter.setBrush(self._default_brush) painter.setPen(self._default_pen)
def paintEvent(self, event): with self.lock: self.event = event rect = event.rect() qp = QPainter() qp.begin(self) radius = min(rect.width(), rect.height()) - 50 qp.setFont(QFont('Helvetica', 100)) qp.setPen(QPen(QBrush(QColor(255, 255, 255)), 20)) if self.is_disabled: qp.fillRect(rect, self._DISABLED_COLOR) qp.drawText(rect, QtCore.Qt.AlignCenter, self._FROWN) elif self.is_blackout: qp.fillRect(rect, self._BLACKOUT_COLOR) qp.drawText(rect, QtCore.Qt.AlignCenter, self._FROWN) time_diff = (self.next_whiteout_time - rospy.Time.now()).to_sec() if time_diff < 0: time_diff = 0 time_ratio = time_diff / (self.next_whiteout_time - self.blackout_time).to_sec() qp.setFont(QFont('Helvetica', 30)) qp.drawText(0, rect.height() - 150, rect.width(), 150, QtCore.Qt.AlignCenter, "%.1f sec" % time_diff) # 0-360 if time_ratio > 0: rad = int(math.fmod(time_ratio * 360 + 90 * 16, 360) * 16) qp.drawArc((rect.width() - radius) / 2, (rect.height() - radius) / 2, radius, radius, 90 * 16, rad) else: qp.fillRect(rect, self._OK_COLOR) qp.drawText(rect, QtCore.Qt.AlignCenter, self._SMILEY) qp.end()
def do_take_sample(self): try: px_x = int(self._widget.spinbox_pixel_location_x.value()) px_y = int(self._widget.spinbox_pixel_location_y.value()) b = self.cv_image.item(px_y, px_x, 0) g = self.cv_image.item(px_y, px_x, 1) r = self.cv_image.item(px_y, px_x, 2) px_bgr = np.zeros((1, 1, 3), np.uint8) px_bgr[:] = tuple((b, g, r)) px_hsv = cv2.cvtColor(px_bgr, cv2.COLOR_BGR2HSV) h = px_hsv.item(0, 0, 0) s = px_hsv.item(0, 0, 1) v = px_hsv.item(0, 0, 2) self._widget.line_edit_pixel_b.setText(str(b)) self._widget.line_edit_pixel_g.setText(str(g)) self._widget.line_edit_pixel_r.setText(str(r)) self._widget.line_edit_pixel_h.setText(str(h)) self._widget.line_edit_pixel_s.setText(str(s)) self._widget.line_edit_pixel_v.setText(str(v)) self.colour_pane_scene.setForegroundBrush(QBrush(QColor(r, g, b))) self._widget.graphics_view_colour_pane.show() if not self.args.quiet: rospy.loginfo("----------------") rospy.loginfo("XY: [%d, %d]" % (px_x, px_y)) rospy.loginfo("RGB: [%d, %d, %d]" % (r, g, b)) rospy.loginfo("HSV: [%d, %d, %d]" % (h, s, v)) except Exception as e: rospy.loginfo(e)
def __init__(self, parent=None): super(Widget, self).__init__(parent) self.setWindowTitle('U-CTF View') self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) # game cube grass area grass_color = QColor(0, 255, 0, 50) self._scene.addRect( 0, 0, CUBE_LENGTH, CUBE_LENGTH, QPen(grass_color), QBrush(grass_color)) # blue team area blue_color = QColor(0, 0, 255, 50) self._scene.addRect( 0, -SUPPORT_AREA_DEPTH, CUBE_LENGTH, SUPPORT_AREA_DEPTH, QPen(blue_color), QBrush(blue_color)) # gold team area gold_color = QColor(255, 215, 0, 50) self._scene.addRect( 0, CUBE_LENGTH, CUBE_LENGTH, SUPPORT_AREA_DEPTH, QPen(gold_color), QBrush(gold_color)) # penalty area orange_color = QColor(0, 200, 0, 50) self._scene.addRect( CUBE_LENGTH, 0, SUPPORT_AREA_DEPTH, CUBE_LENGTH, QPen(orange_color), QBrush(orange_color)) # rotate view to match the coordinate system of the game cube self.rotate(180) self.setScene(self._scene) # pens and brushes for the vehicles self._pens = { 'blue': QPen(Qt.blue, 2), 'gold': QPen(QColor(191, 151, 0), 2), } self._brushes = { 'blue': QBrush(Qt.blue), 'gold': QBrush(QColor(191, 151, 0)), } self._vehicles = {}
def data(self, index, role=None): """ Sets colors of items based on highlight filters and severity type """ messagelist = self.sourceModel()._messages.get_message_list() index = self.mapToSource(index) if index.row() >= 0 or index.row() < len(messagelist): if index.column() >= 0 or index.column() < messagelist[index.row()].count(): if role == Qt.ForegroundRole: if index.column() == 1: data = index.data() severity_levels = {'Debug':QBrush(Qt.cyan), \ 'Info':QBrush(Qt.darkCyan), \ 'Warn':QBrush(Qt.darkYellow), \ 'Error':QBrush(Qt.darkRed), \ 'Fatal':QBrush(Qt.red)} if data in severity_levels.keys(): return severity_levels[data] else: raise KeyError('Unknown severity type: %s'% data) if self._highlight_filters.count_enabled_filters() > 0: if not self._highlight_filters.test_message(messagelist[index.row()]): return QBrush(Qt.gray) return self.sourceModel().data(index, role)
def draw_timeline_segment(self, painter, topic, stamp_start, stamp_end, x, y, width, height): """ draws a stream of images for the topic :param painter: painter object, ''QPainter'' :param topic: topic to draw, ''str'' :param stamp_start: stamp to start drawing, ''rospy.Time'' :param stamp_end: stamp to end drawing, ''rospy.Time'' :param x: x to draw images at, ''int'' :param y: y to draw images at, ''int'' :param width: width in pixels of the timeline area, ''int'' :param height: height in pixels of the timeline area, ''int'' """ if x < self.timeline._history_left: width += x - self.timeline._history_left x = self.timeline._history_left max_interval_thumbnail = self.timeline.map_dx_to_dstamp(self.thumbnail_combine_px) max_interval_thumbnail = max(0.1, max_interval_thumbnail) thumbnail_gap = 6 thumbnail_x, thumbnail_y, thumbnail_height = x + 1, y + 1, height - 2 - thumbnail_gap # leave 1px border # set color to white draw rectangle over messages painter.setBrush(QBrush(Qt.white)) painter.drawRect(x, y, width, height - thumbnail_gap) thumbnail_width = None while True: available_width = (x + width) - thumbnail_x # Check for enough remaining to draw thumbnail if width > 1 and available_width < self.min_thumbnail_width: break # Try to display the thumbnail, if its right edge is to the right of the timeline's left side if not thumbnail_width or thumbnail_x + thumbnail_width >= self.timeline._history_left: stamp = self.timeline.map_x_to_stamp(thumbnail_x, clamp_to_visible=False) thumbnail_bitmap = self.thumbnail_cache.get_item(topic, stamp, max_interval_thumbnail) # Cache miss if not thumbnail_bitmap: thumbnail_details = (thumbnail_height,) self.thumbnail_cache.enqueue((topic, stamp, max_interval_thumbnail, thumbnail_details)) if not thumbnail_width: break else: thumbnail_width, _ = thumbnail_bitmap.size if width > 1: if available_width < thumbnail_width: thumbnail_width = available_width - 1 QtImage = ImageQt(thumbnail_bitmap) pixmap = QPixmap.fromImage(QtImage) painter.drawPixmap(thumbnail_x, thumbnail_y, thumbnail_width, thumbnail_height, pixmap) thumbnail_x += thumbnail_width if width == 1: break painter.setPen(QPen(Qt.black)) painter.setBrush(QBrush(Qt.transparent)) if width == 1: painter.drawRect(x, y, thumbnail_x - x, height - thumbnail_gap - 1) else: painter.drawRect(x, y, width, height - thumbnail_gap - 1) return True
def __init__(self, spline, label, label_center, from_node, to_node, parent=None, **kwargs): super(EdgeItem, self).__init__(parent, **kwargs) self._edge_pen_width = kwargs.get('edge_pen_width', self.EDGE_PEN_WIDTH) self.from_node = from_node self.from_node.add_outgoing_edge(self) self.to_node = to_node self.to_node.add_incoming_edge(self) self._brush = QBrush(self._color) self._label_pen = QPen() self._label_pen.setColor(self._color) self._label_pen.setJoinStyle(Qt.RoundJoin) self._label_pen.setWidthF(self._label_pen_width) self._edge_pen = QPen() self._edge_pen.setColor(self._color) self._edge_pen.setWidthF(self._edge_pen_width) self._sibling_edges = set() self._label = None if label is not None: self._label = QGraphicsSimpleTextItem(label) font = self._label.font() font.setPointSize(8) self._label.setFont(font) label_rect = self._label.boundingRect() label_rect.moveCenter(label_center) self._label.setPos(label_rect.x(), label_rect.y()) # spline specification according to http://www.graphviz.org/doc/info/attrs.html#k:splineType coordinates = spline.split(' ') # extract optional end_point end_point = None if coordinates[0].startswith('e,'): parts = coordinates.pop(0)[2:].split(',') end_point = QPointF(float(parts[0]), -float(parts[1])) # extract optional start_point if coordinates[0].startswith('s,'): parts = coordinates.pop(0).split(',') # first point parts = coordinates.pop(0).split(',') point = QPointF(float(parts[0]), -float(parts[1])) path = QPainterPath(point) while len(coordinates) > 2: # extract triple of points for a cubic spline parts = coordinates.pop(0).split(',') point1 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point2 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point3 = QPointF(float(parts[0]), -float(parts[1])) path.cubicTo(point1, point2, point3) self._arrow = None if end_point is not None: # draw arrow self._arrow = QGraphicsPolygonItem() polygon = QPolygonF() polygon.append(point3) offset = QPointF(end_point - point3) corner1 = QPointF(-offset.y(), offset.x()) * 0.35 corner2 = QPointF(offset.y(), -offset.x()) * 0.35 polygon.append(point3 + corner1) polygon.append(end_point) polygon.append(point3 + corner2) self._arrow.setPolygon(polygon) self._path = QGraphicsPathItem() self._path.setPath(path) self.addToGroup(self._path) self._brush.setColor(self._color) self._edge_pen.setColor(self._color) self._label_pen.setColor(self._color) self._path.setPen(self._edge_pen) if self._arrow is not None: self._arrow.setBrush(self._brush) self._arrow.setPen(self._edge_pen) if self._label is not None: self._label.setBrush(self._brush) self._label.setPen(self._label_pen)
def config_timeline_frame(_self): self = _self._timeline._timeline_frame # Background Rendering self._bag_end_color = QColor( 76, 76, 76 ) # QColor(0, 0, 0, 25) # color of background of timeline before first message and after last self._history_background_color_alternate = QColor(179, 179, 179, 90) self._history_background_color = QColor(204, 204, 204, 102) # Timeline Division Rendering # Possible time intervals used between divisions # 1ms, 5ms, 10ms, 50ms, 100ms, 500ms # 1s, 5s, 15s, 30s # 1m, 2m, 5m, 10m, 15m, 30m # 1h, 2h, 3h, 6h, 12h # 1d, 7d self._sec_divisions = [ 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 15, 30, 1 * 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 1 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 6 * 60 * 60, 12 * 60 * 60, 1 * 60 * 60 * 24, 7 * 60 * 60 * 24 ] self._minor_spacing = 15 self._major_spacing = 50 self._major_divisions_label_indent = 3 # padding in px between line and label self._major_division_pen = QPen(QBrush(QColor(76, 76, 76)), 0, Qt.DashLine) self._minor_division_pen = QPen(QBrush(QColor(76, 76, 76, 75)), 0, Qt.DashLine) self._minor_division_tick_pen = QPen( QBrush(QColor(128, 128, 128, 128)), 0) # Topic Rendering self.topics = [] self._topics_by_datatype = {} self._topic_font_height = None self._topic_name_sizes = None self._topic_name_spacing = 30 # minimum pixels between end of topic name and start of history self._topic_font_size = 11 self._topic_font = QFont("courier new") self._topic_font.setPointSize(self._topic_font_size) self._topic_font.setBold(False) self._topic_vertical_padding = 10 self._topic_name_max_percent = 25.0 # percentage of the horiz space that can be used for topic display # Time Rendering self._time_tick_height = 5 self._time_font_height = None self._time_font_size = 10.0 self._time_font = QFont("courier new") self._time_font.setPointSize(self._time_font_size) self._time_font.setBold(False) # Defaults self._default_brush = QBrush(Qt.black, Qt.SolidPattern) self._default_pen = QPen(QColor(240, 240, 240)) self._default_datatype_color = QColor(255, 180, 125, 75) # QColor(0, 0, 102, 204) self._datatype_colors = { 'sensor_msgs/CameraInfo': QColor(0, 0, 77, 204), 'sensor_msgs/Image': QColor(0, 77, 77, 204), 'sensor_msgs/LaserScan': QColor(153, 0, 0, 204), 'pr2_msgs/LaserScannerSignal': QColor(153, 0, 0, 204), 'pr2_mechanism_msgs/MechanismState': QColor(0, 153, 0, 204), 'tf/tfMessage': QColor(0, 153, 0, 204), } self._default_msg_combine_px = 1.0 # minimum number of pixels allowed between two bag messages before they are combined self._active_message_line_width = 3 # Selected Region Rendering self._selected_region_color = QColor(0, 179, 0, 42) self._selected_region_outline_top_color = QColor(0.0, 77, 0.0, 102) self._selected_region_outline_ends_color = QColor(0.0, 77, 0.0, 204) self._selected_left = None self._selected_right = None self._selection_handle_width = 3.0 # Playhead Rendering self._playhead = None # timestamp of the playhead self._paused = False self._playhead_pointer_size = (6, 6) self._playhead_line_width = 1 self._playhead_color = QColor(255, 255, 255, 191) # Zoom self._zoom_sensitivity = 0.005 self._min_zoom_speed = 0.5 self._max_zoom_speed = 2.0 self._min_zoom = 0.0001 # max zoom out (in px/s) self._max_zoom = 50000.0 # max zoom in (in px/s) # Timeline boundries self._start_stamp = None # earliest of all stamps self._end_stamp = None # latest of all stamps self._stamp_left = None # earliest currently visible timestamp on the timeline self._stamp_right = None # latest currently visible timestamp on the timeline self._history_top = 30 self._history_left = 0 self._history_width = 0 self._history_bottom = 0 self._history_bounds = {} self._margin_left = 30 self._margin_right = 20 self._margin_bottom = 20
def __init__(self, highlight_level, spline, label_center, label, from_node, to_node, parent=None, penwidth=1, edge_color=None, style='solid'): super(EdgeItem, self).__init__(highlight_level, parent) self.from_node = from_node self.from_node.add_outgoing_edge(self) self.to_node = to_node self.to_node.add_incoming_edge(self) self._default_edge_color = self._COLOR_BLACK if edge_color is not None: self._default_edge_color = edge_color self._default_text_color = self._COLOR_BLACK self._default_color = self._COLOR_BLACK self._text_brush = QBrush(self._default_color) self._shape_brush = QBrush(self._default_color) if style in ['dashed', 'dotted']: self._shape_brush = QBrush(Qt.transparent) self._label_pen = QPen() self._label_pen.setColor(self._default_text_color) self._label_pen.setJoinStyle(Qt.RoundJoin) self._edge_pen = QPen(self._label_pen) self._edge_pen.setWidth(penwidth) self._edge_pen.setColor(self._default_edge_color) self._edge_pen.setStyle(self._qt_pen_styles.get(style, Qt.SolidLine)) self._sibling_edges = set() self._label = None if label is not None: self._label = QGraphicsSimpleTextItem(label) label_rect = self._label.boundingRect() label_rect.moveCenter(label_center) self._label.setPos(label_rect.x(), label_rect.y()) self._label.hoverEnterEvent = self._handle_hoverEnterEvent self._label.hoverLeaveEvent = self._handle_hoverLeaveEvent self._label.setAcceptHoverEvents(True) # spline specification according to http://www.graphviz.org/doc/info/attrs.html#k:splineType coordinates = spline.split(' ') # extract optional end_point end_point = None if (coordinates[0].startswith('e,')): parts = coordinates.pop(0)[2:].split(',') end_point = QPointF(float(parts[0]), -float(parts[1])) # extract optional start_point if (coordinates[0].startswith('s,')): parts = coordinates.pop(0).split(',') # first point parts = coordinates.pop(0).split(',') point = QPointF(float(parts[0]), -float(parts[1])) path = QPainterPath(point) while len(coordinates) > 2: # extract triple of points for a cubic spline parts = coordinates.pop(0).split(',') point1 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point2 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point3 = QPointF(float(parts[0]), -float(parts[1])) path.cubicTo(point1, point2, point3) self._arrow = None if end_point is not None: # draw arrow self._arrow = QGraphicsPolygonItem() polygon = QPolygonF() polygon.append(point3) offset = QPointF(end_point - point3) corner1 = QPointF(-offset.y(), offset.x()) * 0.35 corner2 = QPointF(offset.y(), -offset.x()) * 0.35 polygon.append(point3 + corner1) polygon.append(end_point) polygon.append(point3 + corner2) self._arrow.setPolygon(polygon) self._arrow.hoverEnterEvent = self._handle_hoverEnterEvent self._arrow.hoverLeaveEvent = self._handle_hoverLeaveEvent self._arrow.setAcceptHoverEvents(True) self._path = QGraphicsPathItem() self._path.setPath(path) self.addToGroup(self._path) self.set_node_color() self.set_label_color()
def paint(self, ctx): assert isinstance(ctx, QPainter) base_eye_pos = (self.width / 4.0, self.height / 12.0) mx_factor = self.width / 150.0 * 7 my_factor = self.height / 150.0 * 7 mx = (self.look_x + 1.0) / 2.0 * mx_factor - 1 my = (self.look_y + 1.0) / 2.0 * my_factor - 1 fdx = (self.look_x + 1.0) / 2.0 * 6 fdy = (self.look_y + 1.0) / 2.0 * 14 sx = 2 sy = 2 # face if self.draw_contour: ctx.setBrush(self.face_color) ctx.setPen(NOPEN) ctx.drawEllipse(sx + 4, sy, self.width - 8, self.height) ctx.drawEllipse(sx + 4, sy, self.width - 8, int(self.height * 0.66)) else: ctx.fillRect(0, 0, self.width, self.height, self.face_color) left_eye_center = fdx + sx + self.width / 2.0, fdy + sy + self.height / 3.0 right_eye_center = fdx + sx + self.width / 2.0, fdy + sy + self.height / 3.0 eye_height = int(base_eye_pos[1] * (1.0 + self._emotion[0]) + 2) pupil_radius = int(base_eye_pos[0] / 4.0) eye_brow_space = int(base_eye_pos[1] * (1.0 + self._emotion[1] / 2.0) + 1) eye_brow_outer = int(-self._emotion[2] * base_eye_pos[1] / 2.0) eye_brow_inner = int(-self._emotion[3] * base_eye_pos[1] / 2.0) eye_brow_boldness = 2 # left eye left_eye_offset_x = -int(base_eye_pos[0] * 1.4) ctx.setBrush(QBrush(WHITE)) ctx.setPen(NOPEN) ctx.drawChord(left_eye_center[0] + left_eye_offset_x, left_eye_center[1] - eye_height / 2.0, base_eye_pos[0], eye_height, 0, 360 * 16) ctx.setBrush(QBrush(LIGHTBLUE)) ctx.setPen(NOPEN) ctx.drawChord( left_eye_center[0] + left_eye_offset_x + mx + base_eye_pos[0] * 0.5 - pupil_radius / 2.0, left_eye_center[1] + my - pupil_radius / 2.0, pupil_radius, pupil_radius, 0, 360 * 16) ctx.setBrush(QBrush(BLACK)) ctx.setPen(NOPEN) ctx.drawChord( left_eye_center[0] + left_eye_offset_x + mx + base_eye_pos[0] * 0.5 - pupil_radius / 5.0, left_eye_center[1] + my - pupil_radius / 5.0, pupil_radius / 2.5, pupil_radius / 2.5, 0, 360 * 16) ctx.fillRect( left_eye_center[0] + left_eye_offset_x, left_eye_center[1] - eye_height / 2.0 - base_eye_pos[0] / 2.0, base_eye_pos[0], base_eye_pos[0] / 2.0, self.face_color) ctx.fillRect(left_eye_center[0] + left_eye_offset_x, left_eye_center[1] + eye_height / 2.0, base_eye_pos[0], base_eye_pos[0] / 2.0, self.face_color) # left eye brow ctx.setPen(BLACK) for b in range(eye_brow_boldness): ctx.drawLine( left_eye_center[0] + left_eye_offset_x, left_eye_center[1] - eye_brow_space + eye_brow_outer + b, left_eye_center[0] + left_eye_offset_x + base_eye_pos[0], left_eye_center[1] - eye_brow_space + eye_brow_inner + b) # right eye right_eye_offset_x = int(base_eye_pos[0] * 0.4) ctx.setBrush(QBrush(WHITE)) ctx.setPen(NOPEN) ctx.drawChord(right_eye_center[0] + right_eye_offset_x, right_eye_center[1] - eye_height / 2.0, base_eye_pos[0], eye_height, 0, 360 * 16) ctx.setBrush(QBrush(LIGHTBLUE)) ctx.setPen(NOPEN) ctx.drawChord( right_eye_center[0] + right_eye_offset_x + mx + base_eye_pos[0] * 0.5 - pupil_radius / 2.0, right_eye_center[1] + my - pupil_radius / 2.0, pupil_radius, pupil_radius, 0, 360 * 16) ctx.setBrush(QBrush(BLACK)) ctx.setPen(NOPEN) ctx.drawChord( mx + right_eye_center[0] + right_eye_offset_x + base_eye_pos[0] * 0.5 - pupil_radius / 5.0, my + right_eye_center[1] - pupil_radius / 5.0, pupil_radius / 2.5, pupil_radius / 2.5, 0, 360 * 16) ctx.fillRect( right_eye_center[0] + right_eye_offset_x, right_eye_center[1] - eye_height / 2.0 - base_eye_pos[0] / 2.0, base_eye_pos[0], base_eye_pos[0] / 2.0, self.face_color) ctx.fillRect(right_eye_center[0] + right_eye_offset_x, right_eye_center[1] + eye_height / 2.0, base_eye_pos[0], base_eye_pos[0] / 2.0, self.face_color) # right eye brow ctx.setPen(BLACK) for b in range(eye_brow_boldness): ctx.drawLine( right_eye_center[0] + right_eye_offset_x, right_eye_center[1] - eye_brow_space + eye_brow_inner + b, right_eye_center[0] + right_eye_offset_x + base_eye_pos[0], right_eye_center[1] - eye_brow_space + eye_brow_outer + b) # mouth base_mouth_pos = (self.width / 2.0, self.height / 6.0) smx = fdx + sx + self.width / 2.0 smy = fdy + sy + 2.0 * self.height / 3.0 mw = int(base_mouth_pos[0] * (self._emotion[4] + 4) / 6.0) mo = int(base_mouth_pos[1] * (self._emotion[5] + 1) / 3.0) mt = int(base_mouth_pos[1] * (self._emotion[6] + 0) / 2.0) tv = int(base_mouth_pos[1] * (self._emotion[7] - 1) / 3.0) upper_lip = mt - mo lower_lip = mt + mo shift = -mt if upper_lip > 0: if lower_lip > 0: ctx.setBrush(QBrush(WHITE)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy - lower_lip, mw, lower_lip * 2, -180 * 16, 180 * 16) else: ctx.setBrush(QBrush(self.face_color)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy + lower_lip, mw, -lower_lip * 2, 0, 180 * 16) ctx.setBrush(QBrush(self.face_color)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy - upper_lip, mw, upper_lip * 2, -180 * 16, 180 * 16) else: ctx.setBrush(QBrush(WHITE)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy + upper_lip, mw, -upper_lip * 2, 0, 180 * 16) if lower_lip > 0: ctx.setBrush(QBrush(WHITE)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy - lower_lip, mw, lower_lip * 2, -180 * 16, 180 * 16) else: ctx.setBrush(QBrush(self.face_color)) ctx.setPen(NOPEN) ctx.drawChord(smx - mw / 2, shift + smy + lower_lip, mw, -lower_lip * 2, 0, 180 * 16) ctx.fillRect(smx - mw / 2.0, smy + tv, mw, -tv * 2, self.face_color) # teeth ctx.setPen(self.face_color) for i in range(6): ctx.drawLine(smx - base_mouth_pos[0] * (0.5 - i * 0.2), smy - abs(mt) - mo, smx - base_mouth_pos[0] * (0.5 - i * 0.2), smy + abs(mt) + mo) ctx.drawLine(smx - base_mouth_pos[0] / 2.0, smy, smx + base_mouth_pos[0] / 2.0, smy) # lips ctx.setBrush(NOBRUSH) ctx.setPen(LIGHTRED) if upper_lip > 0: ctx.drawArc(smx - mw / 2, shift + smy - upper_lip, mw, upper_lip * 2, -180 * 16, 180 * 16) else: ctx.drawArc(smx - mw / 2, shift + smy + upper_lip, mw, -upper_lip * 2, 0, 180 * 16) if lower_lip > 0: ctx.drawArc(smx - mw / 2, shift + smy - lower_lip, mw, lower_lip * 2, -180 * 16, 180 * 16) else: ctx.drawArc(smx - mw / 2, shift + smy + lower_lip, mw, -lower_lip * 2, 0, 180 * 16)
class MessageDataModel(QAbstractTableModel): # the column names must match the message attributes columns = ['message', 'severity', 'node', 'stamp', 'location'] severity_colors = { Message.DEBUG: QBrush(Qt.darkCyan), Message.INFO: QBrush(Qt.darkBlue), Message.WARN: QBrush(Qt.darkYellow), Message.ERROR: QBrush(Qt.darkRed), Message.FATAL: QBrush(Qt.red), } def __init__(self): super(MessageDataModel, self).__init__() self._messages = MessageList() self._message_limit = 20000 self._info_icon = QIcon.fromTheme('dialog-information') self._warning_icon = QIcon.fromTheme('dialog-warning') self._error_icon = QIcon.fromTheme('dialog-error') # BEGIN Required implementations of QAbstractTableModel functions def rowCount(self, parent=None): return len(self._messages) def columnCount(self, parent=None): return len(MessageDataModel.columns) + 1 def data(self, index, role=None): if role is None: role = Qt.DisplayRole if index.row() >= 0 and index.row() < len(self._messages): msg = self._messages[index.row()] if index.column() == 0: if role == Qt.DisplayRole: return '#%d' % msg.id elif index.column() > 0 and index.column() < len(MessageDataModel.columns) + 1: column = MessageDataModel.columns[index.column() - 1] if role == Qt.DisplayRole or role == Qt.UserRole: if column == 'stamp': if role != Qt.UserRole: data = msg.get_stamp_string() else: data = msg.get_stamp_for_compare() else: data = getattr(msg, column) # map severity enum to label if role == Qt.DisplayRole and column == 'severity': data = Message.SEVERITY_LABELS[data] # implode topic names if column == 'topics': data = ', '.join(data) # append row number to define strict order if role == Qt.UserRole: # append row number to define strict order # shortest string representation to compare stamps # print(column, data, str(index.row()).zfill(len(str(len(self._messages))))) data = str(data) + ' %08x' % index.row() return data # decorate message column with severity icon if role == Qt.DecorationRole and column == 'message': if msg.severity in [Message.DEBUG, Message.INFO]: return self._info_icon elif msg.severity in [Message.WARN]: return self._warning_icon elif msg.severity in [Message.ERROR, Message.FATAL]: return self._error_icon # colorize severity label if role == Qt.ForegroundRole and column == 'severity': assert msg.severity in MessageDataModel.severity_colors, \ 'Unknown severity type: %s' % msg.severity return MessageDataModel.severity_colors[msg.severity] if role == Qt.ToolTipRole and column != 'severity': if column == 'stamp': data = msg.get_stamp_string() elif column == 'topics': data = ', '.join(msg.topics) else: data = getattr(msg, column) # <font> tag enables word wrap by forcing rich text return '<font>' + data + '<br/><br/>' + \ self.tr('Right click for menu.') + '</font>' def headerData(self, section, orientation, role=None): if role is None: role = Qt.DisplayRole if orientation == Qt.Horizontal: if role == Qt.DisplayRole: if section == 0: return self.tr('#') else: return MessageDataModel.columns[section - 1].capitalize() if role == Qt.ToolTipRole: if section == 0: return self.tr('Sort the rows by serial number in descendig order') else: return self.tr( 'Sorting the table by a column other then the serial number slows down the ' 'interaction especially when recording high frequency data') # END Required implementations of QAbstractTableModel functions def get_message_limit(self): return self._message_limit def set_message_limit(self, new_limit): self._message_limit = new_limit self._enforce_message_limit(self._message_limit) def _enforce_message_limit(self, limit): if len(self._messages) > limit: self.beginRemoveRows(QModelIndex(), limit, len(self._messages) - 1) del self._messages[limit:len(self._messages)] self.endRemoveRows() def insert_rows(self, msgs): # never try to insert more message than the limit if len(msgs) > self._message_limit: msgs = msgs[-self._message_limit:] # reduce model before insert limit = self._message_limit - len(msgs) self._enforce_message_limit(limit) # insert newest messages self.beginInsertRows(QModelIndex(), 0, len(msgs) - 1) self._messages.extend(msgs) self.endInsertRows() def remove_rows(self, rowlist): """ :param rowlist: list of row indexes, ''list(int)'' :returns: True if the indexes were removed successfully, ''bool'' """ if len(rowlist) == 0: if len(self._messages) > 0: try: self.beginRemoveRows(QModelIndex(), 0, len(self._messages)) del self._messages[0:len(self._messages)] self.endRemoveRows() except: return False else: rowlist = list(set(rowlist)) rowlist.sort(reverse=True) dellist = [rowlist[0]] for row in rowlist[1:]: if dellist[-1] - 1 > row: try: self.beginRemoveRows(QModelIndex(), dellist[-1], dellist[0]) del self._messages[dellist[-1]:dellist[0] + 1] self.endRemoveRows() except: return False dellist = [] dellist.append(row) if len(dellist) > 0: try: self.beginRemoveRows(QModelIndex(), dellist[-1], dellist[0]) del self._messages[dellist[-1]:dellist[0] + 1] self.endRemoveRows() except: return False return True def get_selected_text(self, rowlist): """ Returns an easily readable block of text for the currently selected rows :param rowlist: list of row indexes, ''list(int)'' :returns: the text from those indexes, ''str'' """ text = None if len(rowlist) != 0: text = '' rowlist = list(set(rowlist)) for row in rowlist: text += self._messages[row].pretty_print() return text def get_time_range(self, rowlist): """ :param rowlist: a list of row indexes, ''list'' :returns: a tuple of min and max times in a rowlist in '(unix timestamp).(fraction of second)' format, ''tuple(str,str)'' """ min_ = float("inf") max_ = float("-inf") for row in rowlist: item = self._messages[row].time_as_datestamp() if float(item) > float(max_): max_ = item if float(item) < float(min_): min_ = item return min_, max_ def get_unique_nodes(self): nodes = set() for message in self._messages: nodes.add(message.node) return nodes def get_unique_severities(self): severities = set() for message in self._messages: severities.add(message.severity) return severities def get_unique_topics(self): topics = set() for message in self._messages: for topic in message.topics: topics.add(topic) return topics def get_severity_dict(self): return Message.SEVERITY_LABELS def get_message_between(self, start_time, end_time=None): """ :param start_time: time to start in timestamp form (including decimal fractions of a second is acceptable, ''unixtimestamp'' :param end_time: time to end in timestamp form (including decimal fractions of a second is acceptable, ''unixtimestamp'' (Optional) :returns: list of messages in the time range ''list[message]'' """ msgs = [] for message in self._messages: msg_time = message.stamp[0] + float(message.stamp[1]) / 10**9 if msg_time >= float(start_time) and (end_time is None or msg_time <= float(end_time)): msgs.append(message) return msgs
def _draw_topic_history(self, painter, topic): """ Draw boxes corrisponding to message regions on the timeline. :param painter: allows access to paint functions,''QPainter'' :param topic: the topic for which message boxes should be drawn, ''str'' """ # x, y, w, h = self._history_bounds[topic] _, y, _, h = self._history_bounds[topic] msg_y = y + 2 msg_height = h - 2 datatype = self.scene().get_datatype(topic) # Get the renderer and the message combine interval renderer = None msg_combine_interval = None if topic in self._rendered_topics: renderer = self._timeline_renderers.get(datatype) if not renderer is None: msg_combine_interval = self.map_dx_to_dstamp(renderer.msg_combine_px) if msg_combine_interval is None: msg_combine_interval = self.map_dx_to_dstamp(self._default_msg_combine_px) # Get the cache if topic not in self.index_cache: return all_stamps = self.index_cache[topic] # start_index = bisect.bisect_left(all_stamps, self._stamp_left) end_index = bisect.bisect_left(all_stamps, self._stamp_right) # Set pen based on datatype datatype_color = self._datatype_colors.get(datatype, self._default_datatype_color) # Iterate through regions of connected messages width_interval = self._history_width / (self._stamp_right - self._stamp_left) # Draw stamps for (stamp_start, stamp_end) in self._find_regions(all_stamps[:end_index], self.map_dx_to_dstamp(self._default_msg_combine_px)): if stamp_end < self._stamp_left: continue region_x_start = self._history_left + (stamp_start - self._stamp_left) * width_interval if region_x_start < self._history_left: region_x_start = self._history_left # Clip the region region_x_end = self._history_left + (stamp_end - self._stamp_left) * width_interval region_width = max(1, region_x_end - region_x_start) painter.setBrush(QBrush(datatype_color)) painter.setPen(QPen(datatype_color, 1)) painter.drawRect(region_x_start, msg_y, region_width, msg_height) # Draw active message if topic in self.scene()._listeners: curpen = painter.pen() oldwidth = curpen.width() curpen.setWidth(self._active_message_line_width) painter.setPen(curpen) playhead_stamp = None playhead_index = bisect.bisect_right(all_stamps, self.playhead.to_sec()) - 1 if playhead_index >= 0: playhead_stamp = all_stamps[playhead_index] if playhead_stamp > self._stamp_left and playhead_stamp < self._stamp_right: playhead_x = self._history_left + (all_stamps[playhead_index] - self._stamp_left) * width_interval painter.drawLine(playhead_x, msg_y, playhead_x, msg_y + msg_height) curpen.setWidth(oldwidth) painter.setPen(curpen) # Custom renderer if renderer: # Iterate through regions of connected messages for (stamp_start, stamp_end) in self._find_regions(all_stamps[:end_index], msg_combine_interval): if stamp_end < self._stamp_left: continue region_x_start = self._history_left + (stamp_start - self._stamp_left) * width_interval region_x_end = self._history_left + (stamp_end - self._stamp_left) * width_interval region_width = max(1, region_x_end - region_x_start) renderer.draw_timeline_segment(painter, topic, stamp_start, stamp_end, region_x_start, msg_y, region_width, msg_height) painter.setBrush(self._default_brush) painter.setPen(self._default_pen)
def add_robot(self): rospy.loginfo('rqt_simulation : A new robot tab has been added.') # Add tab self.num_robots += 1 self.tab_list.append(RobotTab(self.num_robots, self.robots)) #self.tab_list[self.num_robots-1].signalRobotNameChanged.connect(self.robot_name_changed) self.tabWidget.addTab(self.tab_list[self.num_robots - 1], ('Robot ' + str(self.num_robots))) self.button_remove_robot.setEnabled(True) self.current_graphicsScene.addItem( self.tab_list[self.num_robots - 1].initial_pose[ 'start_' + str(self.num_robots).zfill(2)]['text_item']) # Set initial pose if self.num_robots > 1: for i in range(0, len(self.FTS.region_of_interest)): self.tab_list[self.num_robots - 1].robot_comboBox_init.addItem( self.FTS.region_of_interest.keys()[i]) self.tab_list[self.num_robots - 1].robot_comboBox_init.model().sort(0) if len(self.current_graphicsScene.items_dict) > 0: self.tab_list[ self.num_robots - 1].init_pose_msg.position.x = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['position'][0] self.tab_list[ self.num_robots - 1].init_pose_msg.position.y = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['position'][1] self.tab_list[ self.num_robots - 1].init_pose_msg.position.z = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['position'][2] self.tab_list[ self.num_robots - 1].init_pose_msg.orientation.w = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['orientation'][0] self.tab_list[ self.num_robots - 1].init_pose_msg.orientation.x = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['orientation'][1] self.tab_list[ self.num_robots - 1].init_pose_msg.orientation.y = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['orientation'][2] self.tab_list[ self.num_robots - 1].init_pose_msg.orientation.z = self.FTS.region_of_interest[ self.FTS.region_of_interest.keys() [0]]['pose']['orientation'][3] self.current_graphicsScene.items_dict['r01'][ 'ellipse_item'].setBrush(QBrush(QColor('green'))) rect = self.current_graphicsScene.items_dict['r01'][ 'ellipse_item'].rect() point = rect.topLeft() self.tab_list[self.num_robots - 1].initial_pose[ 'start_' + str(self.num_robots).zfill(2)]['text_item'].setPos( point.x() - 11, point.y() - 22) # Connect initial pose comboBox with set_init_pose_id function self.tab_list[self.num_robots - 1].robot_comboBox_init.signalIndexChanged.connect( self.set_init_pose_id)
def draw_flipper_state(self): length = 100 self._widget.flipper_front_current.setText(str(self.flipper_state)) #self.flipper_state += self.flipper_diff; if(self.flipper_state > self.flipper_front_max_state): self.flipper_diff *= -1 # self.flipper_state = self.flipper_front_max_state if(self.flipper_state < self.flipper_front_min_state): self.flipper_diff *= -1 # self.flipper_state = self.flipper_front_min_state self.flipper_scene.clear() self.draw_flipper_max() self.draw_flipper_min() #red chassi self.flipper_scene.addRect(65, 60, 145, 25, QPen(), QBrush(QColor(255,0,0))) #right wheel self.flipper_scene.addEllipse(150, 50, 50, 50, QPen(), QBrush(QColor(0,0,0))) #left wheel self.flipper_scene.addEllipse(50, 50, 50, 50, QPen(), QBrush(QColor(0,0,0))) #flipper wheel transform = QTransform() transform.translate(155,70) transform.rotateRadians(-self.flipper_state) transform.translate(-25,-25) #flipper wheel connection flipper_wheel = QtGui.QGraphicsEllipseItem(120,5, 50, 50) flipper_wheel.setTransform(transform) flipper_wheel.setBrush( QBrush(QColor(0,0,0))) self.flipper_scene.addItem(flipper_wheel) #self.flipper_scene.addEllipse(250, 50, 50, 50, QPen(), QBrush(QColor(0,0,0))) transform = QTransform() transform.translate(160,75) transform.rotateRadians(-self.flipper_state) transform.translate(-10,-10) flipper_link = QtGui.QGraphicsRectItem(0,0, 135, 20) flipper_link.setBrush( QBrush(QColor(163,163,163))) flipper_link.setTransform(transform) self.flipper_scene.addItem(flipper_link) #front connection self.flipper_scene.addEllipse(155, 70, 10, 10, QPen(), QBrush(QColor(0,0,0))) transform = QTransform() transform.translate(160,75) transform.rotateRadians(-self.flipper_state) transform.translate(-10,-10) #flipper wheel connection flipper_wheel_connection = QtGui.QGraphicsEllipseItem(120,5, 10, 10) flipper_wheel_connection.setTransform(transform) flipper_wheel_connection.setBrush( QBrush(QColor(0,0,0))) self.flipper_scene.addItem(flipper_wheel_connection)
def redraw(self, event): """ Draw timeline's "cells" (ie. boxes that represent seconds). Taken from robot_monitor.message_timeline.on_paint @deprecated: This way (using QPainter) didn't work as intended. """ #super(TimelineView, self).paintEvent(event) # painter = QPainter(self) ## This yields warning that says: ## "QPainter::begin: Widget painting can only begin as a result of a paintEvent" painter = QPainter() painter.begin(self.viewport()) pen = QPen( Qt.black, 2) #, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) # Needs modified. painter.setPen(pen) is_enabled = self.isEnabled() #(width_tl, height_tl) = self.size() qsize = self.size() width_tl = qsize.width() height_tl = qsize.height() length_tl = self._max_num_seconds + 1 - self._min_num_seconds rospy.logdebug('paintEvent is_enabled=%s length_tl=%d', is_enabled, length_tl) value_size = width_tl / float(length_tl) for i in xrange(0, length_tl): brush = None color_index = i + self._min_num_seconds if (is_enabled): qcolor = self._color_callback(color_index) else: qcolor = QColor('grey') end_color = QColor(0.5 * QColor('red').value(), 0.5 * QColor('green').value(), 0.5 * QColor('blue').value()) #painter.setBrush(qcolor) painter.setBrush(QBrush(qcolor)) start = i * value_size end = (i + 1) * value_size rect = QRect(start, 0, end, height_tl) # dc.GradientFillLinear(wx.Rect(start, 0, end, height_tl), # qcolor, end_color, wx.SOUTH) rospy.logdebug('paintEvent i=%d start=%s end=%s height_tl=%s', i, start, end, height_tl) #painter.fillRect(QRect(start, end, 100, height_tl), qcolor) painter.fillRect(rect, qcolor) if (i > 0): # dc.SetPen(wx.BLACK_PEN) pen.setColor(Qt.black) # dc.DrawLine(start, 0, start, height_tl) painter.drawLine(start, 0, start, height_tl) size_marker = QSize(20, 20) marker_x = ( (self._xpos_marker - 1) * value_size + (value_size / 2.0) - (self._timeline_marker.actualSize(size_marker).width() / 2.0)) # dc.DrawBitmap(self._timeline_marker, marker_x, 0, True) qrect = QRect(marker_x, 0, size_marker.width(), size_marker.height()) self._timeline_marker.paint(painter, qrect) rospy.logdebug(' paintEvent marker_x=%s', marker_x) painter.end()
def scene_draw_circle(self, id, pos, radius, color): ellipse = QGraphicsEllipseItem(pos['x'] - radius, pos['y'] - radius, radius * 2, radius * 2) ellipse.setBrush(QBrush(getattr(QtCore.Qt, color.lower()))) self._scene.addItem(ellipse) self.items_cache['circle'][id] = ellipse