def paste(self): data = {} try: data = json.loads(QGuiApplication.clipboard().text()) except Exception as e: return self.clear_selection() # calculate offset positions = [] for d in data['drawings']: positions.append({'x': d['pos x'], 'y': d['pos y']}) for n in data['nodes']: positions.append({'x': n['position x'], 'y': n['position y']}) offset_for_middle_pos = QPointF(0, 0) if len(positions) > 0: rect = QRectF(positions[0]['x'], positions[0]['y'], 0, 0) for p in positions: x = p['x'] y = p['y'] if x < rect.left(): rect.setLeft(x) if x > rect.right(): rect.setRight(x) if y < rect.top(): rect.setTop(y) if y > rect.bottom(): rect.setBottom(y) offset_for_middle_pos = self.last_mouse_move_pos - rect.center() self.undo_stack.push(Paste_Command(self, data, offset_for_middle_pos))
def __init__(self, plan: Plan, parent=None): """Constructor. Args: plan: The Plan to associate this Editor with. parent: The QObject that the Editor belongs to; typically a PlanManager. """ super().__init__(parent) self.plan = plan self.lastTilePos = None self.view = EditorView(self) self.setBackgroundBrush(QBrush(Qt.lightGray)) self._currentFloor = 0 self._currentTool = None length = Plan.cellSize * GRID_SIZE # Create editing area borderRect = QRectF(0, 0, length, length) self.editArea = EditArea(borderRect, self) self.grid = EditorGrid(self.editArea) self.view.centerOn(borderRect.center()) self.view.panStarted.connect(self.editArea.unsetHoveredCell) self.view.panEnded.connect(self.editArea.setHoveredCell)
def ScalePicture(self): rect = QRectF(self.graphicsItem.pos(), QSizeF(self.pixMap.size())) unity = self.graphicsView.transform().mapRect(QRectF(0, 0, 1, 1)) width = unity.width() height = unity.height() if width <= 0 or height <= 0: return self.graphicsView.scale(1 / width, 1 / height) viewRect = self.graphicsView.viewport().rect() sceneRect = self.graphicsView.transform().mapRect(rect) if sceneRect.width() <= 0 or sceneRect.height() <= 0: return x_ratio = viewRect.width() / sceneRect.width() y_ratio = viewRect.height() / sceneRect.height() x_ratio = y_ratio = min(x_ratio, y_ratio) self.graphicsView.scale(x_ratio, y_ratio) # if self.readImg.isStripModel: # height2 = self.pixMap.size().height() / 2 # height3 = self.graphicsView.size().height()/2 # height3 = height3/x_ratio # p = self.graphicsItem.pos() # self.graphicsItem.setPos(p.x(), p.y()+height2-height3) self.graphicsView.centerOn(rect.center()) for _ in range(abs(self.scaleCnt)): if self.scaleCnt > 0: self.graphicsView.scale(1.1, 1.1) else: self.graphicsView.scale(1 / 1.1, 1 / 1.1)
def drawTokenTag(self, br: QRectF, painter: 'QPainter'): """ This is a helper function for the paint function. It renders "Token Tags" in the corners of the GUI Components displayed in the TGUIM View. Token Tags show how many Tokens are associated with the associated component. :param br: The bounding rectangle of the component. :type br: QRectF :param painter: A QPainter object. :type painter: QPainter :return: None :rtype: NoneType """ if br.width() >= ComponentGraphics.TITLEBAR_H: token_count = str(self.getNumberOfTokens()) ttX = br.x() + br.width() - ComponentGraphics.TITLEBAR_H ttY = br.y() ttWidth = ComponentGraphics.TITLEBAR_H ttHeight = ComponentGraphics.TITLEBAR_H rectBox = QRectF(ttX, ttY, ttWidth, ttHeight) tokenTagFont = QFont("Times", 10) painter.setFont(tokenTagFont) painter.setBrush(QColor(255, 0, 0, 127)) #painter.drawRect(rectBox) painter.drawEllipse(rectBox.center(), ttWidth / 2 - 1, ttHeight / 2 - 1) painter.setBrush(QColor(100, 200, 255)) fm = QFontMetricsF(tokenTagFont) pixelsWide = fm.width(token_count) pixelsHigh = fm.height() painter.drawText(ttX + ttWidth / 2 - pixelsWide / 2, ttY + ttHeight / 2 + pixelsHigh / 4, token_count)
def anchorPos(self, rect: QtCore.QRectF) -> QtCore.QPointF: if isinstance(self.anchor, QtCore.Qt.Corner): if self.anchor == QtCore.Qt.TopLeftCorner: pos = rect.topLeft() elif self.anchor == QtCore.Qt.TopRightCorner: pos = rect.topRight() elif self.anchor == QtCore.Qt.BottomLeftCorner: pos = rect.bottomLeft() else: # BottomRightCorner pos = rect.bottomRight() else: # AnchorPoint if self.anchor == QtCore.Qt.AnchorTop: pos = QtCore.QPointF(rect.center().x(), rect.top()) elif self.anchor == QtCore.Qt.AnchorLeft: pos = QtCore.QPointF(rect.left(), rect.center().y()) elif self.anchor == QtCore.Qt.AnchorRight: pos = QtCore.QPointF(rect.right(), rect.center().y()) elif self.anchor == QtCore.Qt.AnchorBottom: pos = QtCore.QPointF(rect.center().x(), rect.bottom()) else: raise ValueError( "Only Top, Left, Right, Bottom anchors supported.") return pos
def paint(cls, painter, option, index): rect = QRectF(option.rect) w, h = option.rect.width(), option.rect.height() painter.save() if index.row() % 2 == 0: painter.fillRect(rect, QColor("#FFFFFF")) else: painter.fillRect(rect, QColor("#EFF5F5")) if option.state & QStyle.State_MouseOver: painter.fillRect(rect, QColor("#8CCDDE")) if option.state & QStyle.State_Selected: painter.fillRect(rect, QColor("#5FA4DD")) painter.drawText(rect.adjusted(0, 0, 0, 0), Qt.AlignVCenter, index.data(Qt.DisplayRole)[0]) if index.data(Qt.DecorationRole) == "true": pbrush = QPen(QBrush(QColor("#F2A6A6"), Qt.SolidPattern), 1) painter.setPen(pbrush) circlerect = QRectF(w - h - 1, h * index.row() + 1, h - 2, h - 2) gradient = QRadialGradient(circlerect.center(), h, circlerect.center()) gradient.setColorAt(0.0, QColor("#F2A6A6")) gradient.setColorAt(0.5, QColor("#EE8181")) gradient.setColorAt(1.0, QColor("#E55252")) brush = QBrush(gradient) painter.setBrush(brush) painter.setRenderHint(QPainter.Antialiasing) painter.drawEllipse(circlerect) pbrush = QPen(QBrush(QColor("#313131")), 20) painter.setPen(pbrush) painter.drawText(circlerect, Qt.AlignCenter, str(index.data(Qt.DisplayRole)[1])) painter.restore()
class Apartment: def __init__(self, coppelia_, n_rooms): self.coppelia = coppelia_ self.num_rooms = n_rooms self.max_rooms_per_side = math.ceil(self.num_rooms / 2) self.initial_corridor_width = -1 self.initial_corridor_height = -1 self.initial_corridor = QRectF() self.fixed_height = random.uniform(4, 6) # Almacena los indices de las habitaciones que tendrán a su izquierda un pasillo self.dict_corridors_index_per_side = {'bottom': [], 'top': []} self.dict_rooms_per_side = {'bottom': [], 'top': []} self.dict_rooms_and_corridors_per_side = {'bottom': [], 'top': []} # Lista final una vez hechas todas las transformaciones self.total_rooms_and_corridors = [] self.create_initial_corridor() self.select_side_corridors() self.get_random_rooms() self.adjust_rooms() # to avoid narrow corridors self.add_doors() self.center_apartment() self.add_floor_per_room() self.add_walls() def create_initial_corridor(self): self.initial_corridor_height = random.uniform(1.5, 3) self.initial_corridor_width = random.uniform(self.num_rooms * 4 / 2, self.num_rooms * 8 / 2) self.initial_corridor = QRectF( 0, 0, self.initial_corridor_width, -self.initial_corridor_height ) # - height para que la parte de arriba sea el top self.initial_corridor.translate(-self.initial_corridor.center()) def select_side_corridors(self): # -1 sin pasillo, 0 antes de la primera habitacion, 1 antes de la segunda corridor_position = np.arange(-1, self.max_rooms_per_side) possibles_corridors_per_side = round(self.max_rooms_per_side / 2) if possibles_corridors_per_side == 0: possibles_corridors_per_side = 1 self.dict_corridors_index_per_side['top'] = random.sample( list(corridor_position), k=possibles_corridors_per_side) self.dict_corridors_index_per_side['bottom'] = random.sample( list(corridor_position), k=possibles_corridors_per_side) while -1 in self.dict_corridors_index_per_side['top']: self.dict_corridors_index_per_side['top'].remove(-1) while -1 in self.dict_corridors_index_per_side['bottom']: self.dict_corridors_index_per_side['bottom'].remove(-1) print('posicion pasillo parte superior', self.dict_corridors_index_per_side['top']) print('posicion pasillo parte inferior', self.dict_corridors_index_per_side['bottom']) def get_random_rooms(self): dict_opposite_side = {'bottom': 'top', 'top': 'bottom'} for i in range(0, self.num_rooms): random_side = random.choice(['top', 'bottom']) if len(self.dict_rooms_per_side[random_side] ) >= self.max_rooms_per_side: random_side = dict_opposite_side[random_side] # El indice de mi habitacion está en la lista de pasillos por indice luego tengo que añadir un pasillo a # su izquierda if len(self.dict_rooms_per_side[random_side] ) in self.dict_corridors_index_per_side[random_side]: self.add_corridor(random_side, self.initial_corridor_height, self.fixed_height) if len(self.dict_rooms_and_corridors_per_side[random_side]) == 0: if random_side == 'bottom': initial_point = self.initial_corridor.bottomLeft() else: initial_point = self.initial_corridor.topLeft() + QPointF( 0, self.fixed_height) else: initial_point = self.dict_rooms_and_corridors_per_side[ random_side][-1].room_qrect.topRight() room = Room(type='genericRoom', p=initial_point, w=random.uniform(4, 8), h=-self.fixed_height) self.dict_rooms_and_corridors_per_side[random_side].append(room) self.dict_rooms_per_side[random_side].append(room) for room_location in ['top', 'bottom']: if len(self.dict_rooms_per_side[room_location] ) in self.dict_corridors_index_per_side[room_location]: try: if self.dict_rooms_and_corridors_per_side[room_location][ -1].type != 'corridor': self.add_corridor(random_side, self.initial_corridor_height, self.fixed_height) except: print('there isnt rooms in this side of the corridor') def add_corridor(self, side, corridor_width, corridor_height): if len(self.dict_rooms_and_corridors_per_side[side]) == 0: if side == 'bottom': initial_point = self.initial_corridor.bottomLeft() else: initial_point = self.initial_corridor.topLeft() + QPointF( 0, self.fixed_height) else: initial_point = self.dict_rooms_and_corridors_per_side[side][ -1].room_qrect.topRight() corridor = Room(type='corridor', p=initial_point, w=corridor_width, h=-corridor_height) self.dict_rooms_and_corridors_per_side[side].append(corridor) def adjust_rooms(self): if self.num_rooms == 1: return dict_side_width = {'bottom': 0., 'right': 0., 'top': 0., 'left': 0.} for side, rooms in self.dict_rooms_per_side.items(): print(f' side {side} has {len(rooms)} rooms ') for room in rooms: r = room.room_qrect dict_side_width[side] += r.width() diff = abs(dict_side_width['top'] - dict_side_width['bottom']) dict_opposite_side = { 'bottom': 'top', 'right': 'left', 'top': 'bottom', 'left': 'right' } if dict_side_width['top'] > dict_side_width['bottom']: print('top side is longer') side_to_modify = 'bottom' else: print('bottom side is longer') side_to_modify = 'top' print(f'--- Modifying {side_to_modify} room ---') room_to_modify = self.dict_rooms_and_corridors_per_side[ side_to_modify][-1] opposite_room = self.dict_rooms_and_corridors_per_side[ dict_opposite_side[side_to_modify]][-1] my_side_right = room_to_modify.room_qrect.topRight() opposite_side_right = opposite_room.room_qrect.topRight() if room_to_modify.type == 'corridor': print(f' Room of type {room_to_modify.type} ') room_to_modify.room_qrect.setTopRight( QPointF(opposite_side_right.x(), my_side_right.y())) self.dict_rooms_and_corridors_per_side[side_to_modify][ -1] = room_to_modify self.dict_rooms_and_corridors_per_side[side_to_modify][ -1].update_room_dimensions() else: if diff < self.initial_corridor_height: print('widening room') num_corridors_to_add = 0 else: print('widening room and creating corridor') num_corridors_to_add = 1 print( f' Room of type {room_to_modify.type} -- adding {num_corridors_to_add} corridors' ) room_to_modify.room_qrect.setTopRight( QPointF( opposite_side_right.x() - num_corridors_to_add * self.initial_corridor_height, my_side_right.y())) self.dict_rooms_and_corridors_per_side[side_to_modify][ -1] = room_to_modify self.dict_rooms_and_corridors_per_side[side_to_modify][ -1].update_room_dimensions() if num_corridors_to_add > 0: self.add_corridor(side=side_to_modify, corridor_width=num_corridors_to_add * self.initial_corridor_height, corridor_height=self.fixed_height) def add_doors(self): opposite = {'bottom': 'top', 'top': 'bottom'} for current_side, rooms in self.dict_rooms_per_side.items(): for i, room in enumerate(rooms): possibles_door_locations = [opposite[current_side]] if i in self.dict_corridors_index_per_side[ current_side]: # Pasillo a la izquierda possibles_door_locations.append('left') if i + 1 in self.dict_corridors_index_per_side[current_side]: possibles_door_locations.append('right') door_location = random.choice(possibles_door_locations) room.add_door(door_location) def center_apartment(self): union_polygon = QPolygonF() for list in self.dict_rooms_and_corridors_per_side.values(): for room in list: union_polygon = union_polygon.united( room.room_qpolygon) # Para obtener el bounding box self.total_rooms_and_corridors.append(room) self.initial_corridor.setLeft(union_polygon.boundingRect().left()) self.initial_corridor.setRight(union_polygon.boundingRect().right()) self.total_rooms_and_corridors.append( Room(type='corridor', p=self.initial_corridor.topLeft(), w=self.initial_corridor.width(), h=self.initial_corridor.height())) union_polygon = union_polygon.united(self.initial_corridor) initial_center = union_polygon.boundingRect().center() union_polygon.translate(-initial_center) self.apartment_boundingRect = union_polygon.boundingRect() # Desplazo habitaciones y pasillos al centro for i, room in enumerate(self.total_rooms_and_corridors): room.room_qpolygon.translate( -initial_center ) # Desplazo los poligonos para que la habitación esté centrada room.room_qrect.translate(-initial_center) def add_walls(self): for i, room in enumerate(self.total_rooms_and_corridors): walls = [] if room.type == 'corridor': continue polygon = room.room_qpolygon prev_point = polygon[0] for i, curr_point in enumerate(polygon): if i == 0: continue walls.append(([prev_point.x(), prev_point.y(), .425], [curr_point.x(), curr_point.y(), .425])) prev_point = curr_point room.walls = walls wall_thread = WallCreator(data, walls) wall_thread.start() walls = [] polygon_br = QPolygonF(self.apartment_boundingRect, closed=True) prev_point_br = polygon_br[0] for i, curr_point_br in enumerate(polygon_br): if i == 0: continue walls.append(([prev_point_br.x(), prev_point_br.y(), .4], [curr_point_br.x(), curr_point_br.y(), .4])) prev_point_br = curr_point_br wall_thread = WallCreator(data, walls) wall_thread.start() def add_floor(self): # un suelo conjunto para el apartamento fscale_x = self.apartment_boundingRect.width() / 5 + 0.5 fscale_y = self.apartment_boundingRect.height() / 5 + 0.5 # Create and scale a floor r = self.coppelia.create_model( 'models/infrastructure/floors/5mX5m wooden floor.ttm', 0, 0, 0, 0) self.coppelia.scale_object(r, fscale_x, fscale_y, 1) for handle in self.coppelia.get_objects_children(r): self.coppelia.scale_object(handle, fscale_x, fscale_y, 1) def add_floor_per_room(self): for room in self.total_rooms_and_corridors: room_boundingRect = room.room_qpolygon.boundingRect() room_center = room_boundingRect.center() fscale_x = room_boundingRect.width() / 5 fscale_y = room_boundingRect.height() / 5 if room.type == 'corridor': floor = self.coppelia.create_model( 'models/infrastructure/floors/5mX5m wooden floor.ttm', room_center.x(), room_center.y(), 0, 0) else: floor = self.coppelia.create_model( 'models/infrastructure/floors/5mX5m concrete floor.ttm', room_center.x(), room_center.y(), 0, 0) self.coppelia.scale_object(floor, fscale_x, fscale_y, 1)
class Callout(QGraphicsItem): """ This class code was taken from \ https://code.qt.io/cgit/qt/qtcharts.git/tree/examples/charts/callout/callout.cpp?h=5.13 """ def __init__(self, chart): QGraphicsItem.__init__(self, chart) self.chart = chart self.rect = QRectF() self.anchor = QPointF() self.text_rect = QRectF() self.text = "" self.font = QFont() def boundingRect(self): anchor = self.mapFromParent(self.chart.mapToPosition(self.anchor)) rect = QRectF() rect.setLeft(min(self.rect.left(), anchor.x())) rect.setRight(max(self.rect.right(), anchor.x())) rect.setTop(min(self.rect.top(), anchor.y())) rect.setBottom(max(self.rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget): path = QPainterPath() path.addRoundedRect(self.rect, 5, 5) anchor = self.mapFromParent(self.chart.mapToPosition(self.anchor)) if not self.rect.contains(anchor): point1 = QPointF() point2 = QPointF() # establish the position of the anchor point in relation to m_rect above = anchor.y() <= self.rect.top() aboveCenter = anchor.y() > self.rect.top() and anchor.y( ) <= self.rect.center().y() belowCenter = anchor.y() > self.rect.center().y() and anchor.y( ) <= self.rect.bottom() below = anchor.y() > self.rect.bottom() onLeft = anchor.x() <= self.rect.left() leftOfCenter = anchor.x() > self.rect.left() and anchor.x( ) <= self.rect.center().x() rightOfCenter = anchor.x() > self.rect.center().x() and anchor.x( ) <= self.rect.right() onRight = anchor.x() > self.rect.right() # get the nearest m_rect corner x = (onRight + rightOfCenter) * self.rect.width() y = (below + belowCenter) * self.rect.height() cornerCase = (above and onLeft) or (above and onRight) or ( below and onLeft) or (below and onRight) vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y) x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * ( not vertical) * (onLeft * 10 - onRight * 20) y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * ( above * 10 - below * 20) x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * ( not vertical) * (onLeft * 20 - onRight * 10) y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * ( above * 20 - below * 10) point1.setX(x1) point1.setY(y1) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self.text_rect, self.text) def set_anchor(self, point): self.anchor = point def updateGeometry(self): self.prepareGeometryChange() self.setPos(self.chart.mapToPosition(self.anchor) + QPoint(10, -50)) def set_text(self, text): self.text = text metrics = QFontMetrics(self.font) self.text_rect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft, self.text) self.text_rect.translate(5, 5) self.prepareGeometryChange() self.rect = QRectF(self.text_rect.adjusted(-5.0, -5.0, 5.0, 5.0))
if random.choice(['vertical', 'horizontal']) == 'horizontal': orientation = 'horizontal' initial_corridor = QRectF(0, 0, corridor_width, corridor_height) initial_corridor_interior = QRectF( 0, 0, corridor_width - 0.1, corridor_height - 0.1) # auxiliar para que las habitaciones se unan al pasillo else: orientation = 'vertical' initial_corridor = QRectF(0, 0, corridor_height, corridor_width) initial_corridor_interior = QRectF(0, 0, corridor_height - 0.1, corridor_width - 0.1) print(f'Corridor orientation is {orientation}') initial_corridor.translate( -initial_corridor.center()) # Traslado el pasillo al centro initial_corridor_interior.translate(-initial_corridor_interior.center() ) # Traslado el pasillo auxiliar al centro print( 'Initial corridor --- ', f'Center = {initial_corridor.center()}\n', f'Top Left = {initial_corridor.topLeft()}\n', f'Top Right = {initial_corridor.topRight()}\n' f'Bottom Left = {initial_corridor.bottomLeft()}\n', f'Bottom Right = {initial_corridor.bottomRight()}\n') initial_polygon = QPolygonF(initial_corridor) corridor_points = {'bottom': [], 'right': [], 'top': [], 'left': []} corridor_sides = { # bottom y top deben estar cambiados
class Callout(QGraphicsItem): def __init__(self, chart): QGraphicsItem.__init__(self, chart) self._chart = chart self._text = "" self._textRect = QRectF() self._anchor = QPointF() self._font = QFont() self._rect = QRectF() def boundingRect(self): anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) rect = QRectF() rect.setLeft(min(self._rect.left(), anchor.x())) rect.setRight(max(self._rect.right(), anchor.x())) rect.setTop(min(self._rect.top(), anchor.y())) rect.setBottom(max(self._rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget): path = QPainterPath() path.addRoundedRect(self._rect, 5, 5) anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) if not self._rect.contains(anchor) and not self._anchor.isNull(): point1 = QPointF() point2 = QPointF() # establish the position of the anchor point in relation to _rect above = anchor.y() <= self._rect.top() aboveCenter = (anchor.y() > self._rect.top() and anchor.y() <= self._rect.center().y()) belowCenter = (anchor.y() > self._rect.center().y() and anchor.y() <= self._rect.bottom()) below = anchor.y() > self._rect.bottom() onLeft = anchor.x() <= self._rect.left() leftOfCenter = (anchor.x() > self._rect.left() and anchor.x() <= self._rect.center().x()) rightOfCenter = (anchor.x() > self._rect.center().x() and anchor.x() <= self._rect.right()) onRight = anchor.x() > self._rect.right() # get the nearest _rect corner. x = (onRight + rightOfCenter) * self._rect.width() y = (below + belowCenter) * self._rect.height() cornerCase = ((above and onLeft) or (above and onRight) or (below and onLeft) or (below and onRight)) vertical = abs(anchor.x() - x) > abs(anchor.y() - y) x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * int(not vertical) * (onLeft * 10 - onRight * 20)) y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20)) point1.setX(x1) point1.setY(y1) x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * int(not vertical) * (onLeft * 20 - onRight * 10)) y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10)) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self._textRect, self._text) def mousePressEvent(self, event): event.setAccepted(True) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.setPos( mapToParent(event.pos() - event.buttonDownPos(Qt.LeftButton))) event.setAccepted(True) else: event.setAccepted(False) def setText(self, text): self._text = text metrics = QFontMetrics(self._font) self._textRect = QRectF( metrics.boundingRect(QRect(0.0, 0.0, 150.0, 150.0), Qt.AlignLeft, self._text)) self._textRect.translate(5, 5) self.prepareGeometryChange() self._rect = self._textRect.adjusted(-5, -5, 5, 5) def setAnchor(self, point): self._anchor = QPointF(point) def updateGeometry(self): self.prepareGeometryChange() self.setPos(self._chart.mapToPosition(self._anchor) + QPointF(10, -50))
class Callout(QGraphicsItem): def __init__(self, chart): QGraphicsItem.__init__(self, chart) self._chart = chart self._text = "" self._textRect = QRectF() self._anchor = QPointF() self._font = QFont() self._rect = QRectF() def boundingRect(self): anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) rect = QRectF() rect.setLeft(min(self._rect.left(), anchor.x())) rect.setRight(max(self._rect.right(), anchor.x())) rect.setTop(min(self._rect.top(), anchor.y())) rect.setBottom(max(self._rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget): path = QPainterPath() path.addRoundedRect(self._rect, 5, 5) anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor)) if not self._rect.contains(anchor) and not self._anchor.isNull(): point1 = QPointF() point2 = QPointF() # establish the position of the anchor point in relation to _rect above = anchor.y() <= self._rect.top() aboveCenter = (anchor.y() > self._rect.top() and anchor.y() <= self._rect.center().y()) belowCenter = (anchor.y() > self._rect.center().y() and anchor.y() <= self._rect.bottom()) below = anchor.y() > self._rect.bottom() onLeft = anchor.x() <= self._rect.left() leftOfCenter = (anchor.x() > self._rect.left() and anchor.x() <= self._rect.center().x()) rightOfCenter = (anchor.x() > self._rect.center().x() and anchor.x() <= self._rect.right()) onRight = anchor.x() > self._rect.right() # get the nearest _rect corner. x = (onRight + rightOfCenter) * self._rect.width() y = (below + belowCenter) * self._rect.height() cornerCase = ((above and onLeft) or (above and onRight) or (below and onLeft) or (below and onRight)) vertical = abs(anchor.x() - x) > abs(anchor.y() - y) x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * int(not vertical) * (onLeft * 10 - onRight * 20)) y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20)) point1.setX(x1) point1.setY(y1) x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * int(not vertical) * (onLeft * 20 - onRight * 10)) y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10)) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self._textRect, self._text) def mousePressEvent(self, event): event.setAccepted(True) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.setPos(mapToParent( event.pos() - event.buttonDownPos(Qt.LeftButton))) event.setAccepted(True) else: event.setAccepted(False) def setText(self, text): self._text = text metrics = QFontMetrics(self._font) self._textRect = QRectF(metrics.boundingRect( QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text)) self._textRect.translate(5, 5) self.prepareGeometryChange() self._rect = self._textRect.adjusted(-5, -5, 5, 5) def setAnchor(self, point): self._anchor = QPointF(point) def updateGeometry(self): self.prepareGeometryChange() self.setPos(self._chart.mapToPosition( self._anchor) + QPointF(10, -50))
# quiero que todas las habitaciones a un mismo lado tengan el mismo ancho o alto (si el pasillo es horizontal sera el alto) fixed_w_h_room = random.uniform(4, 6) print(f'el tamaño fijado es de {fixed_w_h_room}') # Crear pasillo initial corridor_width = random.uniform(num_rooms * 4 / 2, num_rooms * 8 / 2) corridor_height = random.uniform(1.5, 3) print( F'Creating corridor with width = {corridor_width} and height = {corridor_height}' ) initial_corridor = QRectF(0, 0, corridor_width, corridor_height) initial_corridor.translate( -initial_corridor.center()) # Traslado el pasillo al centro print( 'Initial corridor --- ', f'Center = {initial_corridor.center()}\n', f'Top Left = {initial_corridor.topLeft()}\n', f'Top Right = {initial_corridor.topRight()}\n' f'Bottom Left = {initial_corridor.bottomLeft()}\n', f'Bottom Right = {initial_corridor.bottomRight()}\n') corridor_sides = { # bottom y top deben estar cambiados 'bottom': [initial_corridor.topLeft(), initial_corridor.topRight()], 'right': [initial_corridor.topRight(), initial_corridor.bottomRight()], 'top': [initial_corridor.bottomLeft(), initial_corridor.bottomRight()],
def drawMagnifier(self): # First, calculate the magnifier position due to the mouse position watch_area_width = 16 watch_area_height = 16 cursor_pos = self.mousePoint watch_area = QRect( QPoint(cursor_pos.x() - watch_area_width / 2, cursor_pos.y() - watch_area_height / 2), QPoint(cursor_pos.x() + watch_area_width / 2, cursor_pos.y() + watch_area_height / 2)) if watch_area.left() < 0: watch_area.moveLeft(0) watch_area.moveRight(watch_area_width) if self.mousePoint.x( ) + watch_area_width / 2 >= self.screenPixel.width(): watch_area.moveRight(self.screenPixel.width() - 1) watch_area.moveLeft(watch_area.right() - watch_area_width) if self.mousePoint.y() - watch_area_height / 2 < 0: watch_area.moveTop(0) watch_area.moveBottom(watch_area_height) if self.mousePoint.y( ) + watch_area_height / 2 >= self.screenPixel.height(): watch_area.moveBottom(self.screenPixel.height() - 1) watch_area.moveTop(watch_area.bottom() - watch_area_height) # tricks to solve the hidpi impact on QCursor.pos() watch_area.setTopLeft( QPoint(watch_area.topLeft().x() * self.scale, watch_area.topLeft().y() * self.scale)) watch_area.setBottomRight( QPoint(watch_area.bottomRight().x() * self.scale, watch_area.bottomRight().y() * self.scale)) watch_area_pixmap = self.screenPixel.copy(watch_area) # second, calculate the magnifier area magnifier_area_width = watch_area_width * 10 magnifier_area_height = watch_area_height * 10 font_area_height = 40 cursor_size = 24 magnifier_area = QRectF( QPoint(QCursor.pos().x() + cursor_size, QCursor.pos().y() + cursor_size), QPoint(QCursor.pos().x() + cursor_size + magnifier_area_width, QCursor.pos().y() + cursor_size + magnifier_area_height)) if magnifier_area.right() >= self.screenPixel.width(): magnifier_area.moveLeft(QCursor.pos().x() - magnifier_area_width - cursor_size / 2) if magnifier_area.bottom( ) + font_area_height >= self.screenPixel.height(): magnifier_area.moveTop(QCursor.pos().y() - magnifier_area_height - cursor_size / 2 - font_area_height) # third, draw the watch area to magnifier area watch_area_scaled = watch_area_pixmap.scaled( QSize(magnifier_area_width * self.scale, magnifier_area_height * self.scale)) magnifier_pixmap = self.graphics_scene.addPixmap(watch_area_scaled) magnifier_pixmap.setOffset(magnifier_area.topLeft()) # then draw lines and text self.graphics_scene.addRect(QRectF(magnifier_area), QPen(QColor(255, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.center().x(), magnifier_area.top()), QPointF(magnifier_area.center().x(), magnifier_area.bottom())), QPen(QColor(0, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.left(), magnifier_area.center().y()), QPointF(magnifier_area.right(), magnifier_area.center().y())), QPen(QColor(0, 255, 255), 2)) # get the rgb of mouse point point_rgb = QColor(self.screenPixel.toImage().pixel(self.mousePoint)) # draw information self.graphics_scene.addRect( QRectF( magnifier_area.bottomLeft(), magnifier_area.bottomRight() + QPoint(0, font_area_height + 30)), QPen(Qt.black), QBrush(Qt.black)) rgb_info = self.graphics_scene.addSimpleText( ' Rgb: ({0}, {1}, {2})'.format(point_rgb.red(), point_rgb.green(), point_rgb.blue())) rgb_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 5)) rgb_info.setPen(QPen(QColor(255, 255, 255), 2)) rect = self.selected_area.normalized() size_info = self.graphics_scene.addSimpleText( ' Size: {0} x {1}'.format(rect.width() * self.scale, rect.height() * self.scale)) size_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 15) + QPoint(0, font_area_height / 2)) size_info.setPen(QPen(QColor(255, 255, 255), 2))