def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent): box = QRectF(self.buttonDownRect) pos = event.pos() offset = pos - event.buttonDownPos(Qt.LeftButton) if self.handleSelected is None: box.translate(offset) new_box = box elif self.handleSelected == 0: pos = box.topLeft() + offset new_size = box.bottomRight() - pos width = max(new_size.x(), 0) height = max(new_size.y(), 0) left = min(pos.x(), box.right()) top = min(pos.y(), box.bottom()) new_box = QRectF(left, top, width, height) elif self.handleSelected == 1: pos = box.topLeft() + offset height = max(box.bottom() - pos.y(), 0) top = min(pos.y(), box.bottom()) new_box = QRectF(box.left(), top, box.width(), height) elif self.handleSelected == 2: pos = box.topRight() + offset top = min(pos.y(), box.bottom()) width = max(pos.x() - box.left(), 0) height = max(box.bottom() - pos.y(), 0) new_box = QRectF(box.left(), top, width, height) elif self.handleSelected == 3: pos = box.topRight() + offset width = max(pos.x() - box.left(), 0) new_box = QRectF(box.left(), box.top(), width, box.height()) elif self.handleSelected == 4: pos = box.bottomRight() + offset new_size = pos - box.topLeft() width = max(new_size.x(), 0) height = max(new_size.y(), 0) new_box = QRectF(box.left(), box.top(), width, height) elif self.handleSelected == 5: pos = box.bottomRight() + offset height = max(pos.y() - box.top(), 0) new_box = QRectF(box.left(), box.top(), box.width(), height) elif self.handleSelected == 6: pos = box.bottomLeft() + offset left = min(pos.x(), box.right()) width = max(box.right() - pos.x(), 0) height = max(pos.y() - box.top(), 0) new_box = QRectF(left, box.top(), width, height) elif self.handleSelected == 7: pos = box.bottomLeft() + offset left = min(pos.x(), box.right()) width = max(box.right() - pos.x(), 0) new_box = QRectF(left, box.top(), width, box.height()) new_box = QRectF(round(new_box.left()), round(new_box.top()), round(new_box.width()), round(new_box.height())) self.setRect(new_box) self.setHandlesPos() self.signalHandler.boxChanged.emit(self.tabIndex, self.rowIndex, new_box)
def draw_NI_extended_background(painter, c, w, h, bounding_rect: QRectF, title_rect): """ :param painter: painter from paint event :param c: NodeInstance's theme color :param w: width :param h: height :param bounding_rect: NodeInstance's bounding rect :param title_rect: NI's title label's bounding rect """ background_color = QColor('#212429') header_color = c header_height = NIPainter.get_header_rect(w, h, title_rect).height() rel_header_height = header_height / h gradient = QLinearGradient(bounding_rect.topLeft(), bounding_rect.bottomLeft()) gradient.setColorAt(0, header_color) gradient.setColorAt(rel_header_height, header_color) gradient.setColorAt(rel_header_height + 0.0001, background_color) gradient.setColorAt(1, background_color) painter.setBrush(QBrush(background_color)) painter.setPen(Qt.NoPen) # QPen(c.darker())) painter.drawRoundedRect( QRectF( QPointF(bounding_rect.left(), bounding_rect.top() + header_height), bounding_rect.bottomRight()), 6, 6)
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(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: QWidget = None): # setup border pen pen = painter.pen() pen.setWidthF(self.monitor_border_width) pen.setCapStyle(Qt.FlatCap) painter.setPen(pen) # create monitor_rect rect_monitor = QRectF(0, 0, self.monitor.screen_width, self.monitor.screen_height) # Draw gradient in the background gradient = QLinearGradient(rect_monitor.topRight(), rect_monitor.bottomLeft()) gradient.setColorAt(0.0, self.monitor_color_gradient_top) gradient.setColorAt(1.0, self.monitor_color_gradient_bottom) painter.fillRect(rect_monitor, gradient) # draw monitor label self.draw_monitor_label(painter, rect_monitor, self.index) # draw borders inside monitor_rect border_offset = painter.pen().widthF() / 2 border_rect = rect_monitor.adjusted(border_offset, border_offset, -border_offset, border_offset) painter.drawRect(border_rect)
def getObjectInteraction(self, persons, objects, interaction, d): # print("getObjectInteration") plt.close('all') polylines_object = [] polylines_interacting = [] for o in objects: obj = Object(o.x / 1000., o.z / 1000., o.angle, o.space) # print("OBJETO") ##para dibujarlo if d: plt.figure('ObjectSpace') rect = plt.Rectangle((obj.x - 0.25, obj.y - 0.25), 0.5, 0.5, fill=False) plt.gca().add_patch(rect) x_aux = obj.x + 0.25 * cos(pi / 2 - obj.th) y_aux = obj.y + 0.25 * sin(pi / 2 - obj.th) heading = plt.Line2D((obj.x, x_aux), (obj.y, y_aux), lw=1, color='k') plt.gca().add_line(heading) w = 1.0 # print (obj.x,obj.y) ##para calcular el rectangulo s = QRectF(QPointF(0, 0), QSizeF(w, obj.sp)) # if (d): # plt.plot (s.bottomLeft().x(),s.bottomLeft().y(),"go") # plt.plot(s.bottomRight().x(), s.bottomRight().y(), "ro") # plt.plot(s.topRight().x(), s.topRight().y(), "yo") # plt.plot(s.topLeft().x(), s.topLeft().y(), "bo") space = QPolygonF() space.append(s.topLeft()) space.append(s.topRight()) space.append( QPointF(s.bottomRight().x() + obj.sp / 4, s.bottomRight().y())) space.append( QPointF(s.bottomLeft().x() - obj.sp / 4, s.bottomLeft().y())) t = QTransform() t.translate(-w / 2, 0) space = t.map(space) t = QTransform() t.rotateRadians(-obj.th) space = t.map(space) t = QTransform() t.translate(obj.x, obj.y) space = t.map(space) # points = [] # for x in xrange(space.count()-1): # point = space.value(x) # print ("valor", point) # points.append([point.x(),point.y()]) # plt.plot(point.x(),point.y(),"go") polyline = [] for x in range(space.count()): point = space.value(x) if (d): plt.plot(point.x(), point.y(), "go") p = SNGPoint2D() p.x = point.x() p.z = point.y() polyline.append([p.x, p.z]) polylines_object.append(polyline) for p in persons: pn = Person(p.x, p.z, p.angle) # print("PERSONA", persons.index(p)+1) if d: body = plt.Circle((pn.x, pn.y), radius=0.3, fill=False) plt.gca().add_patch(body) x_aux = pn.x + 0.30 * cos(pi / 2 - pn.th) y_aux = pn.y + 0.30 * sin(pi / 2 - pn.th) heading = plt.Line2D((pn.x, x_aux), (pn.y, y_aux), lw=1, color='k') plt.gca().add_line(heading) plt.axis('equal') ##CHECKING THE ORIENTATION print("obj.angle", obj.th, "person.angle", pn.th) a = abs(obj.th - abs(pn.th - math.pi)) if a < math.radians(45): checkangle = True else: checkangle = False ##CHECKING IF THE PERSON IS INSIDE THE POLYGON if space.containsPoint(QPointF(pn.x, pn.y), Qt.OddEvenFill): # and checkangle: print("DENTROOOOO Y MIRANDO") if not polyline in polylines_interacting: polylines_interacting.append(polyline) if d: for ps in polylines_interacting: # plt.figure() for p in ps: plt.plot(p.x, p.z, "ro") plt.axis('equal') plt.xlabel('X') plt.ylabel('Y') plt.show() plt.show() if (interaction): return polylines_interacting else: return polylines_object
class Room: def __init__(self, type='genericRoom', p=QPointF(), w=-1, h=-1): self.type = type # corridor, bedroom, kitchen, bathroom, etc self.width = w self.height = h self.initial_point = p self.room_qrect = QRectF() self.room_qpolygon = QPolygonF() self.area = -1 self.door_position = None self.create_room() def create_room(self): print( f'Creating room of type {self.type} with width = {self.width} and height = {self.height}' ) self.room_qrect = QRectF(self.initial_point.x(), self.initial_point.y(), self.width, self.height) self.room_qpolygon = QPolygonF(self.room_qrect) self.area = abs(self.width * self.height) def update_room_dimensions(self): self.width = self.room_qrect.width() self.height = self.room_qrect.height() self.area = abs(self.width * self.height) self.room_qpolygon = QPolygonF(self.room_qrect) def add_door(self, door_location): self.door_position = door_location # Diferenciar entre parte de arriba y parte de abajo dict_location_line = { 'top': QLineF(self.room_qrect.topLeft(), self.room_qrect.topRight()), 'bottom': QLineF(self.room_qrect.bottomLeft(), self.room_qrect.bottomRight()), 'left': QLineF(self.room_qrect.topLeft(), self.room_qrect.bottomLeft()), 'right': QLineF(self.room_qrect.topRight(), self.room_qrect.bottomRight()) } line = dict_location_line[door_location] line_lenght = int(line.length()) step = line_lenght / 100. line_points = [] for t in np.arange(0.25, 0.75, step): line_point = line.pointAt(t) line_points.append(QPointF(line_point.x(), line_point.y())) door = random.choice(line_points) room_polygon = { 'top': QPolygonF([ QPointF(door.x() + 0.5, door.y()), self.room_qrect.topRight(), self.room_qrect.bottomRight(), self.room_qrect.bottomLeft(), self.room_qrect.topLeft(), QPointF(door.x() - 0.5, door.y()) ]), 'bottom': QPolygonF([ QPointF(door.x() + 0.5, door.y()), self.room_qrect.bottomRight(), self.room_qrect.topRight(), self.room_qrect.topLeft(), self.room_qrect.bottomLeft(), QPointF(door.x() - 0.5, door.y()) ]), 'right': QPolygonF([ QPointF(door.x(), door.y() + 0.5), self.room_qrect.topRight(), self.room_qrect.topLeft(), self.room_qrect.bottomLeft(), self.room_qrect.bottomRight(), QPointF(door.x(), door.y() - 0.5) ]), 'left': QPolygonF([ QPointF(door.x(), door.y() + 0.5), self.room_qrect.topLeft(), self.room_qrect.topRight(), self.room_qrect.bottomRight(), self.room_qrect.bottomLeft(), QPointF(door.x(), door.y() - 0.5) ]) } self.room_qpolygon = room_polygon[door_location]
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 QSlideNavigationBar(QWidget): class ItemLineStyle(Enum): ItemNone = 1 ItemTop = 2 ItemRight = 3 ItemBottom = 4 ItemLeft = 5 ItemRect = 6 itemClicked = Signal(int, str) def __init__(self): super(QSlideNavigationBar, self).__init__() # -------成员变量定义------------# # ==========属性=========# self._m_bar_start_color = QColor('#511235') # type: QColor # 导航栏起始颜色 self._m_bar_end_color = QColor('#150507') # type: QColor # 导航栏结束颜色 self._m_bar_radius = 0 # type: int # 导航栏四个角的圆弧半径 self._m_item_start_color = QColor(255, 255, 255, 50) # type: QColor # item 的起始颜色 self._m_item_end_color = QColor("black") # type: QColor # item 的结束颜色 self._m_current_hover_index = -1 # type: int # 当前光标所在的item的index self._m_item_hover_start_color = QColor(255, 0, 0, 25) # type: QColor # 光标所在的item 的起始颜色 self._m_item_hover_end_color = QColor(255, 0, 255, 25) # type: QColor self._m_item_text_color = QColor("red") # type: QColor # item 的文字颜色 self._m_item_line_color = QColor("red") # type: QColor # item 的线的颜色 self._m_item_line_width = 5 # type: int # 线的宽度 self._m_item_line_style = self.ItemLineStyle.ItemNone # type: QSlideNavigationBar.ItemLineStyle # 线的样式类型 self._m_item_font = QFont('宋体') # type: QFont # 字体家族 self._m_item_font_size = 16 # type: int # 字体大小 self._m_item_radius = 0 # type: int # item 的圆角半径 self._m_space = 40 # type: int # 间距大小, item 背景大小 self._m_orientation = Qt.Horizontal # type: Qt.Orientation # 导航栏的方向:横向,纵向 self._m_enable_key_move = True # type: bool # 是否可以使用按键切换item self._m_fixed = False # type: bool # 大小固定 self._m_slide_velocity = 10 # type: int # 滑动速度 self._m_shake_velocity = 10 # type: int # 晃动速度 # ===========内部变量=========# self._m_item_maps = {} # type: map(int, list(str, QRectF)) # 保存的item列表 self._m_total_text_width = 0 # type: int # 总的文字的宽度 self._m_total_text_height = 0 # type: int # 总的文字的高度 self._m_current_index = 0 # type: int # 当前选中的item 的索引 self._m_start_rect = QRectF() # type:QRectF #起始矩形 self._m_stop_rect = QRectF() # type: QRectF # 结束矩形 self._m_slide_timer = QTimer(self) # type: QTimer # 滑动的定时器 self._m_shake_timer = QTimer(self) # type: QTimer # 晃动的定时器 self._m_forward = False # type: bool # 前进 # ----------执行初始化动作-------------# self.setAttribute(Qt.WA_TranslucentBackground) self._m_slide_timer.setInterval(self._m_slide_velocity) self._m_slide_timer.timeout.connect(self._on_do_slide) self._m_shake_timer.setInterval(self._m_shake_velocity) self._m_shake_timer.timeout.connect(self._on_do_shake) self.setFocusPolicy(Qt.ClickFocus) self.setMouseTracking(True) # ---------以下是 API 接口----------# def add_item(self, item_str: str): """ 向导航栏中添加项目(代表一个选项卡),添加之前会查重 :param item_str:项目名称(显示出来的文字) :return:None """ if not item_str: return for key, value in self._m_item_maps.items(): if value[0] == item_str: return # 如果存在同名item,则返回 f = QFont() f.setPointSize(self._m_item_font_size) fm = QFontMetrics(f) text_width = fm.width(item_str) text_height = fm.height() item_count = len(self._m_item_maps) if item_count > 0: if self._m_orientation == Qt.Horizontal: top_left = QPointF(self._m_total_text_width, 0) self._m_total_text_width += text_width + self._m_space bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height) else: top_left = QPointF(0, self._m_total_text_height) self._m_total_text_height += text_height + self._m_space bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height) self._m_item_maps[item_count] = [item_str, QRectF(top_left, bottom_right)] else: if self._m_orientation == Qt.Horizontal: # 水平方向,水平各占1个space, 竖直占1个space self._m_total_text_width = text_width + self._m_space self._m_total_text_height = text_height + self._m_space else: # 竖直方向, 水平各占2个space, 竖直占一个space self._m_total_text_width = text_width + 2 * self._m_space self._m_total_text_height = text_height + self._m_space top_left = QPointF(0.0, 0.0) bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height) self._m_item_maps[item_count] = [item_str, QRectF(top_left, bottom_right)] self.setMinimumSize(self._m_total_text_width, self._m_total_text_height) if self._m_fixed: if self._m_orientation == Qt.Horizontal: self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) # 固定高度 else: self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) # 固定宽度 if len(self._m_item_maps): self._m_start_rect = QRectF(self._m_item_maps[0][1]) self.update() def set_items(self, items_list: list): """ 一次性设置一组项目, 会清空之前设置的项目 :param items_list: 项目名称列表 :return: None """ pass def get_items(self): pass def set_bar_start_color(self, color: QColor): """ 设置导航栏背景的起始颜色(渐变色的起始) :param color:QColor类型 :return: None """ if color != self._m_bar_start_color: self._m_bar_start_color = color self.update() def set_bar_end_color(self, color: QColor): """ 设置导航栏背景的结束颜色(渐变色的结束) :param color: QColor 类型 :return: None """ if color != self._m_bar_end_color: self._m_bar_end_color = color self.update() def set_item_start_color(self, color: QColor): """ 设置项目的背景色的起始颜色(渐变色的起始) :param color: QColor 类型 :return: None """ if color != self._m_item_start_color: self._m_item_start_color = color self.update() def set_item_end_color(self, color: QColor): """ 设置项目的背景色的结束颜色(渐变色的结束) :param color: QColor 类型 :return: None """ if color != self._m_item_end_color: self._m_item_end_color = color self.update() def set_item_text_color(self, color: QColor) -> None: """ 设置 item 的文字颜色 :param color: QColor 类型 :return: None """ if color != self._m_item_text_color: self._m_item_text_color = color self.update() def set_item_line_color(self, color: QColor) -> None: """ 设置 item 的线的颜色 :param color: QColor 类型 :return: None """ if color != self._m_item_line_color: self._m_item_line_color = color self.update() def set_bar_radius(self, radius: int): """ 设置导航栏四个角的圆弧半径 :param radius: int 类型 :return: None """ if radius >= 0 and radius != self._m_bar_radius: self._m_bar_radius = radius self.update() def set_item_radius(self, radius: int): """ 设置项目的四个角的圆弧半径 :param radius: int 类型 :return: None """ if radius >= 0 and radius != self._m_item_radius: self._m_item_radius = radius self.update() def set_space(self, space: int): """ 设置 item 所占的空间大小 :param space: int 类型 :return: None """ if space >= 0 and space != self._m_space: self._m_space = space self.update() def set_item_line_width(self, width: int): """ 设置项目周围的线宽度 :param width: int 类型 :return: None """ if width >= 0 and width != self._m_item_line_width: self._m_item_line_width = width self.update() def set_item_line_style(self, style: ItemLineStyle): """ 设置项目周围的线的类型:不显示,上方,下方,左方, 右方, 矩形 :param style: 枚举类型 :return: None """ if style != self._m_item_line_style: self._m_item_line_style = style self.update() def set_orientation(self, orientation: Qt.Orientation): """ 设置导航栏是横向还是纵向 :param orientation: Qt.Orientation 类型 :return: None """ if orientation != self._m_orientation: self._m_orientation = orientation self.update() def set_fixed(self, fixed: bool): """ 设置导航栏尺寸固定,不随窗口大小进行缩放 :param fixed: bool 类型 :return: None """ if fixed != self._m_fixed: self._m_fixed = fixed self.update() def get_current_item_index(self): """ 返回当前选中项目的索引号 :return: int类型,索引号 """ return self._m_current_index # -----------以下是槽函数--------------# def on_set_enable_key_move(self, enable: bool): """ 设置可以使用按键来切换导航项目 :param enable: bool 类型 :return: None """ if enable != self._m_enable_key_move: self._m_enable_key_move = enable def on_move_to_first_item(self): """ 切换到第一个项目 :return: None """ self.on_move_to_index(0) def on_move_to_last_item(self): """ 切换到最后一个项目 :return: None """ self.on_move_to_index(len(self._m_item_maps) - 1) def on_move_to_previous_item(self): """ 切换到上一个项目 :return: None """ if self._m_current_index == 0: return self.on_move_to_index(self._m_current_index - 1) def on_move_to_next_item(self): """ 切换到下一个项目 :return: None """ if self._m_current_index == len(self._m_item_maps) - 1: return self.on_move_to_index(self._m_current_index + 1) def on_move_to_index(self, index: int): """ 切换到指定索引的项目 :param index: int, 项目的索引号 :return: None """ if (index >= 0) and (index < len(self._m_item_maps)) and (index != self._m_current_index): self.itemClicked.emit(index, self._m_item_maps[index][0]) if self._m_current_index == -1: self._m_start_rect = QRectF(self._m_item_maps[index][1]) self._m_forward = index > self._m_current_index self._m_current_index = index self._m_stop_rect = QRectF(self._m_item_maps[index][1]) self._m_slide_timer.start() def on_move_to_name(self, name: str): """ 切换到指定名称的项目 :param name: 项目的名称,str类型 :return: None """ for key, value in self._m_item_maps.items(): if value[0] == name: target_index = key if target_index == self._m_current_index: return self.on_move_to_index(target_index) break def on_move_to_position(self, point: QPointF): """ 切换到指定位置的项目 :param point: 位置坐标,QPointF类型 :return: None """ for key, value in self._m_item_maps.items(): if value[1].contains(point): target_index = key if target_index == self._m_current_index: return self.on_move_to_index(target_index) break def on_set_current_item_index(self, index: int): """ 将当前选中项目切换到指定索引的项目 :param index: 索引号, int :return: NOne """ self.on_move_to_index(index) # ------------以下是私有槽函数---------# def _on_do_slide(self): """ 完成滑动动作 :return: None """ if self._m_space <= 0 or self._m_start_rect == self._m_stop_rect: self.update() self._m_slide_timer.stop() return if self._m_orientation == Qt.Horizontal: dx = self._m_space / 2.0 dy = 0 else: dx = 0 dy = self._m_space / 2.0 if self._m_forward: self._m_start_rect.adjust(dx, dy, dx, dy) if ((self._m_orientation == Qt.Horizontal) and (self._m_start_rect.topLeft().x() >= self._m_stop_rect.topLeft().x())) or \ ((self._m_orientation == Qt.Vertical) and (self._m_start_rect.topLeft().y() >= self._m_stop_rect.topLeft().y())): self._m_slide_timer.stop() if self._m_start_rect != self._m_stop_rect: self._m_shake_timer.start() else: self._m_start_rect.adjust(-dx, -dy, -dx, -dy) if ((self._m_orientation == Qt.Horizontal) and (self._m_start_rect.topLeft().x() <= self._m_stop_rect.topLeft().x())) or \ ((self._m_orientation == Qt.Vertical) and (self._m_start_rect.topLeft().y() <= self._m_stop_rect.topLeft().y())): self._m_slide_timer.stop() if self._m_start_rect != self._m_stop_rect: self._m_shake_timer.start() self.update() def _on_do_shake(self): """ 完成晃动动作 :return: None """ delta = 2.0 dx1 = dx2 = dy1 = dy2 = 0.0 if self._m_start_rect.topLeft().x() > self._m_stop_rect.topLeft().x(): dx1 = -delta elif self._m_start_rect.topLeft().x() < self._m_stop_rect.topLeft().x(): dx1 = delta if self._m_start_rect.topLeft().y() > self._m_stop_rect.topLeft().y(): dy1 = -delta elif self._m_start_rect.topLeft().y() < self._m_stop_rect.topLeft().y(): dy1 = delta if self._m_start_rect.bottomRight().x() > self._m_stop_rect.bottomRight().x(): dx2 = -delta elif self._m_start_rect.bottomRight().x() < self._m_stop_rect.bottomRight().x(): dx2 = delta if self._m_start_rect.bottomRight().y() > self._m_stop_rect.bottomRight().y(): dy2 = -delta elif self._m_start_rect.bottomRight().y() < self._m_stop_rect.bottomRight().y(): dy2 = delta self._m_start_rect.adjust(dx1, dy1, dx2, dy2) if abs(self._m_start_rect.topLeft().x() - self._m_stop_rect.topLeft().x()) <= delta: self._m_start_rect.setLeft(self._m_stop_rect.topLeft().x()) if abs(self._m_start_rect.topLeft().y() - self._m_stop_rect.topLeft().y()) <= delta: self._m_start_rect.setTop(self._m_stop_rect.topLeft().y()) if abs(self._m_start_rect.bottomRight().x() - self._m_stop_rect.bottomRight().x()) <= delta: self._m_start_rect.setRight(self._m_stop_rect.bottomRight().x()) if abs(self._m_start_rect.bottomRight().y() - self._m_stop_rect.bottomRight().y()) <= delta: self._m_start_rect.setBottom(self._m_stop_rect.bottomRight().y()) if self._m_start_rect == self._m_stop_rect: self._m_shake_timer.stop() self.update() # -----------以下是事件响应函数的重载函数-----------# def paintEvent(self, a0: QtGui.QPaintEvent) -> None: """ 重载paintEvent函数 :param a0: :return: """ painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) self._draw_bar_background(painter) self._draw_item_background(painter) self._draw_item_line(painter) self._draw_text(painter) def resizeEvent(self, a0: QtGui.QResizeEvent) -> None: """ 重载resizeEvent函数 :param a0: :return: """ self._adjust_item_size() def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None: """ 重载mousePressEvent函数 :param a0: 事件 :return:None """ self.on_move_to_position(a0.pos()) def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None: """ 重载mouseMoveEvent函数 :param a0: 事件 :return: None """ is_on_item = False for key, value in self._m_item_maps.items(): if value[1].contains(a0.pos()): self._m_current_hover_index = key is_on_item = True break if not is_on_item: self._m_current_hover_index = -1 self.update() def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None: """ 重载keyPressEvent函数 :param a0: :return: """ if not self._m_enable_key_move: # self.keyPressEvent(a0) return if a0.key() == Qt.Key_Home: self.on_move_to_first_item() elif a0.key() == Qt.Key_End: self.on_move_to_last_item() elif a0.key() == Qt.Key_Up or a0.key() == Qt.Key_Left: self.on_move_to_previous_item() elif a0.key() == Qt.Key_Down or a0.key() == Qt.Key_Right: self.on_move_to_next_item() else: # self.keyPressEvent(a0) return # -----------------以下是私有成员函数---------------------# def _draw_bar_background(self, p: QPainter): """ 绘制导航栏的背景 :param p: 画刷 :return: None """ p.save() p.setPen(Qt.NoPen) lgt = QLinearGradient(QPointF(0, 0), QPointF(0, self.height())) lgt.setColorAt(0.0, self._m_bar_start_color) lgt.setColorAt(1.0, self._m_bar_end_color) p.setBrush(lgt) p.drawRoundedRect(self.rect(), self._m_bar_radius, self._m_bar_radius) p.restore() def _draw_item_background(self, p: QPainter): """ 绘制项目的背景 :param p: 画刷 :return: None """ if self._m_start_rect.isNull(): return p.save() lgt = QLinearGradient(self._m_start_rect.topLeft(), self._m_start_rect.bottomRight()) lgt.setColorAt(0.0, self._m_item_start_color) lgt.setColorAt(1.0, self._m_item_end_color) p.setPen(Qt.NoPen) p.setBrush(lgt) p.drawRoundedRect(self._m_start_rect, self._m_item_radius, self._m_item_radius) # 绘制 hover 状态下的item if self._m_current_hover_index != -1: hover_rect = QRectF(self._m_item_maps[self._m_current_hover_index][1]) lgt = QLinearGradient(hover_rect.topLeft(), hover_rect.bottomRight()) lgt.setColorAt(0.0, self._m_item_hover_start_color) lgt.setColorAt(1.0, self._m_item_hover_end_color) p.setPen(Qt.NoPen) p.setBrush(lgt) p.drawRoundedRect(hover_rect, self._m_item_radius, self._m_item_radius) p.restore() def _draw_item_line(self, p: QPainter) -> None: """ 绘制项目周边的线条 :param p: 画刷 :return: None """ if self._m_start_rect.isNull(): return if self._m_item_line_style == self.ItemLineStyle.ItemNone: return elif self._m_item_line_style == self.ItemLineStyle.ItemTop: p1 = self._m_start_rect.topLeft() p2 = self._m_start_rect.topRight() elif self._m_item_line_style == self.ItemLineStyle.ItemRight: p1 = self._m_start_rect.topRight() p2 = self._m_start_rect.bottomRight() elif self._m_item_line_style == self.ItemLineStyle.ItemBottom: p1 = self._m_start_rect.bottomLeft() p2 = self._m_start_rect.bottomRight() elif self._m_item_line_style == self.ItemLineStyle.ItemLeft: p1 = self._m_start_rect.topLeft() p2 = self._m_start_rect.bottomLeft() elif self._m_item_line_style == self.ItemLineStyle.ItemRect: p1 = self._m_start_rect.topLeft() p2 = self._m_start_rect.bottomRight() else: return p.save() line_pen = QPen() line_pen.setColor(self._m_item_line_color) line_pen.setWidth(self._m_item_line_width) p.setPen(line_pen) if self._m_item_line_style == self.ItemLineStyle.ItemRect: p.drawRoundedRect(QRectF(p1, p2), self._m_item_radius, self._m_item_radius) else: p.drawLine(p1, p2) p.restore() def _draw_text(self, p: QPainter) -> None: """ 绘制项目的名称 :param p: 画刷 :return: None """ p.save() p.setPen(self._m_item_text_color) for key, value in self._m_item_maps.items(): self._m_item_font.setPointSize(self._m_item_font_size) p.setFont(self._m_item_font) p.drawText(value[1], Qt.AlignCenter, value[0]) p.restore() def _adjust_item_size(self) -> None: """ 调整Item大小 :return: """ if self._m_fixed: return item_count = len(self._m_item_maps) if self._m_orientation == Qt.Horizontal: add_width = 1.0 * (self.width() - self._m_total_text_width) / item_count add_height = 1.0 * (self.height() - self._m_total_text_height) else: add_width = 1.0 * (self.width() - self._m_total_text_width) add_height = 1.0 * (self.height() - self._m_total_text_height) / item_count dx = dy = 0.0 for key, value in self._m_item_maps.items(): # f = QFont() fm = QFontMetrics(self._m_item_font) text_width = fm.width(value[0]) text_height = fm.height() if self._m_orientation == Qt.Horizontal: topLeft = QPointF(dx, 0) dx += text_width + self._m_space + add_width dy = self._m_total_text_height + add_height else: topLeft = QPointF(0, dy) dx = self._m_total_text_width + add_width dy += text_height + self._m_space + add_height bottomRight = QPointF(dx, dy) text_rect = QRectF(topLeft, bottomRight) self._m_item_maps[key] = [value[0], QRectF(text_rect)] if key == self._m_current_index: self._m_start_rect = text_rect self._m_stop_rect = text_rect self.update()
initial_polygon = QPolygonF(initial_corridor) corridor_points = {'bottom': [], 'right': [], 'top': [], 'left': []} corridor_sides = { # bottom y top deben estar cambiados 'bottom': [ initial_corridor_interior.topLeft(), initial_corridor_interior.topRight() ], 'right': [ initial_corridor_interior.topRight(), initial_corridor_interior.bottomRight() ], 'top': [ initial_corridor_interior.bottomLeft(), initial_corridor_interior.bottomRight() ], 'left': [ initial_corridor_interior.bottomLeft(), initial_corridor_interior.topLeft() ] } # -------- Recorro el pasillo inicial buscando puntos a lo largo de su perimetro ----------- for side, points in corridor_sides.items(): line = QLineF(points[0], points[1]) line_lenght = int(line.length()) step = line_lenght / 100.
class Room: def __init__(self, type='genericRoom', p=QPointF(), w=-1, h=-1): self.type = type # corridor, bedroom, kitchen, bathroom, etc self.width = w self.height = h self.initial_point = p self.room_qrect = QRectF() self.room_qpolygon = QPolygonF() self.area = -1 self.side = None self.door_loc = -1 # 0 entre topL y topR, 1 entre topR y bottomR, 2 entre bottomR y bottomL y 3 entr bL y tL self.create_room() def create_room(self): print( f'Creating room of type {self.type} with width = {self.width} and height = {self.height}' ) self.room_qrect = QRectF(self.initial_point.x(), self.initial_point.y(), self.width, self.height) self.room_qpolygon = QPolygonF(self.room_qrect) self.area = abs(self.width * self.height) def update_room_dimensions(self): self.width = self.room_qrect.width() self.height = self.room_qrect.height() self.area = abs(self.width * self.height) self.room_qpolygon = QPolygonF(self.room_qrect) def add_door(self, door_location, room_side): self.side = room_side dict_location_line = { 'center': QLineF(self.room_qrect.topLeft(), self.room_qrect.topRight()), 'left': QLineF(self.room_qrect.topLeft(), self.room_qrect.bottomLeft()), 'right': QLineF(self.room_qrect.topRight(), self.room_qrect.bottomRight()) } line = dict_location_line[door_location] line_lenght = int(line.length()) step = line_lenght / 100. line_points = [] for t in np.arange(0.25, 0.75, step): line_point = line.pointAt(t) line_points.append(QPointF(line_point.x(), line_point.y())) random_center_door = random.choice(line_points) door_sides = { 'center': { 'left_door': QPointF(random_center_door.x() - 0.5, random_center_door.y()), 'right_door': QPointF(random_center_door.x() + 0.5, random_center_door.y()) }, 'left': { 'left_door': QPointF(random_center_door.x(), random_center_door.y() - 0.5), 'right_door': QPointF(random_center_door.x(), random_center_door.y() + 0.5) }, 'right': { 'left_door': QPointF(random_center_door.x(), random_center_door.y() - 0.5), 'right_door': QPointF(random_center_door.x(), random_center_door.y() + 0.5) } } if door_location == 'center': self.room_qpolygon = QPolygonF([ door_sides[door_location]['right_door'], self.room_qrect.topRight(), self.room_qrect.bottomRight(), self.room_qrect.bottomLeft(), self.room_qrect.topLeft(), door_sides[door_location]['left_door'] ]) self.door_loc = 0 elif door_location == 'right': if room_side == 'bottom': self.room_qpolygon = QPolygonF([ door_sides[door_location]['right_door'], self.room_qrect.topRight(), self.room_qrect.topLeft(), self.room_qrect.bottomLeft(), self.room_qrect.bottomRight(), door_sides[door_location]['left_door'] ]) elif room_side == 'top': self.room_qpolygon = QPolygonF([ door_sides[door_location]['right_door'], self.room_qrect.bottomRight(), self.room_qrect.bottomLeft(), self.room_qrect.topLeft(), self.room_qrect.topRight(), door_sides[door_location]['left_door'] ]) self.door_loc = 1 elif door_location == 'left': if room_side == 'bottom': self.room_qpolygon = QPolygonF([ door_sides[door_location]['right_door'], self.room_qrect.topLeft(), self.room_qrect.topRight(), self.room_qrect.bottomRight(), self.room_qrect.bottomLeft(), door_sides[door_location]['left_door'] ]) elif room_side == 'top': self.room_qpolygon = QPolygonF([ door_sides[door_location]['right_door'], self.room_qrect.bottomLeft(), self.room_qrect.bottomRight(), self.room_qrect.topRight(), self.room_qrect.topLeft(), door_sides[door_location]['left_door'] ]) self.door_loc = 3
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()], 'left': [initial_corridor.topLeft(), initial_corridor.bottomLeft()] } # -------------------------------------------------------------------------------------------------------- # ------------ Se buscan n habitaciones que no interseccionen ni contengan a ninguna otra -------------- # -------------------------------------------------------------------------------------------------------- random_qrect_list = [] for i in range(0, num_rooms): print(f'------------ i - {i} ------------') valid = False count = 0
def redraw(self): self.graphics_scene.clear() # draw screenshot self.graphics_scene.addPixmap(self.screenPixel) # prepare for drawing selected area rect = QRectF(self.selected_area) rect = rect.normalized() top_left_point = rect.topLeft() top_right_point = rect.topRight() bottom_left_point = rect.bottomLeft() bottom_right_point = rect.bottomRight() top_middle_point = (top_left_point + top_right_point) / 2 left_middle_point = (top_left_point + bottom_left_point) / 2 bottom_middle_point = (bottom_left_point + bottom_right_point) / 2 right_middle_point = (top_right_point + bottom_right_point) / 2 # draw the picture mask mask = QColor(0, 0, 0, 155) if self.selected_area == QRect(): self.graphics_scene.addRect(0, 0, self.screenPixel.width(), self.screenPixel.height(), QPen(Qt.NoPen), mask) else: self.graphics_scene.addRect(0, 0, self.screenPixel.width(), top_right_point.y(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect(0, top_left_point.y(), top_left_point.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect( top_right_point.x(), top_right_point.y(), self.screenPixel.width() - top_right_point.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphics_scene.addRect( 0, bottom_left_point.y(), self.screenPixel.width(), self.screenPixel.height() - bottom_left_point.y(), QPen(Qt.NoPen), mask) # draw the toolBar if self.action != ACTION_SELECT: spacing = 5 # show the toolbar first, then move it to the correct position # because the width of it may be wrong if this is the first time it shows self.tooBar.show() dest = QPointF(rect.bottomRight() - QPointF(self.tooBar.width(), 0) - QPointF(spacing, -spacing)) if dest.x() < spacing: dest.setX(spacing) pen_set_bar_height = self.penSetBar.height( ) if self.penSetBar is not None else 0 if dest.y() + self.tooBar.height( ) + pen_set_bar_height >= self.height(): if rect.top() - self.tooBar.height( ) - pen_set_bar_height < spacing: dest.setY(rect.top() + spacing) else: dest.setY(rect.top() - self.tooBar.height() - pen_set_bar_height - spacing) self.tooBar.move(dest.toPoint()) if self.penSetBar is not None: self.penSetBar.show() self.penSetBar.move(dest.toPoint() + QPoint(0, self.tooBar.height() + spacing)) if self.action == ACTION_TEXT: self.penSetBar.showFontWidget() else: self.penSetBar.showPenWidget() else: self.tooBar.hide() if self.penSetBar is not None: self.penSetBar.hide() # draw the list for step in self.drawListResult: self.drawOneStep(step) if self.drawListProcess is not None: self.drawOneStep(self.drawListProcess) if self.action != ACTION_TEXT: self.drawListProcess = None if self.selected_area != QRect(): self.items_to_remove = [] # draw the selected rectangle pen = QPen(QColor(0, 255, 255), 2) self.items_to_remove.append(self.graphics_scene.addRect(rect, pen)) # draw the drag point radius = QPoint(3, 3) brush = QBrush(QColor(0, 255, 255)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_left_point - radius, top_left_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_middle_point - radius, top_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(top_right_point - radius, top_right_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(left_middle_point - radius, left_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(right_middle_point - radius, right_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_left_point - radius, bottom_left_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_middle_point - radius, bottom_middle_point + radius), pen, brush)) self.items_to_remove.append( self.graphics_scene.addEllipse( QRectF(bottom_right_point - radius, bottom_right_point + radius), pen, brush)) # draw the textedit if self.textPosition is not None: textSpacing = 50 position = QPoint() if self.textPosition.x() + self.textInput.width( ) >= self.screenPixel.width(): position.setX(self.textPosition.x() - self.textInput.width()) else: position.setX(self.textPosition.x()) if self.textRect is not None: if self.textPosition.y() + self.textInput.height( ) + self.textRect.height() >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height() - self.textRect.height()) else: position.setY(self.textPosition.y() + self.textRect.height()) else: if self.textPosition.y() + self.textInput.height( ) >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height()) else: position.setY(self.textPosition.y()) self.textInput.move(position) self.textInput.show() # self.textInput.getFocus() # draw the magnifier if self.action == ACTION_SELECT: self.drawMagnifier() if self.mousePressed: self.drawSizeInfo() if self.action == ACTION_MOVE_SELECTED: self.drawSizeInfo()
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))