def paint( self, p: QtGui.QPainter, opt: QtWidgets.QStyleOptionGraphicsItem, w: QtWidgets.QWidget ) -> None: if self._in_ds: return profiler = pg.debug.Profiler( disabled=not pg_profile_enabled(), gt=ms_slower_then, ) # p.setCompositionMode(0) # TODO: one thing we could try here is pictures being drawn of # a fixed count of bars such that based on the viewbox indices we # only draw the "rounded up" number of "pictures worth" of bars # as is necesarry for what's in "view". Not sure if this will # lead to any perf gains other then when zoomed in to less bars # in view. p.setPen(self.last_bar_pen) p.drawLines(*tuple(filter(bool, self._last_bar_lines))) profiler('draw last bar') p.setPen(self.bars_pen) p.drawPath(self.path) profiler(f'draw history path: {self.path.capacity()}')
def paintEvent(self, event): """Paint event for the overlay :param event: QPaintEvent event :type event: QPaintEvent """ super().paintEvent(event) painter = QPainter(self) pen = QPen(Qt.black) pen.setWidth(1) painter.setPen(pen) painter.setBrush(Qt.NoBrush) painter.drawRect(0, 0, 16 * 25 - 1, self.height * 25 - 1) lines = [] for longitude in range(16): line = QLineF(longitude * 25, 0, longitude * 25, self.height * 25) lines.append(line) for latitude in range(self.height): line = QLineF(0, latitude * 25, 16 * 25, latitude * 25) lines.append(line) painter.drawLines(lines) s_root, s_width, s_height = self.selected x = s_root % 16 y = math.floor(s_root / 16) pen.setColor(Qt.red) pen.setWidth(3) pen.setJoinStyle(Qt.MiterJoin) painter.setPen(pen) painter.drawRect(x * 25, y * 25, s_width * 25, s_height * 25)
def drawBackground(self, painter: QPainter, rect: QRectF): rect = self.sceneRect() super().drawBackground(painter, rect) # 绘制纯色背景 # 绘制网格 xLines_thin = [] yLines_thin = [] xLines_blod = [] yLines_blod = [] for i in range(0, self.rectSize, self.gridSize): if (i % 100) != 0: xLines_thin.append( QLineF(rect.left(), rect.top() + i, rect.right(), rect.top() + i)) yLines_thin.append( QLineF(rect.left() + i, rect.top(), rect.left() + i, rect.bottom())) else: xLines_blod.append( QLineF(rect.left(), rect.top() + i, rect.right(), rect.top() + i)) yLines_blod.append( QLineF(rect.left() + i, rect.top(), rect.left() + i, rect.bottom())) painter.setPen(QPen(self.grid_line_color, self.tinny_grid_line_width)) painter.drawLines(xLines_thin) painter.drawLines(yLines_thin) painter.setPen(QPen(self.grid_line_color, self.bold_grid_line_width)) painter.drawLines(xLines_blod) painter.drawLines(yLines_blod)
def paintEvent(self, a0: QPaintEvent): # print("paint") painter = QPainter(self) # painter.begin(self) painter.drawPixmap(0, 0, self.width(), self.height(), self.qpix) if self.enable_extra_14_bytes and self.extra_data: pix_width = self.width() / self.imgWidth pix_height = self.height() / self.imgHeight # painter.setPen(QPen(Qt.red, -14)) painter.setBrush(QBrush(Qt.red)) painter.drawEllipse(self.extra_data[1] * pix_width, self.extra_data[0] * pix_height, pix_width, pix_height) painter.drawEllipse(self.extra_data[2] * pix_width, self.extra_data[0] * pix_height, pix_width, pix_height) painter.drawEllipse(self.extra_data[3] * pix_width, self.extra_data[0] * pix_height, pix_width, pix_height) painter.drawEllipse(self.extra_data[4] * pix_width, self.extra_data[0] * pix_height, pix_width, pix_height) if self.enable_grid: painter.setPen(Qt.darkBlue) painter.drawLines(self.grid_points)
def draw_background(self, painter: QtGui.QPainter, rect: QtCore.QRectF) -> None: if not self._show_grid: return painter.setPen( QtGui.QPen( QtGui.QColor(0, 0, 0) ) ) lines = [] for x in list(self.stacker_map.row_termination_points())[:-1]: if rect.left() <= x <= rect.right(): lines.append( QLineF( x, rect.top(), x, rect.bottom(), ) ) for y in list(self.stacker_map.column_termination_points())[:-1]: if rect.top() <= y <= rect.bottom(): lines.append( QLineF( rect.left(), y, rect.right(), y, ) ) painter.drawLines(lines)
def drawBackground(self, painter: QPainter, rect: QRectF): # freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate) if self.draw_grid and len(self.frequencies) > 0: painter.setPen(QPen(painter.pen().color(), 0)) parent_width = self.parent().width() if hasattr( self.parent(), "width") else 750 view_rect = self.parent().view_rect() if hasattr( self.parent(), "view_rect") else rect font_width = self.font_metrics.width( Formatter.big_value_with_suffix(self.center_freq) + " ") x_grid_size = int(view_rect.width() / parent_width * font_width) # x_grid_size = int(0.1 * view_rect.width()) if 0.1 * view_rect.width() > 1 else 1 y_grid_size = 1 x_mid = np.where(self.frequencies == 0)[0] x_mid = int(x_mid[0]) if len(x_mid) > 0 else 0 left = int(rect.left()) - (int(rect.left()) % x_grid_size) left = left if left > 0 else 0 top = rect.top() - (rect.top() % y_grid_size) bottom = rect.bottom() - (rect.bottom() % y_grid_size) right_border = int( rect.right()) if rect.right() < len(self.frequencies) else len( self.frequencies) x_range = list(range(x_mid, left, -x_grid_size)) + list( range(x_mid, right_border, x_grid_size)) lines = [QLineF(x, rect.top(), x, bottom) for x in x_range] \ + [QLineF(rect.left(), y, rect.right(), y) for y in np.arange(top, bottom, y_grid_size)] painter.drawLines(lines) scale_x, scale_y = util.calc_x_y_scale(rect, self.parent()) painter.scale(scale_x, scale_y) counter = -1 # Counter for Label for every second line for x in x_range: freq = self.frequencies[x] counter += 1 if freq != 0 and (counter % 2 != 0): # Label for every second line continue if freq != 0: prefix = "+" if freq > 0 else "" value = prefix + Formatter.big_value_with_suffix(freq, 2) else: counter = 0 value = Formatter.big_value_with_suffix(6800e6 - self.center_freq + self.status_k) font_width = self.font_metrics.width(value) painter.drawText(x / scale_x - font_width / 2, bottom / scale_y, value)
def paintEvent(self, event): lin = [QLineF(400, 150, 770, 150)] QWidget.paintEvent(self, event) painter = QPainter(self) painter.setPen(QPen(Qt.darkYellow, 6)) painter.drawLines(ln for ln in lin) painter.setPen(QPen(Qt.lightGray, 6)) painter.drawLines(el for el in self.lines) if not self.center.isNull(): painter.drawEllipse(self.center, self.rad, self.rad)
def drawCross(self): w, h = self._getDimensions() painter = QPainter(self) self.pen.setColor(QColor.fromRgb(47, 101, 236)) painter.setPen(self.pen) lines = [QLineF(self.delta, self.delta, w - self.delta, h - self.delta), QLineF(self.delta, h - self.delta, w - self.delta, self.delta)] painter.drawLines(lines)
def drawCursors(self): qp = QPainter() qp.begin(self) for cursor in self.cursors: pen = QPen(cursor.getColor(), 1, Qt.SolidLine) qp.setPen(pen) line = self.getLine(cursor) qp.drawLine(line) if cursor.getStyle() == CursorStyle.barred: lines = self.getBars(cursor) pen = QPen(cursor.getBarColor(), 1, Qt.SolidLine) qp.setPen(pen) qp.drawLines(lines) qp.end()
def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image.scaledToWidth(self.width*self.image_pixel_width, Qt.SmoothTransformation)) if self.agc_roi_from != None and self.agc_roi_to != None and not self.image_is_16bit: pen = QPen() pen.setColor(Qt.green) pen.setWidth(1) painter.setPen(pen) roi = self.parent.get_agc_roi() painter.drawRect(roi[0] * self.image_pixel_width + 1, roi[1] * self.image_pixel_width + 1, (roi[2] - roi[0]) * self.image_pixel_width + 1, (roi[3] - roi[1]) * self.image_pixel_width + 1) self.parent.update_agc_roi_label() if self.spotmeter_roi_from != None and self.spotmeter_roi_to != None: pen = QPen() pen.setColor(Qt.white) pen.setWidth(1) painter.setPen(pen) from_x, from_y, to_x, to_y = self.parent.get_spotmeter_roi() from_x = from_x * self.image_pixel_width + 1 from_y = from_y * self.image_pixel_width + 1 to_x = to_x * self.image_pixel_width + 1 to_y = to_y * self.image_pixel_width + 1 cross_x = from_x + (to_x-from_x) / 2.0 cross_y = from_y + (to_y-from_y) / 2.0 if to_x-from_x > 5 or to_y - from_y > 5: lines = [QLineF(from_x, from_y, from_x + self.crosshair_width, from_y), QLineF(from_x, from_y, from_x, from_y + self.crosshair_width), QLineF(to_x, to_y, to_x, to_y - self.crosshair_width), QLineF(to_x, to_y, to_x - self.crosshair_width, to_y), QLineF(from_x, to_y, from_x, to_y-self.crosshair_width), QLineF(from_x, to_y, from_x + self.crosshair_width, to_y), QLineF(to_x, from_y, to_x, from_y+self.crosshair_width), QLineF(to_x, from_y, to_x - self.crosshair_width, from_y)] painter.drawLines(lines) lines = [QLineF(cross_x - self.crosshair_width, cross_y, cross_x + self.crosshair_width, cross_y), QLineF(cross_x, cross_y - self.crosshair_width, cross_x, cross_y+self.crosshair_width)] painter.drawLines(lines) self.parent.update_spotmeter_roi_label()
def drawBackground(self, painter: QPainter, rect: QRectF): # freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate) if self.draw_grid and len(self.frequencies) > 0: painter.setPen(QPen(painter.pen().color(), Qt.FlatCap)) parent_width = self.parent().width() if hasattr(self.parent(), "width") else 750 view_rect = self.parent().view_rect() if hasattr(self.parent(), "view_rect") else rect font_width = self.font_metrics.width(Formatter.big_value_with_suffix(self.center_freq) + " ") x_grid_size = int(view_rect.width() / parent_width * font_width) # x_grid_size = int(0.1 * view_rect.width()) if 0.1 * view_rect.width() > 1 else 1 y_grid_size = view_rect.height() / parent_width * font_width x_mid = np.where(self.frequencies == 0)[0] x_mid = int(x_mid[0]) if len(x_mid) > 0 else 0 left = int(rect.left()) - (int(rect.left()) % x_grid_size) left = left if left > 0 else 0 top = rect.top() - (rect.top() % y_grid_size) bottom = rect.bottom() - (rect.bottom() % y_grid_size) right_border = int(rect.right()) if rect.right() < len(self.frequencies) else len(self.frequencies) x_range = list(range(x_mid, left, -x_grid_size)) + list(range(x_mid, right_border, x_grid_size)) lines = [QLineF(x, rect.top(), x, bottom) for x in x_range] \ + [QLineF(rect.left(), y, rect.right(), y) for y in np.arange(top, bottom, y_grid_size)] painter.drawLines(lines) scale_x = view_rect.width() / parent_width scale_y = view_rect.height() / parent_width painter.scale(scale_x, scale_y) font_height = self.font_metrics.height() counter = -1 # Counter for Label for every second line for x in x_range: freq = self.frequencies[x] counter += 1 if freq != 0 and (counter % 2 != 0): # Label for every second line continue if freq != 0: prefix = "+" if freq > 0 else "" value = prefix+Formatter.big_value_with_suffix(freq, 2) else: counter = 0 value = Formatter.big_value_with_suffix(self.center_freq) font_width = self.font_metrics.width(value) painter.drawText(x / scale_x - font_width / 2, bottom / scale_y + font_height, value)
def paintEvent(self, event): super(ScaleWindow, self).paintEvent(event) if self._image: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) path = QPainterPath() radius = min(self.width(), self.height()) / 2 path.addRoundedRect(QRectF(self.rect()), radius, radius) painter.setClipPath(path) painter.drawImage(self.rect(), self._image) painter.setPen(QPen(QColor(0, 174, 255), 3)) hw = self.width() / 2 hh = self.height() / 2 painter.drawLines(QLineF(hw, 0, hw, self.height()), QLineF(0, hh, self.width(), hh)) painter.setPen(QPen(Qt.white, 3)) painter.drawRoundedRect(self.rect(), radius, radius)
def drawBackground(self, painter: QtGui.QPainter, rect: QtCore.QRectF): grid_size = 25 left = int(rect.left()) - (int(rect.left()) % grid_size) top = int(rect.top()) - (int(rect.top()) % grid_size) lines = [] for x in range(left, int(rect.right()), grid_size): lines.append(QLineF(x, rect.top(), x, rect.bottom())) for y in range(top, int(rect.bottom()), grid_size): lines.append(QLineF(rect.left(), y, rect.right(), y)) # print(len(lines)) painter.drawLines(lines)
def drawBackground(self, painter: QPainter, rect: QRectF): # freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate) if self.draw_grid and len(self.frequencies) > 0: painter.setPen(QPen(painter.pen().color(), Qt.FlatCap)) parent_width = self.parent().width() if hasattr( self.parent(), "width") else 750 view_rect = self.parent().view_rect() if hasattr( self.parent(), "view_rect") else rect font_width = self.font_metrics.width( self.value_with_suffix(self.center_freq) + " ") x_grid_size = int(view_rect.width() / parent_width * font_width) # x_grid_size = int(0.1 * view_rect.width()) if 0.1 * view_rect.width() > 1 else 1 y_grid_size = view_rect.height() / parent_width * font_width x_mid = np.where(self.frequencies == 0)[0] x_mid = int(x_mid[0]) if len(x_mid) > 0 else 0 left = int(rect.left()) - (int(rect.left()) % x_grid_size) left = left if left > 0 else 0 top = rect.top() - (rect.top() % y_grid_size) bottom = rect.bottom() - (rect.bottom() % y_grid_size) right_border = int( rect.right()) if rect.right() < len(self.frequencies) else len( self.frequencies) x_range = list(range(x_mid, left, -x_grid_size)) + list( range(x_mid, right_border, x_grid_size)) lines = [QLineF(x, rect.top(), x, bottom) for x in x_range] \ + [QLineF(rect.left(), y, rect.right(), y) for y in np.arange(top, bottom, y_grid_size)] painter.drawLines(lines) scale_x = view_rect.width() / parent_width scale_y = view_rect.height() / parent_width painter.scale(scale_x, scale_y) font_height = self.font_metrics.height() for x in x_range: value = self.value_with_suffix(self.center_freq + self.frequencies[x]) font_width = self.font_metrics.width(value) painter.drawText(x / scale_x - font_width / 2, bottom / scale_y + font_height, value)
def draw(self, qp: QPainter, end_pos: tuple or list = None) -> bool: """ draws line in core object :param qp: QPainter of main UI object (core) :param end_pos: position of mouse if arrow on mouse if arrow has end position, end_pos param will be ignored """ if self.end_pos: qp.drawLine(QLine(*self.start_pos, *self.end_pos)) if self.need_arrow: ar1, ar2 = self.create_arrow(end_pos=self.end_pos) qp.drawLines(ar1, ar2) return False elif end_pos: start, end = self.get_start_and_end(end_pos) qp.drawLine(QLine(*start, *end)) if self.need_arrow: ar1, ar2 = self.create_arrow(end_pos=end_pos) qp.drawLines(ar1, ar2) return True
def draw(self, qp: QtGui.QPainter): """ draws grid and special lines :param qp: QPainter from main object """ if not self.show or not self.grid: return qp.setPen(self.pen) special_lines = self.get_special_lines() if self.grid.get("x", []): qp.drawLines(*self.grid["x"]) if self.grid.get("y", []): qp.drawLines(*self.grid["y"]) pen = QtGui.QPen(QtGui.QColor(self.special_lines_color), self.pen.width()) pen.setStyle(self.line) qp.setPen(pen) if special_lines.get("x", []): qp.drawLines(*special_lines["x"]) if special_lines.get("y", []): qp.drawLines(*special_lines["y"]) if self.special_lines_for_drag_obj: qp.drawLines(*self.special_lines_for_drag_obj)
def paintGrid(self, painter: QPainter, rect: QRectF, gridSize: int): left, top, right, bottom = rect.getCoords() x_min = (int(left - 1) // gridSize + 1) * gridSize y_min = (int(top - 1) // gridSize + 1) * gridSize x_max = (int(right) // gridSize) * gridSize y_max = (int(bottom) // gridSize) * gridSize # logging.debug( # "x=(%s<=%s..%s<=%s) y=(%s<=%s..%s<=%s)", # *(left, x_min, x_max, right), # *(top, y_min, y_max, bottom) # ) painter.setPen(QPen(Qt.gray, 2)) painter.drawLines(QLineF(0, top, 0, bottom), QLineF(left, 0, right, 0)) painter.setPen(QPen(Qt.gray, 1)) painter.drawLines( QLineF(x, top, x, bottom) for x in range(x_min, x_max + 1, gridSize) if x) painter.drawLines( QLineF(left, y, right, y) for y in range(y_min, y_max + 1, gridSize) if y)
def paintEvent(self, event): if self.x >= self.h_res / 2: if self.y >= self.v_res / 2: cuadrant = 4 else: cuadrant = 1 else: if self.y >= self.v_res / 2: cuadrant = 3 else: cuadrant = 2 opposite_cuadrants = {1: 3, 3: 1, 2: 4, 4: 2} cuadrant = opposite_cuadrants[cuadrant] corner = self.corner_positions[cuadrant] self.move(corner[0], corner[1]) painter = QPainter() painter.begin(self) painter.setPen(QColor(75, 75, 75)) # Paint border painter.drawRect(0, 0, self.rect_width, self.rect_height) # Paint the grid v_lines = [] for i in range(self.M_SIZE[0] - 1): x = 1 + (i + 1) * self.pixel_size + self.grid_thickness * i line = QLineF(x, 1, x, self.rect_height - 1) v_lines.append(line) h_lines = [] for i in range(self.M_SIZE[0] - 1): y = 1 + (i + 1) * self.pixel_size + self.grid_thickness * i line = QLineF(1, y, self.rect_width - 1, y) h_lines.append(line) painter.drawLines(v_lines) painter.drawLines(h_lines) # Paint zoomed pixels img = ImageGrab.grab( bbox=(self.true_corners[0][0], self.true_corners[0][1], self.true_corners[1][0], self.true_corners[1][1]), all_screens=True) pixels = img.load() average = ImageStat.Stat(img).mean for row in range(self.M_SIZE[1]): for col in range(self.M_SIZE[0]): color = QColor(*pixels[col, row]) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawRect( 1 + col * self.pixel_size + col * self.grid_thickness, 1 + row * self.pixel_size + row * self.grid_thickness, self.pixel_size, self.pixel_size) if (row == self.y - self.true_corners[0][1] or col == self.x - self.true_corners[0][0]): pixel = ((255 - average[0]), (255 - average[1]), (255 - average[2]), 120) color = QColor(*pixel) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawRect( 1 + col * self.pixel_size + col * self.grid_thickness, 1 + row * self.pixel_size + row * self.grid_thickness, self.pixel_size, self.pixel_size)
def paintEvent(self, _): """ 重写绘制事件,参考 qfusionstyle.cpp 中的 CE_ProgressBarContents 绘制方法 """ option = QStyleOptionProgressBar() self.initStyleOption(option) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.translate(0.5, 0.5) vertical = option.orientation == Qt.Vertical # 是否垂直 inverted = option.invertedAppearance # 是否反转 # 是否显示动画 indeterminate = (option.minimum == option.maximum) or ( option.minimum < option.progress < option.maximum) rect = option.rect if vertical: rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()) # 翻转宽度和高度 m = QTransform.fromTranslate(rect.height(), 0) m.rotate(90.0) painter.setTransform(m, True) maxWidth = rect.width() progress = max(option.progress, option.minimum) totalSteps = max(1, option.maximum - option.minimum) progressSteps = progress - option.minimum progressBarWidth = int(progressSteps * maxWidth / totalSteps) width = progressBarWidth # 已进行的进度宽度 radius = max(1, (min(width, self.width() if vertical else self.height()) // 4) if self._radius is None else self._radius) reverse = (not vertical and option.direction == Qt.RightToLeft) or vertical if inverted: reverse = not reverse # 绘制范围 path = QPainterPath() if not reverse: progressBar = QRectF(rect.left(), rect.top(), width, rect.height()) else: progressBar = QRectF(rect.right() - width, rect.top(), width, rect.height()) # 切割范围 path.addRoundedRect(progressBar, radius, radius) painter.setClipPath(path) # 绘制背景颜色 painter.setPen(Qt.NoPen) painter.setBrush(self._color) painter.drawRoundedRect(progressBar, radius, radius) if not indeterminate: if self._animation: self._animation.stop() self._animation = None else: # 叠加颜色覆盖后出现类似线条间隔的效果 color = self._color.lighter(320) color.setAlpha(80) painter.setPen(QPen(color, self._lineWidth)) if self._animation: step = int(self._animation.animationStep() % self._lineWidth) else: step = 0 self._animation = QProgressStyleAnimation(self._fps, self) self._animation.start() # 动画斜线绘制 startX = int(progressBar.left() - rect.height() - self._lineWidth) endX = int(rect.right() + self._lineWidth) if (not inverted and not vertical) or (inverted and vertical): lines = [ QLineF(x + step, progressBar.bottom(), x + rect.height() + step, progressBar.top()) for x in range(startX, endX, self._lineWidth) ] else: lines = [ QLineF(x - step, progressBar.bottom(), x + rect.height() - step, progressBar.top()) for x in range(startX, endX, self._lineWidth) ] painter.drawLines(lines)
def paintEvent(self, event): painter = QPainter(self) if self.main_ui.combo_interpolation.currentIndex() == 0: scale_mode = Qt.SmoothTransformation else: scale_mode = Qt.FastTransformation painter.drawImage( event.rect(), self.image.scaledToWidth(self.width * self.image_pixel_size, scale_mode)) if self.agc_roi_from != None and self.agc_roi_to != None and not self.image_is_16bit: from_x, from_y, to_x, to_y = self.agc_roi_from.x( ), self.agc_roi_from.y(), self.agc_roi_to.x(), self.agc_roi_to.y() draw_rect( painter, from_x * self.image_pixel_size + self.image_pixel_size // 2, from_y * self.image_pixel_size + self.image_pixel_size // 2, (to_x - from_x) * self.image_pixel_size + 1, (to_y - from_y) * self.image_pixel_size + 1, 1, Qt.green) self.main_ui.update_agc_roi_label() if self.spotmeter_roi_from != None and self.spotmeter_roi_to != None: pen = QPen() pen.setColor(Qt.white) pen.setWidth(1) painter.setPen(pen) from_x, from_y, to_x, to_y = self.spotmeter_roi_from.x( ), self.spotmeter_roi_from.y(), self.spotmeter_roi_to.x( ), self.spotmeter_roi_to.y() from_x = from_x * self.image_pixel_size + self.image_pixel_size // 2 + 1 from_y = from_y * self.image_pixel_size + self.image_pixel_size // 2 + 1 to_x = to_x * self.image_pixel_size + self.image_pixel_size // 2 - 1 to_y = to_y * self.image_pixel_size + self.image_pixel_size // 2 - 1 cross_x = from_x + (to_x - from_x) / 2.0 cross_y = from_y + (to_y - from_y) / 2.0 if to_x - from_x > self.image_pixel_size or to_y - from_y > self.image_pixel_size: lines = [ QLineF(from_x, from_y, from_x + self.crosshair_width, from_y), QLineF(from_x, from_y, from_x, from_y + self.crosshair_width), QLineF(to_x, to_y, to_x, to_y - self.crosshair_width), QLineF(to_x, to_y, to_x - self.crosshair_width, to_y), QLineF(from_x, to_y, from_x, to_y - self.crosshair_width), QLineF(from_x, to_y, from_x + self.crosshair_width, to_y), QLineF(to_x, from_y, to_x, from_y + self.crosshair_width), QLineF(to_x, from_y, to_x - self.crosshair_width, from_y) ] painter.drawLines(lines) lines = [ QLineF(cross_x - self.crosshair_width, cross_y, cross_x + self.crosshair_width, cross_y), QLineF(cross_x, cross_y - self.crosshair_width, cross_x, cross_y + self.crosshair_width) ] painter.drawLines(lines) self.main_ui.update_spotmeter_roi_label()
class Ui_MainWindow(QMainWindow): def __init__(self): super(Ui_MainWindow, self).__init__() self.setObjectName("MainWindow") self.resize(Game.screenWidth, Game.screenHeight) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("res/Instructions-icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.setWindowIcon(icon) self.menubar = QtWidgets.QMenuBar(self) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.actionExit = QtWidgets.QAction(self) self.actionExit.setObjectName("actionExit") self.menuFile.addAction(self.actionExit) self.menubar.addAction(self.menuFile.menuAction()) self.actionExit.triggered.connect(self.closeEvent) _translate = QtCore.QCoreApplication.translate self.menuFile.setTitle(_translate("MainWindow", "File")) self.actionExit.setText(_translate("MainWindow", "Exit")) self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q")) self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) pen = QPen() pen.setBrush(QtGui.QBrush(Game.angleLineColor)) self.painter = QPainter(self.image) self.painter.setPen(pen) self.stateMessage = '' # self.hitSound = QtGui. self.homeUi() def homeUi(self): Game.state = Game.GameState.INTRO self.removeAllPaint() self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.centralwidget.setAutoFillBackground(False) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.gridLayout.addItem(spacerItem, 2, 1, 1, 1) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem1, 1, 2, 1, 1) self.label = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("Orbitron") font.setPointSize(28) font.setBold(True) font.setWeight(75) self.label.setFont(font) self.label.setFrameShadow(QtWidgets.QFrame.Raised) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setObjectName("label") self.gridLayout.addWidget(self.label, 1, 1, 1, 1) spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem2, 1, 0, 1, 1) self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setEnabled(True) font = QtGui.QFont() font.setPointSize(16) self.pushButton.setFont(font) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("res/Instructions-icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.pushButton.setIcon(icon) self.pushButton.setObjectName("pushButton") self.gridLayout.addWidget(self.pushButton, 4, 1, 1, 1) self.pushButton.pressed.connect(self.insUi) spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.gridLayout.addItem(spacerItem3, 0, 1, 1, 1) spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.gridLayout.addItem(spacerItem4, 5, 1, 1, 1) self.playButton = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(16) self.playButton.setFont(font) self.playButton.setAutoFillBackground(False) icon1 = QtGui.QIcon() icon1.addPixmap(QtGui.QPixmap("res/Play-icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.playButton.setIcon(icon1) self.playButton.setObjectName("playButton") self.gridLayout.addWidget(self.playButton, 3, 1, 1, 1) self.playButton.pressed.connect(self.gameTypeUi) self.setCentralWidget(self.centralwidget) self.retranslateHomeUi() QtCore.QMetaObject.connectSlotsByName(self) def retranslateHomeUi(self): _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "MainWindow")) self.label.setText(_translate("MainWindow", "HIT ME IF YOU CAN")) self.pushButton.setText(_translate("MainWindow", "Instructions")) self.playButton.setText(_translate("MainWindow", "Play Now")) self.show() def gameTypeUi(self): self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setAutoFillBackground(False) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.p2c = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(12) self.p2c.setFont(font) self.p2c.setObjectName("p2c") self.gridLayout.addWidget(self.p2c, 5, 3, 1, 1) self.p2c.pressed.connect(self.p2cSelection) self.p2p = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(12) self.p2p.setFont(font) self.p2p.setObjectName("p2p") self.gridLayout.addWidget(self.p2p, 5, 1, 1, 1) self.p2p.pressed.connect(self.p2pSelection) spacerItem = QtWidgets.QSpacerItem(20, 100, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) self.gridLayout.addItem(spacerItem, 6, 1, 1, 3) spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) self.gridLayout.addItem(spacerItem1, 1, 1, 1, 3) self.gameType = QtWidgets.QLabel(self.centralwidget) self.gameType.setTextFormat(QtCore.Qt.RichText) self.gameType.setAlignment(QtCore.Qt.AlignCenter) self.gameType.setObjectName("gameType") self.gridLayout.addWidget(self.gameType, 0, 0, 1, 5) spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem2, 5, 2, 1, 1) spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem3, 5, 0, 1, 1) spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem4, 5, 4, 1, 1) self.setCentralWidget(self.centralwidget) self.retranslateGameTypeUi() QtCore.QMetaObject.connectSlotsByName(self) def retranslateGameTypeUi(self): _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "MainWindow")) self.p2c.setText(_translate("MainWindow", "With Computer")) self.p2p.setText(_translate("MainWindow", "Two Player")) self.gameType.setText( _translate("MainWindow", "<b style=\'font-size:25px\' >Choose The Game Type<b>")) def p2pSelection(self): Game.type = Game.Type.P2P self.playUi() def p2cSelection(self): Game.type = Game.Type.P2C self.playUi() def insUi(self): Game.state = Game.GameState.INSTRUCT self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setAutoFillBackground(False) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.backButton = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(14) self.backButton.setFont(font) self.backButton.setObjectName("backButton") self.gridLayout.addWidget(self.backButton, 8, 1, 1, 1) self.backButton.pressed.connect(self.homeUi) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem, 8, 0, 1, 1) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem1, 8, 2, 1, 1) spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) self.gridLayout.addItem(spacerItem2, 6, 0, 1, 3) self.plainTextEdit = QtWidgets.QPlainTextEdit(self.centralwidget) font = QtGui.QFont() font.setPointSize(16) self.plainTextEdit.setFont(font) self.plainTextEdit.setReadOnly(True) self.plainTextEdit.setObjectName("plainTextEdit") self.gridLayout.addWidget(self.plainTextEdit, 3, 0, 1, 3) spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) self.gridLayout.addItem(spacerItem3, 2, 0, 1, 3) self.label = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setPointSize(18) font.setBold(True) font.setWeight(75) self.label.setFont(font) self.label.setFrameShape(QtWidgets.QFrame.NoFrame) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setObjectName("label") self.gridLayout.addWidget(self.label, 0, 0, 1, 3) self.setCentralWidget(self.centralwidget) self.retranslateInsUi() QtCore.QMetaObject.connectSlotsByName(self) def retranslateInsUi(self): _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "MainWindow")) self.backButton.setText(_translate("MainWindow", "Back to Mainmenu")) ins = ''' 1. Each of the players will have his turn. 2. Player 1 can tune angle and speed by Key A and D. 3. Player 2 can use Key Left Arrow and Right Arrow to do that. 4. Space Key is used to select an angle or speed and advance. 5. The opponent has a few time to take his position also using A and D or Right and Left Arrow Button depending on his playing side. 6. Player who can hit his opponent gains a point. 7. Press P to pause the game and then Esc to get to the Mainmenu or again P to resume 8. Player gaining 5 points first, is the winner. ''' self.plainTextEdit.setPlainText(_translate("MainWindow", ins)) self.label.setText(_translate("MainWindow", "INSTRUCTION")) self.show() def playUi(self): Game.state = Game.GameState.PLAY self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setAutoFillBackground(False) self.centralwidget.setObjectName("centralwidget") self.painter.fillRect(0, Game.screenHeight - Game.fieldHeight, Game.screenWidth, Game.fieldHeight, Game.fieldColor) self.painter.fillRect(Game.barPosX, Game.barPosY, Game.barWidth, Game.barHeight, Game.fieldColor) self.setCentralWidget(self.centralwidget) self.show() global player1 global player2 player1 = Player((Game.player1limitX[0] + Game.player1limitX[1]) / 2) player2 = Player((Game.player2limitX[0] + Game.player2limitX[1]) / 2) # Main GameLoop Begins Game.turn = Game.Turn.P1 self.startToMove() # Main GameLoop Ends def startToMove(self): Game.action = Game.Action.MOVE stone.gotoP() self.stateMessage = 'Take your position' self.paintField() QTimer.singleShot(2000, self.switchMoveToThrow) if Game.type == Game.Type.P2C and Game.turn == Game.Turn.P1: player2.playerX = random.randint(Game.player2limitX[0], Game.player2limitX[1]) self.paintField() # ----------------------------- # # # # for development purpose # # # # ----------------------------- # # # else: # player1.playerX = random.randint(Game.player1limitX[0], Game.player1limitX[1]) ## # QTimer.singleShot(5, self.switchMoveToThrow) # Till here # def switchMoveToThrow(self): self.stateMessage = 'Aim and Throw' Game.action = Game.Action.SET_ANGLE_FORCE angle_line.gotoStone() self.paintField() if Game.type == Game.Type.P2C and Game.turn == Game.Turn.P2: Game.action = Game.Action.THROW # target = player2.playerX - player1.playerX# - Game.playerHeight / 2 # bar_dist = player2.playerX - Game.barPosX # print(target - bar_dist, bar_dist) # computer_input = [[target, bar_dist]] #to feed the model imageCrop = 300 imageResize = (80, 30) computer_input = qimage2ndarray.byte_view(self.image)[imageCrop:] computer_input = cv2.resize(computer_input, imageResize) # cv2.imshow(' ', computer_input) # cv2.waitKey(0) # cv2.destroyAllWindows() computer_input = computer_input.reshape((1, ) + computer_input.shape) computer_input = computer_input / 255 computer_output = Game.computer.predict(computer_input) angle = computer_output[0][0] velocity = computer_output[0][1] # - 2 # angle_line.current_angle = angle angle_line.current_vel = velocity # print(angle, velocity) self.throw() self.paintField() angle_line.current_vel = Game.defaultForceLen # ----------------------------- # # # # for development purpose # # # # ----------------------------- # # Game.data.append([target, bar_dist, angle, a_velocity]) # Game.dataCount += 1 # # if Game.dataCount >= 100: # x_train = [] # y_train = [] # # for i in Game.data: # x_train.append([i[0], i[2]]) # y_train.append([i[3]]) # # x_train = numpy.array(x_train) # y_train = numpy.array(y_train) # # x_train = tf.keras.utils.normalize(x_train) # y_train = y_train / 110 # # Game.computer_vel.fit(x_train, y_train, epochs=3) # # Game.data = [] # Game.dataCount = 0 # # else: # Game.action = Game.Action.THROW # self.throw() # Till here # def throw(self): prevX = stone.stoneX prevY = stone.stoneY v0 = angle_line.getVel() theta = angle_line.current_angle * math.pi / 180 cos_theta = math.cos(theta) sin_theta = math.sin(theta) g = 9.8 ground = Game.screenHeight - Game.fieldHeight - Game.stoneWidth t = 0 if Game.turn == Game.Turn.P1: player = player1 opponent = player2 else: player = player2 opponent = player1 while stone.stoneY < ground: if Game.state == Game.GameState.PAUSED: QtTest.QTest.qWait(1000) continue x_ = v0 * t * cos_theta y_ = v0 * t * sin_theta - 0.5 * g * t * t # if stone.stoneY >= opponent.playerY: # print('distance travelled = ', x_) stone.stoneX = prevX + x_ stone.stoneY = prevY - y_ if stone.stoneY > ground: stone.stoneY = ground # unsuccessful self.stateMessage = 'Missed...' thread.start_new_thread( self.playMusic, ('res\\Woosh-Mark_DiAngelo-4778593.wav', 'ignore it')) break if stone.stoneX > Game.barPosX - Game.stoneWidth and stone.stoneX < Game.barPosX + Game.barWidth: if stone.stoneY > Game.barPosY - Game.stoneHeight: # unsuccessful self.stateMessage = 'Missed...' thread.start_new_thread( self.playMusic, ('res\\Woosh-Mark_DiAngelo-4778593.wav', 'ignore it')) # # winsound.PlaySound('res\\Woosh-Mark_DiAngelo-4778593.wav', winsound.SND_FILENAME) break if stone.stoneX > opponent.playerX - Game.stoneWidth and stone.stoneX < opponent.playerX + Game.playerWidth: if stone.stoneY > opponent.playerY - Game.stoneHeight: # successful self.stateMessage = 'Hit!!' thread.start_new_thread( self.playMusic, ('res\\Realistic_Punch-Mark_DiAngelo-1609462330.wav', 'ignore it')) # winsound.PlaySound('res\\Realistic_Punch-Mark_DiAngelo-1609462330.wav', winsound.SND_FILENAME) # for not development purpose # player.score += 1 break self.paintField() QtTest.QTest.qWait(50) # ----------------------------- # # # # for development purpose # # # # ----------------------------- # # QtTest.QTest.qWait(1) # Till here # t += 0.3 if player1.score >= Game.gameScore: #player1 wins if Game.type == Game.Type.P2P: self.stateMessage = 'Player 1 wins <br> Press any key to continue' else: self.stateMessage = 'You Win..! <br> Press any key to continue' thread.start_new_thread( self.playMusic, ('res\\Applauding-and-cheering.mp3', 'ignore it')) Game.state = Game.GameState.GAMEOVER elif player2.score >= Game.gameScore: #player2 wins if Game.type == Game.Type.P2P: self.stateMessage = 'Player 2 wins <br> Press any key to continue' thread.start_new_thread( self.playMusic, ('res\\Applauding-and-cheering.mp3', 'ignore it')) else: self.stateMessage = 'You lose..! <br> Press any key to continue' thread.start_new_thread( self.playMusic, ('res\\fail-trombone-01.mp3', 'ignore it')) Game.state = Game.GameState.GAMEOVER else: if Game.turn == Game.Turn.P1: Game.turn = Game.Turn.P2 else: Game.turn = Game.Turn.P1 QTimer.singleShot(500, self.startToMove) # ----------------------------- # # # # for development purpose # # # # ----------------------------- # # QTimer.singleShot(1, self.startToMove) # Till here # def keyPressEvent(self, event): # print(event) if event.key() == Qt.Key_P and Game.state == Game.GameState.PLAY: Game.state = Game.GameState.PAUSED self.prevMessage = self.stateMessage self.stateMessage = 'Paused' self.paintField() elif Game.state == Game.GameState.PAUSED: if event.key() == Qt.Key_P: Game.state = Game.GameState.PLAY self.stateMessage = self.prevMessage self.paintField() elif event.key() == Qt.Key_Escape: QTimer.singleShot(50, self.homeUi) elif Game.state == Game.GameState.PLAY and Game.action != Game.Action.THROW: if Game.turn == Game.Turn.P1: if Game.type == Game.Type.P2P and Game.action == Game.Action.MOVE: if event.key() == Qt.Key_Left and Game.player2limitX[ 0] < player2.playerX: player2.move(-1) elif event.key( ) == Qt.Key_Right and player2.playerX < Game.player2limitX[ 1]: player2.move(1) elif Game.action == Game.Action.SET_ANGLE_FORCE: if event.key() == Qt.Key_W and angle_line.getAngle( ) < Game.player1AngleLimit[1]: angle_line.change(1) elif event.key() == Qt.Key_S and Game.player1AngleLimit[ 0] < angle_line.getAngle(): angle_line.change(-1) elif event.key( ) == Qt.Key_A and angle_line.getVel() > Game.minForceLen: angle_line.changeVel(-1) elif event.key( ) == Qt.Key_D and Game.maxForceLen > angle_line.getVel(): angle_line.changeVel(1) elif event.key() == Qt.Key_Space: Game.action = Game.Action.THROW self.throw() angle_line.current_vel = Game.defaultForceLen else: return else: if Game.action == Game.Action.MOVE: if event.key( ) == Qt.Key_A and Game.player1limitX[0] < player1.playerX: player1.move(-1) elif event.key( ) == Qt.Key_D and player1.playerX < Game.player1limitX[1]: player1.move(1) elif Game.action == Game.Action.SET_ANGLE_FORCE: if event.key() == Qt.Key_Down and angle_line.getAngle( ) < Game.player2AngleLimit[1]: angle_line.change(1) elif event.key() == Qt.Key_Up and Game.player2AngleLimit[ 0] < angle_line.getAngle(): angle_line.change(-1) elif event.key( ) == Qt.Key_Left and Game.maxForceLen > angle_line.getVel( ): angle_line.changeVel(1) elif event.key() == Qt.Key_Right and angle_line.getVel( ) > Game.minForceLen: angle_line.changeVel(-1) elif event.key() == Qt.Key_Space: Game.action = Game.Action.THROW self.throw() angle_line.current_vel = Game.defaultForceLen else: return self.paintField() elif Game.state == Game.GameState.GAMEOVER: QTimer.singleShot(50, self.homeUi) # print(self.position) def removeAllPaint(self): self.painter.fillRect(self.image.rect(), Qt.white) self.update() def paintField(self): self.removeAllPaint() self.painter.fillRect(0, Game.screenHeight - Game.fieldHeight, Game.screenWidth, Game.fieldHeight, Game.fieldColor) self.painter.fillRect(Game.barPosX, Game.barPosY, Game.barWidth, Game.barHeight, Game.fieldColor) self.painter.fillRect(player1.playerX, player1.playerY, Game.playerWidth, Game.playerHeight, Game.playerColor) self.painter.fillRect(player2.playerX, player2.playerY, Game.playerWidth, Game.playerHeight, Game.playerColor) self.painter.fillRect(stone.stoneX, stone.stoneY, Game.stoneWidth, Game.stoneWidth, Game.stoneColor) self.scoreText1 = '<b style="font-size:20px;">Player 1 : ' + str( player1.score) + '<\b>' if Game.type == Game.Type.P2P: self.scoreText2 = '<b style="font-size:20px;">Player 2 : ' + str( player2.score) + '<\b>' else: self.scoreText2 = '<b style="font-size:20px;">Computer : ' + str( player2.score) + '<\b>' self.message = '<b style="font-size:40px;">' + self.stateMessage + '<\b>' text1 = QtGui.QStaticText(self.scoreText1) text1.setTextFormat(Qt.RichText) text2 = QtGui.QStaticText(self.scoreText2) text2.setTextFormat(Qt.RichText) message = QtGui.QStaticText(self.message) message.setTextFormat(Qt.RichText) self.painter.drawStaticText(Game.scoreText1PosX, Game.scoreText1PosY, text1) self.painter.drawStaticText(Game.scoreText2PosX, Game.scoreText2PosY, text2) self.painter.drawStaticText(Game.stateMessageBoxX, Game.stateMessageBoxY, message) if Game.action == Game.Action.SET_ANGLE_FORCE: self.painter.drawLines(angle_line.getLines()) self.update() def paintEvent(self, event): canvas = QPainter(self) if Game.state == Game.GameState.PLAY or Game.state == Game.GameState.GAMEOVER: canvas.drawImage(self.rect(), self.image, self.image.rect()) elif Game.state == Game.GameState.PAUSED: message = '<b style="font-size:40px;">PAUSED<br> Press P to play or Esc to exit<\b>' message = QtGui.QStaticText(message) message.setTextFormat(Qt.RichText) canvas.drawStaticText(Game.stateMessageBoxX, Game.stateMessageBoxY, message) def playMusic(self, file, ignored): playsound(file) def closeEvent(self, event): # QCoreApplication.quit() # ----------------------------- # # # # for development purpose # # # # ----------------------------- # # numpy.save('modelDataReal.npy', Game.data) # Game.computer_vel.save('model6') # till here sys.exit()
class AniState: """Wrapper class around QPainter to ease its usage.""" def __init__(self, widget, frame, time, dt, center=False): self._painter = QPainter(widget) self._painter.setRenderHint(QPainter.Antialiasing, True) if center: self._painter.translate(widget.width() / 2, widget.height() / 2) self.width = widget.width() self.height = widget.height() self.frame = frame self.time = time self.dt = dt def color(self, value): """ Sets the border color. The input value might be ``None`` to use no border, a tuple consisting of (r, g, b, [a]), a string or an integer representing the color, or a QColor/QPen itself. """ width = self._painter.pen().widthF() if value is None: self._painter.setPen(Qt.NoPen) elif isinstance(value, tuple): self._painter.setPen(QPen(QColor(*value), width)) elif isinstance(value, (str, int)): self._painter.setPen(QPen(QColor(value), width)) elif isinstance(value, QColor): self._painter.setPen(QPen(value, width)) elif isinstance(value, QPen): self._painter.setPen(value) return self def fill(self, value): """ Sets the fill color. The input value might be ``None`` to use no fill, a tuple consisting of (r, g, b, [a]), a string or an integer representing the color, or a QColor/QBrush itself. """ if value is None: self._painter.setBrush(Qt.NoBrush) elif isinstance(value, tuple): self._painter.setBrush(QBrush(QColor(*value))) elif isinstance(value, (str, int)): self._painter.setBrush(QBrush(QColor(value))) elif isinstance(value, QColor): self._painter.setBrush(QBrush(value)) elif isinstance(value, QBrush): self._painter.setBrush(value) return self def size(self, size): """ Sets the size for lines and points. """ pen = self._painter.pen() pen.setWidthF(size) self._painter.setPen(pen) return self def line(self, x1, y1, x2=None, y2=None): """ Draws a line between the input positions. If list/tuples are given as the first two arguments, they should consist of two elements representing elements in a position vector. """ if isinstance(x1, (tuple, list)): x2 = y1 x1, y1 = x1 if isinstance(x2, (tuple, list)): x2, y2 = x2 self._painter.drawLine(x1, y1, x2, y2) return self def point(self, x, y=None): """ Draws a single point. If a list/tuple is supplied as the first argument, it should consist of two elements representing elements in a position vector. """ if isinstance(x, (tuple, list)): x, y = x self._painter.drawPoint(x, y) return self def points(self, values): """ Draws a series of points. If the first element of the list of values is a list/tuple, then the following must be the same type. """ assert len(values) % 2 == 0 if isinstance(values[0], (tuple, list)): self._painter.drawPoints(*[QPointF(x, y) for x, y, in values]) else: self._painter.drawPoints(*[QPointF(values[i], values[i + 1]) for i in range(0, len(values), 2)]) def lines(self, values, closed=False): """ Draws a series of connected lines. If the first element of the list of values is a list/tuple, then the following must be the same type. If ``closed``, the first point will be connected to the last. """ assert len(values) > 4 and len(values) % 2 == 0 if isinstance(values[0], (tuple, list)): self._painter.drawLines(*[ QLineF( values[i - 1][0], values[i - 1][1], values[i][0], values[i][0] ) for i in range(0 if closed else 1, len(values)) ]) else: self._painter.drawLines(*[ QLineF( values[i - 2], values[i - 1], values[i], values[i + 1] ) for i in range(0 if closed else 2, len(values), 2) ]) return self def box(self, x, y, width, height): """Draws a box at the given position with the given size.""" self._painter.drawRect(x, y, width, height) def rect(self, x1, y1, x2, y2): """Wrapper around anistate.box(x1, y1, x2 - x1, y2 - y1).""" if x2 < x1: x1, x2 = x2, x1 if y2 < y1: y1, y2 = y2, y1 self._painter.drawRect(x1, y1, x2 - x1, y2 - y1) def circle(self, x, y, radius): """Draws a centered circle at the given position and radius.""" self._painter.drawEllipse(QPointF(x, y), radius, radius) def poly(self, values): """Draws a filled polygon with the shape of the input values.""" assert len(values) % 2 == 0 if isinstance(values[0], (tuple, list)): self._painter.drawPolygon(*[QPointF(x, y) for x, y, in values]) else: self._painter.drawPolygon(*[QPointF(values[i], values[i + 1]) for i in range(0, len(values), 2)]) return self
def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: QWidget=None): fillColor = self.color.darker(150) if (option.state & QStyle.State_Selected) else self.color if option.state & QStyle.State_MouseOver: fillColor = fillColor.lighter(125) lod = option.levelOfDetailFromTransform(painter.worldTransform()) if lod < 0.2: if lod < 0.125: painter.fillRect(QRectF(0, 0, 110, 70), fillColor) return b = painter.brush() painter.setBrush(fillColor) painter.drawRect(13, 13, 97, 57) painter.setBrush(b) return oldPen = painter.pen() pen = oldPen width = 0 if option.state & QStyle.State_Selected: width += 2 pen.setWidth(width) b = painter.brush() f = 120 if option.state & QStyle.State_Sunken else 100 painter.setBrush(QBrush(fillColor.darker(f))) painter.drawRect(QRect(14, 14, 79, 39)) painter.setBrush(b) if lod >= 1: painter.setPen(QPen(Qt.gray, 1)) painter.drawLine(15, 54, 94, 54) painter.drawLine(94, 53, 94, 15) painter.setPen(QPen(Qt.black, 0)) if lod >= 2: font = QFont("Times", 10) font.setStyleStrategy(QFont.ForceOutline) painter.setFont(font) painter.save() painter.scale(0.1, 0.1) painter.drawText(170, 180, "Model: VSC-2000 (Very Small Chip) at {}x{}".format(self.x, self.y)) painter.drawText(170, 200, "Serial number: DLWR-WEER-123L-ZZ33-SDSJ") painter.drawText(170, 220, "Manufacturer: Chip Manufacturer") lines = [] if lod >= 0.5: for i in np.arange(0, 10, 1 if lod > 0.5 else 2): lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)) lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)) for i in np.arange(0, 6, 1 if lod > 0.5 else 2): lines.append(QLineF(5,18 + 5 * i, 13, 18 + 5 * i)) lines.append(QLineF(94, 18 + 5 * i, 102, 18 + 5 * i)) if lod >= 0.4: lineData = [ QLineF(25, 35, 35, 35), QLineF(35, 30, 35, 40), QLineF(35, 30, 45, 35), QLineF(35, 40, 45, 35), QLineF(45, 30, 45, 40), QLineF(45, 35, 55, 35), ] lines.extend(lineData) painter.drawLines(lines) if len(self.stuff) > 1: p = painter.pen() painter.setPen(QPen(Qt.red, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(Qt.NoBrush) path = QPainterPath() path.moveTo(self.stuff[0]) for i in np.arange(len(self.stuff)): path.lineTo(self.stuff[i]) painter.drawPath(path) painter.setPen(p)
class QtRenderer(Renderer): """An implementation of :class:`~renderer.Renderer` for PyQt5. This renderer will draw on any `QPaintDevice` """ def __init__(self, paint_device): """Creates a new renderer based on a QPaintDevice pd""" self._grid_pen = QPen(QColor(0x808080)) self._grid_pen.setStyle(Qt.DashLine) self._painter = None Renderer.__init__(self, paint_device) def set_canvas(self, canvas): """Tell the renderer to draw on canvas The type of canvas is implementation-dependent""" if self._painter is not None: self._painter.restore() self._painter.restore() self._painter.end() self._paintdevice = canvas self._painter = QPainter(canvas) self._painter.setRenderHint(QPainter.Antialiasing) # invert the y axis self._painter.scale(1,-1) self._painter.translate(0,-canvas.height()) Renderer.set_canvas(self,canvas) def _get_canvas_size(self,pd): """Get the canvas size tuple (width,height)""" return (pd.width(), pd.height()) def push_state(self): """Store the current state on the stack. Current state includes default pose, pen and brush""" ### FIXME store things self._painter.save() def pop_state(self): """Restore the last saved state from the stack The state includes default pose, pen and brush""" ### FIXME store things self._painter.restore() def _calculate_bounds(self): transform = self._painter.worldTransform().inverted()[0] xs,ys = zip( transform.map(0.0,0.0), transform.map(0.0,float(self.size[1])), transform.map(float(self.size[0]),float(self.size[1])), transform.map(float(self.size[0]),0.0) ) self._bounds = (min(xs), min(ys), max(xs), max(ys)) def _draw_grid(self): self.reset_pose() self._painter.setPen(self._grid_pen) xmin, ymin, xmax, ymax = self._bounds # Determine min/max x & y line indices: x_ticks = (int(xmin//self._grid_spacing), int(xmax//self._grid_spacing + 1)) y_ticks = (int(ymin//self._grid_spacing), int(ymax//self._grid_spacing + 1)) self._painter.drawLines( [QLineF(xmin, i * self._grid_spacing, xmax, i * self._grid_spacing) for i in range(*y_ticks)]) self._painter.drawLines( [QLineF(i * self._grid_spacing, ymin, i * self._grid_spacing, ymax) for i in range(*x_ticks)]) def scale(self, factor): """Scale drawing operations by factor To be implemented in subclasses.""" self._painter.scale(factor,factor) def rotate(self, angle): """Rotate canvas by angle (in radians) To be implemented in subclasses.""" self._painter.rotate(degrees(angle)) def translate(self, dx, dy): """Translate canvas by dx, dy To be implemented in subclasses.""" self._painter.translate(dx,dy) def clear_screen(self): """Erases the current screen with a white brush""" self._painter.save() self._painter.resetTransform() self.set_pen(0xFFFFFF) self.set_brush(0xFFFFFF) self.draw_rectangle(0,0,self.size[0],self.size[1]) self._painter.restore() Renderer.clear_screen(self) @staticmethod def __qcolor(color): """Returns qcolor for a given ARGB color""" c = QColor(color) if color > 0xFFFFFF: c.setAlpha((color >> 24) & 0xFF) return c def set_pen(self,color=0, thickness=0): """Sets the line color and thickness. Color is interpreted as 0xAARRGGBB.""" if color is None: self._painter.setPen(Qt.NoPen) else: self._painter.setPen(QPen(self.__qcolor(color),thickness)) def set_brush(self,color): """Sets the fill color. Color is interpreted as 0xAARRGGBB.""" if color is None: self._painter.setBrush(Qt.NoBrush) else: self._painter.setBrush(self.__qcolor(color)) def draw_polygon(self,points): """Draws a polygon. Expects a list of points as a list of tuples or as a numpy array.""" self._painter.drawPolygon(QPolygonF([QPointF(*point[:2]) for point in points])) def draw_ellipse(self, cx, cy, ra, rb = None): """Draws an ellipse.""" if rb is None: rb = ra self._painter.drawEllipse(QRectF(cx-ra,cy-ra,2*ra,2*rb)) def draw_rectangle(self, x, y, w, h): """Draws a rectangle.""" self._painter.drawRect(QRectF(x,y,w,h)) def draw_text(self, text, x, y, bgcolor = 0): """Draws a text string at the defined position.""" pass def draw_line(self, x1, y1, x2, y2): """Draws a line using the current pen from (x1,y1) to (x2,y2)""" self._painter.drawLine(QLineF(x1,y1,x2,y2)) def draw_point(self,x,y): """Draw a single point using the current pen at (x,y)""" self._painter.drawPoint(QPointF(x,y)) def draw_points(self,points): """Draw a set of points, given as [(x,y)], using the current pen""" self._painter.drawPoints(QPolygonF([QPointF(x,y) for x,y in points]))
class ImageViewer(QWidget): MousePosChangedSignal = pyqtSignal([QPointF], name='Mouse Pos Changed') ViewPointChangeSignal = pyqtSignal([QPointF, QPointF, float, float], name='View Point Changed') def __init__(self): super(ImageViewer, self).__init__() self.setMouseTracking(True) # moniter = QApplication.desktop().size() moniter = QApplication.primaryScreen().size() self.resize(int(moniter.width() / 1.5), int(moniter.height() / 1.5)) self.initUi() def initUi(self): self.ImagePath = None # 原始图片路径 self.Image = None # 图像 self.cropPolygon = None # 裁剪边框 # private property self.mousePos = QPointF(0, 0) self.mouseLeftButtonDown = False self.scale = 1 # 比例 self.offset = QPointF(0, 0) # 初始坐标 self.backgroundColor = QColor("#898989") # button self.zoomInBtn = QPushButton(QIcon('images/icons/zoom-in.png'), '') self.zoomInBtn.setToolTip('Zoom In') self.zoomInBtn.clicked.connect(self.zoomIn) self.zoomOutBtn = QPushButton(QIcon('images/icons/zoom-out.png'), '') self.zoomOutBtn.setToolTip('Zoom Out') self.zoomOutBtn.clicked.connect(self.zoomOut) self.reloadBtn = QPushButton(QIcon('./images/icons/expand.png'), '') self.reloadBtn.setToolTip('Center') self.reloadBtn.clicked.connect(self.setImageCenter) # layout self.mainLayout = QVBoxLayout() self.mainLayout.addStretch(1) self.toolBox = QHBoxLayout() self.toolBox.addStretch(1) self.toolBox.addWidget(self.zoomInBtn) self.toolBox.addWidget(self.zoomOutBtn) self.toolBox.addWidget(self.reloadBtn) self.mainLayout.addLayout(self.toolBox) self.setLayout(self.mainLayout) def paintEvent(self, event): if self.mouseLeftButtonDown: self.setCursor(Qt.SizeAllCursor) else: self.setCursor(Qt.ArrowCursor) self.backgroundPalette = QPalette() self.backgroundPalette.setColor(self.backgroundRole(), self.backgroundColor) self.setPalette(self.backgroundPalette) self.setAutoFillBackground(True) self.pt = QPainter() if self.Image: renderImage = self.renderImage() scaledImage = renderImage.scaled( int(renderImage.size().width() * self.scale), int(renderImage.size().height() * self.scale)) self.pt.begin(self) self.pt.drawImage(self.offset, scaledImage) self.pt.end() self.draw_axis() def draw_axis(self): # get size of widget width = self.size().width() height = self.size().height() axisLength = 100 axisOriginPoint = QPoint(20, height - 20) PLU = QPoint(0, -10) + axisOriginPoint PL = QPoint(0, 0) + axisOriginPoint PR = QPoint(axisLength, 0) + axisOriginPoint PRU = QPoint(axisLength, -10) + axisOriginPoint textRect = QRect(PL - QPoint(0, 20), PR) self.pt.begin(self) lines = [QLineF(PLU, PL), QLineF(PL, PR), QLineF(PR, PRU)] self.pt.drawLines(lines) self.pt.drawText(textRect, Qt.AlignCenter, str(np.around(axisLength / self.scale, 2)) + 'PX') self.pt.end() def resizeEvent(self, event: QResizeEvent) -> None: pass def wheelEvent(self, event: QWheelEvent) -> None: step = event.angleDelta().y() / 8 / 150 # one step, 0.1 pos = event.position() print('鼠标滚轮滚动, X: %s, Y: %s, Step: %s' % (pos.x(), pos.y(), step)) if step > 0: self.zoomIn(pos=pos, p=abs(step)) else: self.zoomOut(pos=pos, p=abs(step)) def mousePressEvent(self, event: QMouseEvent) -> None: if event.button() == Qt.LeftButton: print('鼠标左键单击: %s, %s' % (event.x(), event.y())) self.mouseLeftButtonDown = True self.mousePos = event.pos() def mouseReleaseEvent(self, event: QMouseEvent) -> None: if event.button() == Qt.LeftButton: print('鼠标左键释放: %s, %s' % (event.x(), event.y())) self.mouseLeftButtonDown = False def mouseMoveEvent(self, event: QMouseEvent) -> None: if self.mouseLeftButtonDown: print('鼠标左键拖移: %s, %s' % (event.x(), event.y())) posDiff = event.pos() - self.mousePos print('移动量: %s, %s' % (posDiff.x(), posDiff.y())) # self.offset = self.offset + posDiff self.setViewPoint(offset=self.offset + posDiff) self.mousePos = event.pos() self.MousePosChangedSignal.emit(self._real2pix(event.pos())) self.update() def keyPressEvent(self, event: QKeyEvent) -> None: pass def _pix2real(self, pos: QPointF): return pos * self.scale + self.offset def _real2pix(self, pos: QPointF): return (pos - self.offset) / self.scale def setImage(self, imagePath=None, image=None): if not os.path.exists(imagePath) and image == None: raise Exception('Error image path.') self.initUi() try: if image and type(image) == QImage: self.Image = image else: self.ImagePath = imagePath self.Image = QImage(self.ImagePath) self.update() except Exception as e: raise e self.setImageCenter() def setImageCenter(self): if not self.Image: return None self.setViewPoint( scale=min(self.size().width() / self.Image.size().width(), self.size().height() / self.Image.size().height())) # self.setScale(min(self.size().width() / self.Image.size().width(), # self.size().height() / self.Image.size().height())) offsetX = (self.size().width() - self.Image.width() * self.scale) / 2 offsetY = (self.size().height() - self.Image.height() * self.scale) / 2 self.setViewPoint(offset=QPointF(offsetX, offsetY)) self.update() def setViewPoint(self, offset=None, scale=None): if not self.Image: return None oldOffset = False oldScale = False if offset and not offset == self.offset: oldOffset = self.offset self.offset = offset if scale and not scale == self.scale: oldScale = self.scale self.scale = scale if oldOffset or oldScale: self.ViewPointChangeSignal.emit( oldOffset if oldOffset else self.offset, self.offset, oldScale if oldScale else self.scale, self.scale) self.update() def zoomIn(self, pos=None, p=0.1): if not self.Image: return None if not pos: pos = QPointF(self.size().width() / 2, self.size().height() / 2) self.setViewPoint(scale=self.scale * (1 + p), offset=self.offset - (pos - self.offset) * p) self.update() def zoomOut(self, pos=None, p=0.1): if not self.Image: return None if not pos: pos = QPointF(self.size().width() / 2, self.size().height() / 2) self.setViewPoint(scale=self.scale * (1 - p), offset=self.offset + (pos - self.offset) * p) self.update() def setCropPolygon(self, polygon: QPolygonF): self.cropPolygon = polygon self.update() def renderImage(self, remove_useless_background=False): if not self.Image: return paintedImage = QImage(self.Image.size(), QImage.Format_ARGB32) paintedImage.fill(Qt.transparent) painter = QPainter(paintedImage) if self.cropPolygon: painterPath = QPainterPath() painterPath.addPolygon(self.cropPolygon) painter.setClipPath(painterPath) painter.drawImage(QPoint(), self.Image) painter.end() if remove_useless_background: return paintedImage.copy(painterPath.boundingRect().toRect()) else: return paintedImage
class GraphicCore(QtWidgets.QWidget): """ main class with UI """ STANDARD_SIZE = 640, 480 OFFSET_MAGNET = 5 def __init__(self, manager: Manager): super().__init__() self.qp = QPainter() self.manager = manager self.setAcceptDrops(True) self.setMouseTracking(True) def __init_ui__(self): self.setWindowTitle("tabula") self.setMinimumSize(640, 480) self.resize(*self.STANDARD_SIZE) self.showMaximized() self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.setObjectName("core") self.setStyleSheet("QWidget#core {background-color: white}") self.setFocus() self.create_settings() self.manager.settings_window.show_sett(self) def create_settings(self): self.manager.settings_window.add_settings(self, SettingsWindow.Title, name="Положение экрана") self.manager.settings_window.add_settings( self, SettingsWindow.SettOneLineEdit, name="Положение центра по горизонтали", standard_values=( self.manager.grid_manager.zero_point_dot.get_pos()[0], ), int_only=True, default_values_to_return=(self.size().width() // 2, ), callback=(self.call_back_zero_pos_width, ), call_update_all=self.call_set_zero_pos_x) self.manager.settings_window.add_settings( self, SettingsWindow.SettOneLineEdit, name="Положение центра по вертикали", standard_values=( self.manager.grid_manager.zero_point_dot.get_pos()[1], ), int_only=True, default_values_to_return=(self.size().height() // 2, ), callback=(self.call_back_zero_pos_height, ), call_update_all=self.call_set_zero_pos_y) self.manager.settings_window.add_settings( self, SettingsWindow.Line, ) self.manager.settings_window.add_settings(self, SettingsWindow.Title, name="Сетка") self.manager.settings_window.add_settings( self, SettingsWindow.SettOneLineEdit, name="Размер сетки", standard_values=(self.manager.grid_manager.grid.get_step(), ), int_only=True, default_values_to_return=( self.manager.grid_manager.grid.get_step(), ), callback=(self.call_back_grid_size, ), call_update_all=self.call_set_grid_size) self.manager.settings_window.add_settings( self, SettingsWindow.SettCheckbox, name="Сетка", standard_values=(("вкл", True), ), default_values_to_return=(True, ), callback=(self.call_back_grid_show, ), call_update_all=self.call_set_grid_show) def call_back_zero_pos_width(self, x: int): """ callback for settings window. This is necessary to move zero point horizontally settings window -> core """ self.manager.grid_manager.zero_point_dot.move_event( x + self.width() // 2, self.manager.grid_manager.zero_point_dot.get_pos()[1]) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.update() def call_back_zero_pos_height(self, y: int): """ callback for settings window. This is necessary to move zero point vertically settings window -> core """ self.manager.grid_manager.zero_point_dot.move_event( self.manager.grid_manager.zero_point_dot.get_pos()[0], y + self.height() // 2) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.update() def call_set_zero_pos(self) -> Tuple[int, int]: """ gives right zero point position to settings window core -> settings window :return: position in tuple format (x, y) """ x_left, y_up = self.manager.grid_manager.zero_point_dot.get_pos() x = x_left - self.width() // 2 y = y_up - self.height() // 2 return x, y def call_set_zero_pos_x(self) -> int: return self.call_set_zero_pos()[0] def call_set_zero_pos_y(self) -> int: return self.call_set_zero_pos()[1] def call_back_grid_show(self, show: bool): """ callback for settings window. This is necessary to change grid showing settings window -> core """ if show and not self.manager.grid_manager.grid.show: self.manager.grid_manager.grid.toggle_show() elif not show and self.manager.grid_manager.grid.show: self.manager.grid_manager.grid.toggle_show() self.update() def call_back_grid_size(self, step: int): """ callback for settings window. This is necessary to change grid size settings window -> core """ self.manager.grid_manager.grid.change_step(step) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.update() def call_set_grid(self) -> Tuple[bool, int]: """ gives grid's showing and step core -> settings window :return: tuple: (show, step) """ return self.manager.grid_manager.grid.show, self.manager.grid_manager.grid.get_step( ) def call_set_grid_show(self) -> int: return self.call_set_grid()[0] def call_set_grid_size(self) -> int: return self.call_set_grid()[1] def resizeEvent(self, event: QtGui.QResizeEvent) -> None: super().resizeEvent(event) self.update() x, y = self.manager.grid_manager.zero_point_dot.get_pos() x -= self.manager.grid_manager.zero_point_dot.get_zero()[0] y -= self.manager.grid_manager.zero_point_dot.get_zero()[1] new_x, new_y = event.size().width() // 2, event.size().height() // 2 [ widget.move_event( widget.x() + new_x - self.manager.grid_manager.zero_point_dot.get_zero()[0], widget.y() + new_y - self.manager.grid_manager.zero_point_dot.get_zero()[1], show_pos=False) for widget in self.manager.widget_manager.get_all_widgets() ] self.manager.grid_manager.set_new_zero_point_pos(new_x, new_y) self.manager.grid_manager.zero_point_dot.move_event( new_x + x, new_y + y) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.generate_grid() self.manager.grid_manager.grid.change_core_size( event.size().width(), event.size().height()) self.manager.settings_window.set_geometry() self.manager.settings_window.update_obj_settings(self) self.update() def self_menu_show(self): """ main context menu """ pos = self.manager.mouse_manager.get_mouse_pos() context_menu = QtWidgets.QMenu() context_menu.addAction( 'Добавить объект', lambda: self.manager.widget_manager.add_widget(pos), shortcut="Ctrl+N") context_menu.setStyleSheet( f"font-size: 15px;" f"border-radius: 5%;" f"border: 1px solid {CONTEXT_MENU_BORDER_COLOR};") context_menu.setWindowFlags(context_menu.windowFlags() | Qt.NoDropShadowWindowHint) context_menu.exec_(QtGui.QCursor.pos()) def arrow_menu_show(self, arrow: Arrow): """ arrow's context menu :param arrow: arrow_class.Arrow class """ context_menu = QtWidgets.QMenu() context_menu.addAction( "Изменить цвет", lambda: self.manager.arrow_manager.change_arrow_color(arrow)) context_menu.addAction( 'Удалить стрелку', lambda: self.manager.arrow_manager.delete_arrow(arrow), shortcut=QtCore.Qt.Key_D) context_menu.setStyleSheet(f"font-size: 15px;" f"border-radius: 5%;" f"border: 1px solid black;") context_menu.exec_(QtGui.QCursor.pos()) def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None: if event.buttons() == QtCore.Qt.LeftButton and self.hasFocus(): x, y = self.manager.mouse_manager.get_mouse_pos() [ widget.move_event(widget.x() + (event.pos().x() - x), widget.y() + (event.pos().y() - y), show_pos=False) for widget in self.manager.widget_manager.get_all_widgets() ] self.manager.grid_manager.zero_point_dot.move_event( self.manager.grid_manager.zero_point_dot.x() + (event.pos().x() - x), self.manager.grid_manager.zero_point_dot.y() + (event.pos().y() - y)) if self.manager.grid_manager.grid.show: self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.manager.settings_window.update_obj_settings(self) self.update() self.manager.mouse_manager.change_mouse_pos(event.x(), event.y()) def keyReleaseEvent(self, event: QtGui.QKeyEvent) -> None: modifier = QtWidgets.QApplication.keyboardModifiers() if modifier == Qt.ControlModifier: if event.key() in (Qt.Key_N, 1058): w = self.manager.widget_manager.add_widget( self.manager.mouse_manager.get_mouse_pos()) self.update() self.manager.widget_manager.clear_focus() w.setFocus() w.show_angles() self.update() widget_has_focus = self.manager.widget_manager.widget_has_focus_or_none( ) if widget_has_focus: widget_has_focus.keyReleaseEvent(event) self.update() if not self.hasFocus(): return if event.key() in (QtCore.Qt.Key_R, 1050): [ widget.return_to_fact_pos() for widget in self.manager.widget_manager.get_all_widgets() ] self.manager.grid_manager.zero_point_dot.return_to_zero() self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() if event.key() in (QtCore.Qt.Key_G, 1055): self.manager.grid_manager.grid.toggle_show() self.manager.settings_window.update_obj_settings(self) if event.key() == QtCore.Qt.Key_Plus: self.manager.grid_manager.grid.change_step( self.manager.grid_manager.grid.get_step() * 2) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.manager.settings_window.update_obj_settings(self) elif event.key() == QtCore.Qt.Key_Minus: self.manager.grid_manager.grid.change_step( self.manager.grid_manager.grid.get_step() // 2) self.manager.grid_manager.grid.set_offset_by_zero_point() self.manager.grid_manager.grid.regenerate_grid() self.manager.settings_window.update_obj_settings(self) self.update() def mouseReleaseEvent(self, event: QtGui.QMouseEvent) -> None: [a.clear_focus() for a in self.manager.arrow_manager.get_all_arrows()] if event.button() == QtCore.Qt.RightButton: if self.manager.arrow_manager.get_active_arrow(): self.manager.arrow_manager.delete_arrow( self.manager.arrow_manager.get_active_arrow()) self.manager.arrow_manager.toggle_active_arrow() return for arrow in self.manager.arrow_manager.get_all_arrows(): if arrow.start_pos and arrow.end_pos: x1, y1 = arrow.start_pos x2, y2 = arrow.end_pos x3, y3 = event.pos().x(), event.pos().y() if -3 < check_on_arrow(x1, y1, x2, y2, x3, y3) < 3: self.arrow_menu_show(arrow) self.update() return if self.hasFocus(): self.self_menu_show() elif event.button() == QtCore.Qt.LeftButton: for arrow in self.manager.arrow_manager.get_all_arrows(): if arrow.start_pos and arrow.end_pos: x1, y1 = arrow.start_pos x2, y2 = arrow.end_pos x3, y3 = event.pos().x(), event.pos().y() if -3 < check_on_arrow(x1, y1, x2, y2, x3, y3) < 3: arrow.set_focus() self.update() return self.manager.settings_window.hide_all_sett() self.manager.settings_window.show_sett(self) self.manager.arrow_manager.clear_focus_arrows() self.manager.widget_manager.clear_focus() self.setFocus() self.update() def dragEnterEvent(self, event: QtGui.QDragEnterEvent) -> None: x, y = event.pos().x() - event.source().pos().x(), event.pos().y( ) - event.source().pos().y() if not self.manager.widget_manager.dragged_obj and \ event.source().size().width() - event.source().OFFSET - 5 \ <= x <= \ event.source().size().width() + 5 and \ event.source().size().height() - event.source().OFFSET - 5 \ <= y <= \ event.source().size().height() + 5: self.manager.widget_manager.set_dor(RESIZE) event.source().show_size_or_pos_label() event.source().show_angles() self.manager.settings_window.hide_all_sett() self.manager.settings_window.show_sett(event.source()) else: if self.manager.widget_manager.dragged_obj is None: self.manager.widget_manager.dragged_obj = event.source() self.manager.widget_manager.set_dor(DRAG) event.source().show_size_or_pos_label() event.source().show_angles() self.manager.widget_manager.drag_dot = (event.pos().x() - event.source().x(), event.pos().y() - event.source().y()) self.manager.settings_window.hide_all_sett() self.manager.settings_window.show_sett(event.source()) event.accept() self.update() def dragMoveEvent(self, event: QtGui.QDragMoveEvent) -> None: obj: TextWidget = event.source() modifier_pressed = QtWidgets.QApplication.keyboardModifiers() shift_pressed = (int(modifier_pressed) & QtCore.Qt.ShiftModifier) == QtCore.Qt.ShiftModifier if self.manager.widget_manager.get_dor() == DRAG: obj.move(event.pos().x() - self.manager.widget_manager.drag_dot[0], event.pos().y() - self.manager.widget_manager.drag_dot[1]) x, y, _, _, x_mod, y_mod, widgets = self.manager.widget_manager.drag_magnet_checker( obj) if shift_pressed: if not x_mod: x = x - (x - self.manager.grid_manager.zero_point_dot.get_pos()[0]) \ % (OFFSET_MAGNET * 2) if not y_mod: y = y - (y - self.manager.grid_manager.zero_point_dot.get_pos()[1]) \ % (OFFSET_MAGNET * 2) x, y = max(x, 0), max(y, 0) if self.manager.grid_manager.grid.show: x, y, widgets = \ self.manager.grid_manager.check_and_set_grid_magnet_lines_for_resizing( obj, x, y, x_mod, y_mod, widgets ) self.manager.widget_manager.set_coords_on_widgets( widgets, event, x, y) obj.move_event(x, y) obj.update_arrows() elif self.manager.widget_manager.get_dor() == RESIZE: obj_x1, obj_y1, obj_x2, obj_y2, x_mod, y_mod, widgets = \ self.manager.widget_manager.resize_magnet_checker(obj, event.pos()) x, y = obj_x2 - obj_x1, obj_y2 - obj_y1 if shift_pressed: if not x_mod: x = max(x - x % (OFFSET_MAGNET * 2), 0) if not y_mod: y = max(y - y % (OFFSET_MAGNET * 2), 0) self.manager.widget_manager.set_coords_on_widgets( widgets, event, x, y) obj.resize_event(x, y) self.update() def dropEvent(self, event: QtGui.QDropEvent) -> None: self.manager.widget_manager.dragged_obj = None self.manager.grid_manager.drop_magnet_lines() self.manager.grid_manager.grid.clear_special_lines() event.accept() self.manager.widget_manager.set_dor(NONE) [ widget.hide_size_or_pos_label() for widget in self.manager.widget_manager.get_all_widgets() ] self.update() def paintEvent(self, event: QtGui.QPaintEvent) -> None: self.qp.begin(self) self.qp.setRenderHint(QPainter.Antialiasing) self.manager.grid_manager.grid.draw(self.qp) for arrow in self.manager.arrow_manager.get_all_arrows(): self.qp.setPen(QPen(QColor(arrow.get_color()), 2)) end = self.manager.mouse_manager.get_mouse_pos() if arrow.draw(self.qp, end_pos=end): self.update() pen = QPen(QColor(MAGNET_LINE_COLOR), 1) pen.setStyle(QtCore.Qt.DashLine) self.qp.setPen(pen) mls = self.manager.grid_manager.get_magnet_lines() if mls: self.qp.drawLines(*mls) self.qp.end()