class Line(Node): def __init__(self, event: dict): super().__init__(event) self._position_end = QPoint(0, 0) @property def x_end(self): return self._position_end.x() @property def y_end(self): return self._position_end.y() @property def position_end(self): return self.x_end, self.y_end def set_position_end(self, x=None, y=None): if x is not None: self._position_end.setX(x) if y is not None: self._position_end.setY(y) def draw(self): super().draw() p = self.painter s = self.scale if s == 1: p.drawLine(self._position, self._position_end) else: points = [self.x * s, self.y * s, self.x_end * s, self.y_end * s] points = [int(i) for i in points] p.drawLine(*points)
def dropEvent(self, event): if event.mimeData().hasText(): mime = event.mimeData() pieces = mime.text().split() position = event.pos() hotSpot = QPoint() hotSpotPos = mime.data('application/x-hotspot').split(' ') if len(hotSpotPos) == 2: hotSpot.setX(hotSpotPos[0].toInt()[0]) hotSpot.setY(hotSpotPos[1].toInt()[0]) for piece in pieces: newLabel = DragLabel(piece, self) newLabel.move(position - hotSpot) newLabel.show() position += QPoint(newLabel.width(), 0) if event.source() in self.children(): event.setDropAction(Qt.MoveAction) event.accept() else: event.acceptProposedAction() else: event.ignore()
def keyPressEvent(self, e: QtGui.QKeyEvent): if not self.m_isEditing: return if e.key() == QtCore.Qt.Key_Delete: self.deleteLater() # Moving container with arrows if QApplication.keyboardModifiers() == QtCore.Qt.ControlModifier: newPos = QPoint(self.x(), self.y()) if e.key() == QtCore.Qt.Key_Up: newPos.setY(newPos.y() - 1) if e.key() == QtCore.Qt.Key_Down: newPos.setY(newPos.y() + 1) if e.key() == QtCore.Qt.Key_Left: newPos.setX(newPos.x() - 1) if e.key() == QtCore.Qt.Key_Right: newPos.setX(newPos.x() + 1) self.move(newPos) if QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier: if e.key() == QtCore.Qt.Key_Up: self.resize(self.width(), self.height() - 1) if e.key() == QtCore.Qt.Key_Down: self.resize(self.width(), self.height() + 1) if e.key() == QtCore.Qt.Key_Left: self.resize(self.width() - 1, self.height()) if e.key() == QtCore.Qt.Key_Right: self.resize(self.width() + 1, self.height()) self.newGeometry.emit(self.geometry())
def mouseDoubleClickEvent(self, a0: QtGui.QMouseEvent) -> None: pos = self.relative_pos() cursor = QCursor() win_pos = self.geometry() centralwidget_pos = self.centralwidget.geometry() showspace_pos = self.showspace.geometry() scrollarea_pos = self.scrollArea.geometry() scrollarea_ab_pos = QPoint() scrollarea_ab_pos.setX(scrollarea_pos.x() + showspace_pos.x() + centralwidget_pos.x() + win_pos.x()) scrollarea_ab_pos.setY(scrollarea_pos.y() + showspace_pos.y() + centralwidget_pos.y() + win_pos.y()) if scrollarea_ab_pos.x() < cursor.pos().x() < ( scrollarea_ab_pos.x() + scrollarea_pos.width() ) and scrollarea_ab_pos.y() < cursor.pos().y() < ( scrollarea_ab_pos.y() + scrollarea_pos.height()): if self.map_type == 'image': self.input_x.setText(str(pos.x())) self.input_y.setText(str(pos.y())) else: row = math.ceil(pos.y() / 14) self.input_y.setText(str(row)) def get_max_char(): len_x = [0 for _ in range(len(self.file))] for i in range(len(self.file)): len_x[i] = len(self.file[i]) len_x.sort() return len_x[len(self.file) - 1] w_col = self.map.width() / (get_max_char()) col = math.ceil(pos.x() / w_col) self.input_x.setText(str(col))
def add_point_by_btn(win): p = QPoint() p.setX(win.x.value()) p.setY(win.y.value()) add_point(p)
def paintEvent(self, event): super(WinMinButton, self).paintEvent(event) if not self.show_foreground: return # 不显示前景 w = self._w h = self._h left = QPoint(self._l + w / 3, self._t + h / 2) right = QPoint(self._l + w * 2 / 3, self._t + h / 2) mid = QPoint(self._l + w / 2 + self.offset_pos.x(), self._t + h / 2 + self.offset_pos.y()) if self.click_ani_appearing or self.click_ani_disappearing: pro = self.click_ani_progress / 800.0 left.setX(left.x() - left.x() * pro) right.setX(right.x() + (w - right.x()) * pro) painter = QPainter(self) path = QPainterPath() path.moveTo(left) path.cubicTo(left, mid, right) painter.setPen(QPen(self.icon_color)) if left.y() != mid.y(): painter.setRenderHint(QPainter.Antialiasing, True) painter.drawPath(path)
def add_point_by_btn(win): x = win.x.value() y = win.y.value() p = QPoint() p.setX(x) p.setY(y) add_point(p)
def slideOverIn(self): if self.isAnimated() and self.isAnimatedForward(): return self.setAnimatedForward() self.m_decorator.grabWidget() startPos = QPoint() finalPos = QPoint() if self.m_direction == AnimationDirection.FromLeftToRight: startPos.setX(-1 * self.stackedWidget().width()) if self.m_direction == AnimationDirection.FromRightToLeft: startPos.setX(self.stackedWidget().width()) if self.m_direction == AnimationDirection.FromTopToBottom: startPos.setY(-1 * self.stackedWidget().height()) if self.m_direction == AnimationDirection.FromBottomToTop: startPos.setY(self.stackedWidget().height()) self.m_decorator.show() self.m_decorator.raise_() if self.m_animation.state() == QPropertyAnimation.Running: self.m_animation.pause() self.m_animation.setDirection(QPropertyAnimation.Backward) self.m_animation.resume() else: self.m_animation.setEasingCurve(QEasingCurve.InOutExpo) self.m_animation.setDirection(QPropertyAnimation.Forward) self.m_animation.setStartValue(startPos) self.m_animation.setEndValue(finalPos) self.m_animation.start()
def placePopUp(): resultado = QPoint(event.x() + 15, event.y() + 15) if event.x() > self.width() - self.popup.width() - 15: resultado.setX(event.x() - self.popup.width() - 15) if event.y() > self.height() - self.popup.height() - 15: resultado.setY(event.y() - self.popup.height() - 15) return resultado
def compute_tag_rects_with_range(self, lt: QPoint, height: int, tags_range: Tuple[int, int]) -> None: for tag_index in range(*tags_range): i_width = self.fontMetrics().horizontalAdvance( self.tags[tag_index].text) i_r = QRectF(lt, QSizeF(i_width, height)) i_r.translate(TAG_TEXT_HORIZONTAL_PADDING, 0) i_r.adjust( -TAG_TEXT_HORIZONTAL_PADDING, 0, TAG_TEXT_HORIZONTAL_PADDING + TAG_CROSS_LEFT_PADDING + TAG_CROSS_RIGHT_PADDING + TAG_CROSS_WIDTH, 0, ) # Check if we overflow and if so, move this tag to the next line in the input field. input_rect = self.input_field_rect() if i_r.topRight().x() >= input_rect.topRight().x(): i_r.setRect(input_rect.x(), i_r.y() + TAG_HEIGHT + TAG_VERTICAL_MARGIN, i_r.width(), i_r.height()) lt.setY(lt.y() + TAG_HEIGHT + TAG_VERTICAL_MARGIN) lt.setX(int(i_r.right() + TAG_HORIZONTAL_MARGIN)) self.tags[tag_index].rect = i_r
class Handle(QObject): handleMoved = pyqtSignal(QPoint) def __init__(self, label, xpos, ypos, radius): super(Handle, self).__init__() self.pos = QPoint(xpos, ypos) self.label = label self.radius = radius def __str__(self): stringval = "%s (%d, %d)" % (self.label, self.pos.x(), self.pos.y()) return stringval def setPos(self, newpos): self.pos.setX(newpos.x()) self.pos.setY(newpos.y()) self.handleMoved.emit(self.pos) def x(self): return self.pos.x() def y(self): return self.pos.y() def bounds(self): return QRect(self.x() - self.radius, self.y() - self.radius, self.radius * 2, self.radius * 2)
def treeContextMenuRequested(self,point): mpoint = QPoint() mpoint.setX(point.x() + 10 + self.tree.x()) mpoint.setY(point.y() + self.menubar.height()) try: if self.tree.currentItem().text(0) == 'Серверы 1С Предприятия': menu = QMenu(self) menu.addAction('Создать подключение к службе RAS...',self.ServerCreate) action = menu.exec_(self.mapToGlobal(mpoint)) except Exception: return try: parent = self.tree.currentItem().parent() except Exception: return if parent == None: return if not self.tree.indexAt(point).isValid(): return parent = self.tree.currentItem().parent() if parent.text(0) == 'Серверы 1С Предприятия': menu = QMenu(self) menu.addAction('Удалить подключение к службе RAS',self.serverDelete) action = menu.exec_(self.mapToGlobal(mpoint)) try: if parent.text(0) == 'Информационные базы': menu = QMenu(self) menu.addAction('Свойства базы...',self.BaseProp) menu.addAction('Удалить базу...',self.BaseDelete) action = menu.exec_(self.mapToGlobal(mpoint)) except Exception: pass try: if self.tree.currentItem().text(0) == 'Информационные базы': menu = QMenu(self) menu.addAction('Создать базу...',self.BaseCreate) action = menu.exec_(self.mapToGlobal(mpoint)) except Exception: return
def convert_to_animal_pos(self, pos): point = QPoint() point.setX(pos.x() - self.width() / 2) point.setY(pos.y() - self.height() / 2 + self.horizontalLayoutWidget.height() - self.SheepLabel.height()) return point
class FrameLabel2(QLabel): onMouseMoveEvent = pyqtSignal() onMouseClickEvent = pyqtSignal() def __init__(self, parent=None): super(FrameLabel2, self).__init__(parent) self.mouseCursorPos = QPoint() self.mouseCursorPos.setX(0) self.mouseCursorPos.setY(0) self.pixmap_points = [] def mouseMoveEvent(self, ev): self.setMouseCursorPos(ev.pos()) self.onMouseMoveEvent.emit() def setMouseCursorPos(self, data): self.mouseCursorPos = data def getMouseCursorPos(self): return self.mouseCursorPos def mousePressEvent(self, ev): self.setMouseCursorPos(ev.pos()) self.onMouseClickEvent.emit() self.draw_something() def draw_something(self): if self.pixmap(): painter = QPainter(self.pixmap()) painter.setPen(QPen(Qt.black, 5, Qt.SolidLine)) painter.setBrush(QBrush(Qt.red, Qt.VerPattern)) points = QPolygon(self.pixmap_points) painter.drawPolygon(points) print(self.pixmap_points)
def re_map_pos(self, pos: QPoint) -> QPoint: """ re map the position of the app, to prevent dragging it to outer space :param pos: a QPoint that app would move to :return: a position that always in window space """ # calculates the screen's width and height and minus that of our floating window width = self.screen_size().width() - self.width() height = self.screen_size().height() - self.height() # map it to global position---the desktop position pos = self.mapToGlobal(pos) # set it back on border if it's out if pos.x() > width: pos.setX(width) elif pos.x() < 0: pos.setX(0) if pos.y() > height: pos.setY(height) elif pos.y() < 0: pos.setY(0) return pos
def __add_point_by_btn(self): x = self.x.value() y = self.y.value() p = QPoint() p.setX(x) p.setY(y) add_point(p)
def add_point_on_click_button(self, win): x = win.x_box.value() y = win.y_box.value() p = QPoint() p.setX(x) p.setY(y) self.add_point_mouse(p)
def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.zcopy = self.pix.pixmap().copy() self.drawing = True point = QPoint() point.setX(event.pos().x() - 10) point.setY(event.pos().y() - 50) self.lastPoint = point
def draw_sheep(self, painter): painter.setPen(self.sheepPen) for s in self.chase.sheep_arr: if s is not None: sheep_pos = QPoint() sheep_pos.setX(s.x) sheep_pos.setY(s.y) painter.drawPoint(self.convert_animal_to_pixmap(sheep_pos))
def tRightContextMenuRequested(self, point): mpoint = QPoint() mpoint.setX(point.x() + self.tRight.x()) mpoint.setY(point.y() + self.menubar.height() + self.tRight.y()) if not self.tRight.indexAt(point).isValid(): return menu = QMenu(self) menu.addAction('Завершить выбранные сеансы', self.closeSessions) action = menu.exec_(self.mapToGlobal(mpoint))
class Frame(QFrame): clicked = pyqtSignal(str) MIN_VALOR = 1 MAX_VALOR = 101 VALOR = MAX_VALOR + MIN_VALOR def __init__(self, parent=None): super(Frame, self).__init__(parent) self.parent = parent self.mover = QPoint() self.habilitado = False def actualizarEstado(self): # Si la posicion x del boton mas la mitad de su ancho # es menor que la mitad del ancho del widget padre, # entonces esta apagado (NO) if (self.parent.button.x() + (self.parent.button.width() / 2)) < Frame.VALOR / 2: self.habilitado = False # Si la posicion x del boton mas la mitad de su ancho # es mayor que la mitad del ancho del widget padre, # entonces esta encendido (SI) if (self.parent.button.x() + (self.parent.button.width() / 2)) > Frame.VALOR / 2: self.habilitado = True if self.habilitado: self.parent.button.setText("SI") color = QColor(206, 61, 59) elif not self.habilitado: self.parent.button.setText("NO") color = QColor(147, 183, 89) colorFrame = self.palette() colorFrame.setColor(QPalette.Background, color) self.setPalette(colorFrame) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.mover.setY(1) if event.pos().x() < Frame.VALOR / 2: self.mover.setX(Frame.MIN_VALOR) elif event.pos().x() > Frame.VALOR / 2: self.mover.setX(Frame.MAX_VALOR - self.parent.button.width()) self.animacion = QPropertyAnimation(self.parent.button, b"pos") self.animacion.setDuration(150) self.animacion.setEndValue(self.mover) self.animacion.valueChanged.connect(self.actualizarEstado) self.animacion.finished.connect(self.emitirEstado) self.animacion.start(QAbstractAnimation.DeleteWhenStopped) def emitirEstado(self): self.clicked.emit(self.parent.button.text())
def paintEvent(self, event): size = self.size() point = QPoint(0, 0) scaledPix = self._renderedPixmap() # start painting the label from left upper corner point.setX((size.width() - scaledPix.width()) / 2) point.setY((size.height() - scaledPix.height()) / 2) QtGui.QPainter(self).drawPixmap(point, scaledPix)
def getFirstColor(self, img: QImage, point: QPoint, x=False, unit=1): color = img.pixelColor(point) while color.alpha() == 0: if x: point.setX(point.x() + unit) else: point.setY(point.y() + unit) color = img.pixelColor(point) return color
def slot_actionRightPassword(self): """在槽内setMenu,然后显示,才可以改变menu菜单的位置。 如果在外面setMenu就不用self.menuKeyBoard.exec()方法了,直接点击就显示了。 """ self.actionRightPassword.setMenu(self.menuKeyBoard) pos = QPoint() pos.setX(93) pos.setY(233) self.menuKeyBoard.exec(self.mapToGlobal(pos))
def force_bounded_pos(self, pos: QtCore.QPoint): if pos.x() < self.img_bounds[0]: pos.setX(self.img_bounds[0]) elif pos.x() > self.img_bounds[2]: pos.setX(self.img_bounds[2]) if pos.y() < self.img_bounds[1]: pos.setY(self.img_bounds[1]) elif pos.y() > self.img_bounds[3]: pos.setY(self.img_bounds[3]) return pos
def placePopUp(frmshow): """ Sets the place of the popup in the windows to avoid getout of the screen frmshow can be a frmShowCasilla or a frmShowFicha """ resultado = QPoint(event.x(), event.y()) if event.x() > self.width() - frmshow.width(): resultado.setX(event.x() - frmshow.width()) if event.y() > self.height() - frmshow.height(): resultado.setY(event.y() - frmshow.height()) return resultado
def mouseMoveEvent(self, event): if (event.buttons() and Qt.LeftButton) and self.drawing: painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) point = QPoint() point.setX(event.pos().x() - 10) point.setY(event.pos().y() - 50) painter.drawLine(self.lastPoint, point) self.lastPoint = point self.pix.setPixmap(QPixmap(self.image))
def _get_relative_pos(self): cursor_pos = QCursor.pos() relative_pos = QPoint() w_size = self.dialog.size() s_size = self.app.primaryScreen().size() x = cursor_pos.x() - ((w_size.width()) / 2) if (x + w_size.width()) > s_size.width(): x = s_size.width() - w_size.width() relative_pos.setX(x) y = self._get_y_pos(cursor_pos, w_size, s_size) relative_pos.setY(y) return relative_pos
def tile_graphs_horizontally(self): if self.UI.mdiArea.subWindowList() is None: return position = QPoint(0,0) for window in self.UI.mdiArea.subWindowList(): rect = QRect(0,0, self.UI.mdiArea.width() / len(self.UI.mdiArea.subWindowList()), self.UI.mdiArea.height()) window.setGeometry(rect) window.move(position) position.setX(position.x() + window.width())
def paintEvent(self, event): if self.pixmap != None and (not self.pixmap.isNull()): size = self.size() painter = QPainter(self) point = QPoint(0,0) scaledPix = self.pixmap.scaled(size, Qt.KeepAspectRatio, transformMode = Qt.SmoothTransformation) if self.scale else self.pixmap point.setX((size.width() - scaledPix.width())/2) point.setY((size.height() - scaledPix.height())/2) painter.drawPixmap(point, scaledPix) super().paintEvent(event)
def draw_item(self, face, painter): is_draw = True if self.is_clipping: is_draw = self.sphere.is_face_visible(face) if is_draw: polygon = QPolygon() for index, point_index in enumerate(face): p1_x = int(self.sphere.geom.points[face[index-1]][0]) p1_y = int(self.sphere.geom.points[face[index-1]][1]) p1_z = int(self.sphere.geom.points[face[index-1]][2]) p2_x = int(self.sphere.geom.points[point_index][0]) p2_y = int(self.sphere.geom.points[point_index][1]) p2_z = int(self.sphere.geom.points[point_index][2]) if self.sphere.projection_name == "front": # Фронтальная проекция (вид спереди) -> z = 0 real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) elif self.sphere.projection_name == "horizontal": # Горизонтальная проекция (вид сверху) -> y = 0 real_p1 = QPoint(p1_x, p1_z) real_p2 = QPoint(p2_x, p2_z) elif self.sphere.projection_name == "profile": # Профильная проекция (вид сбоку) -> x = 0 real_p1 = QPoint(p1_y, p1_z) real_p2 = QPoint(p2_y, p2_z) else: real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) # Точки для проволочного рисования real_p1.setX(self.width()/2 + real_p1.x()) real_p1.setY(self.height()/2 - real_p1.y()) real_p2.setX(self.width()/2 + real_p2.x()) real_p2.setY(self.height()/2 - real_p2.y()) # Полигоны для рисования с цветом polygon.append(real_p1) polygon.append(real_p2) if not self.is_light: painter.drawLine(real_p1, real_p2) if self.is_light: painter.setBrush(self.sphere.get_face_light(face, self.faces_color)) painter.drawPolygon(polygon)
def tryMove(self, oldPos, newPos, directions): p = QPoint(oldPos) if directions & 1: #X轴方向 gridX = self.parent().width() / 40 delta = newPos.x() - oldPos.x() if abs(delta) / gridX > 0.5: newX = oldPos.x() + delta / abs(delta) * gridX * round(abs(delta) / gridX) newX = gridX * round(newX / gridX) p.setX(newX) if directions & 2: gridY = self.parent().height() / 30 delta = newPos.y() - oldPos.y() if abs(delta) / gridY > 0.5: newY = oldPos.y() + delta / abs(delta) * gridY * round(abs(delta) / gridY) newY = gridY * round(newY / gridY) p.setY(newY) return p
def update_me(self): """ Triangle types: :. | .: | ˸˙ | ˙˸ Store vertexes as { most left, most rith, third }; those at the top go first """ self.vertexes = list() most_left = QPoint(self.x, self.y) most_right = QPoint(self.x + self.width, self.y) third = QPoint(self.x, self.y + self.height) form = self.mesh.data['form'] if form == 1: most_left.setY(self.y + self.height) third.setX(self.x + self.width) elif form == 0: most_right.setY(self.y + self.height) elif form == 3: third.setX(self.x + self.width) self.vertexes.append(most_left) self.vertexes.append(most_right) self.vertexes.append(third)
def __limitPointToRect(self, point, rect): """ Private method to limit the given point to the given rectangle. @param point point to be limited (QPoint) @param rect rectangle the point shall be limited to (QRect) @return limited point (QPoint) """ q = QPoint() if point.x() < rect.x(): q.setX(rect.x()) elif point.x() < rect.right(): q.setX(point.x()) else: q.setX(rect.right()) if point.y() < rect.y(): q.setY(rect.y()) elif point.y() < rect.bottom(): q.setY(point.y()) else: q.setY(rect.bottom()) return q
def kineticMove(self, oldx, oldy, newx, newy ): """Start a kinetic move from (oldx, oldy) to (newx, newy)""" if newx == oldx and newy == oldy: return speed = QPoint(0,0) # solve speed*(speed+1)/2 = delta to ensure 1+2+3+...+speed is as close as possible under delta.. speed.setX((sqrt(1+8*abs(newx-oldx))-1)/2) speed.setY((sqrt(1+8*abs(newy-oldy))-1)/2) # compute the amount of displacement still needed because we're dealing with integer values. diff = QPoint(0,0) diff.setX((speed.x() * (speed.x() + 1) // 2) - abs(newx - oldx)) diff.setY((speed.y() * (speed.y() + 1) // 2) - abs(newy - oldy)) # Since this function is called for exact moves (not free scrolling) # limit the kinetic time to 2 seconds, which means 100 ticks, 5050 pixels. if speed.y() > 100: speed.setY(100) diff.setY(-abs(newy-oldy) + 5050) # Although it is less likely to go beyond that limit for horizontal scrolling, # do it for x as well. if speed.x() > 100: speed.setX(100) diff.setX(-abs(newx-oldx) + 5050) # move left or right, up or down if newx > oldx : speed.setX(-speed.x()) diff.setX(-diff.x()) if newy > oldy : speed.setY(-speed.y()) diff.setY(-diff.y()) # move immediately by the step that cannot be handled by kinetic scrolling. # By construction that step is smaller that the initial speed value. self.fastScrollBy(diff) self.kineticStart(speed)
def drawTileLayer(self, painter, layer, exposed = QRectF()): tileWidth = self.map().tileWidth() tileHeight = self.map().tileHeight() if (tileWidth <= 0 or tileHeight <= 1): return rect = exposed.toAlignedRect() if (rect.isNull()): rect = self.boundingRect(layer.bounds()) drawMargins = layer.drawMargins() drawMargins.setTop(drawMargins.top() - tileHeight) drawMargins.setRight(drawMargins.right() - tileWidth) rect.adjust(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()) # Determine the tile and pixel coordinates to start at tilePos = self.screenToTileCoords(rect.x(), rect.y()) rowItr = QPoint( math.floor(tilePos.x()), math.floor(tilePos.y())) startPos = self.tileToScreenCoords_(rowItr) startPos.setX(startPos.x() - tileWidth / 2) startPos.setY(startPos.y() + tileHeight) # Compensate for the layer position rowItr -= QPoint(layer.x(), layer.y()) ## Determine in which half of the tile the top-left corner of the area we # need to draw is. If we're in the upper half, we need to start one row # up due to those tiles being visible as well. How we go up one row # depends on whether we're in the left or right half of the tile. ## inUpperHalf = startPos.y() - rect.y() > tileHeight / 2 inLeftHalf = rect.x() - startPos.x() < tileWidth / 2 if (inUpperHalf): if (inLeftHalf): rowItr.setX(rowItr.x() - 1) startPos.setX(startPos.x() - tileWidth / 2) else: rowItr.setY(rowItr.y() - 1) startPos.setX(startPos.x() + tileWidth / 2) startPos.setY(startPos.y() - tileHeight / 2) # Determine whether the current row is shifted half a tile to the right shifted = inUpperHalf ^ inLeftHalf renderer = CellRenderer(painter) y = startPos.y() * 2 while(y - tileHeight*2 < rect.bottom()*2): columnItr = QPoint(rowItr) x = startPos.x() while(x < rect.right()): if (layer.contains(columnItr)): cell = layer.cellAt(columnItr) if (not cell.isEmpty()): renderer.render(cell, QPointF(x, y/2), QSizeF(0, 0), CellRenderer.BottomLeft) # Advance to the next column columnItr.setX(columnItr.x() + 1) columnItr.setY(columnItr.y() - 1) x += tileWidth # Advance to the next row if (not shifted): rowItr.setX(rowItr.x() + 1) startPos.setX(startPos.x() + tileWidth / 2) shifted = True else: rowItr.setY(rowItr.y() + 1) startPos.setX(startPos.x() - tileWidth / 2) shifted = False y += tileHeight
def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.brush) if self.antialiased: painter.setRenderHint(QPainter.Antialiasing) angle_step = 360 / self.n_states painter.save() #Save_1. Save the state of the system (push matrix) painter.translate(self.dist_center.x(), self.dist_center.y()) # go to the center of the render area painter.rotate(-180) #to start painting from the left side of the circle (clockwise) #center of the circumference where through we are going to paint our states x = self.dist_radius * math.cos(0) y = self.dist_radius * math.sin(0) for h in range(self.n_states): rot = angle_step * h # each state is equidistant from the others. We paint them in circles painter.save() #Save_2 painter.rotate(rot) #now our system is pointing to the next state to be drawn painter.translate(x,y) #now our origin is in the center of the next state to be drawn #if the state is active, fill it green if self.machine.getState(h).isActive(): painter.setBrush(self.greenGradientBrush) painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius) #draw the new state #global position of transformed coordinates (before any transformation, origin at top-left corner) gx = painter.worldTransform().map(QPoint(0,0)).x() gy = painter.worldTransform().map(QPoint(0,0)).y() self.machine.getState(h).setPos(gx, gy) #store the center of the state without any transformation applied # text transformation. Our origin is still in the center of the current state painter.save() #Save_3 painter.rotate(180) #making the text go vertical painter.rotate(-rot) #undoing the rotation made for painting the state. No the text is horizontal font = painter.font(); font.setPixelSize(self.state_radius*.4); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName()); painter.restore() #Restore_3 #end text transformation painter.restore() #Restore_2 painter.restore() #Restore_1. Restore the state of the system (pop matrix) #drawing transitions. Line between states painter.save() # Save_4 pptv = QTransform() #Define a new transformation. Needed to rotate the system along other axis than Z pptv.translate(0, self.height()) #We are now at the bottom-left corner of the screen pptv.rotate(-180, Qt.XAxis) #Rotate along the X-axis so now we are in a typical cartesian system. painter.setTransform(pptv) #Apply the transformation states = self.machine.getStates() for state in states: transitions = state.getTransitions() for transition in transitions: #get the center of the origin and destination states in our current system state orig = QPoint(state.getPos()[0], state.getPos()[1]) end = QPoint(self.machine.getState(transition.getStateEnd()).getPos()[0], self.machine.getState(transition.getStateEnd()).getPos()[1]) # get those coordinates without transformation orig2 = QPoint(painter.worldTransform().map(orig)) end2 = QPoint(painter.worldTransform().map(end)) #get the angle between states centers and the horizon angle = math.atan2(end2.y() - orig2.y(), end2.x() - orig2.x()) #get the coordinates of the starting point of the transition (it starts in the bound of the state, not in the center) newX = self.state_radius * math.cos(angle) + orig2.x() newY = self.state_radius * math.sin(angle) + orig2.y() #now the transition starts at the border, not in the center orig2.setX(newX) orig2.setY(newY) #same for the destination state angle2 = math.atan2(orig2.y() - end2.y(), orig2.x() - end2.x()) newX2 = self.state_radius * math.cos(angle2) + end2.x() newY2 = self.state_radius * math.sin(angle2) + end2.y() end2.setX(newX2) end2.setY(newY2) #draw the line between the origin and destination states painter.drawLine(orig2, end2) #get the start and the end of the transition untransformed init = QPoint(painter.worldTransform().map(orig2)) end = QPoint(painter.worldTransform().map(end2)) #store that info transition.setOrig(init.x(), init.y()) transition.setDest(end.x(), end.y()) transition.setAngle(angle) painter.restore() #Restore_4 #Appliying style to the transitions painter.setPen(QPen(QColor(Qt.gray), 3)) for state in self.machine.getStates(): for transition in state.getTransitions(): #get the start and end coordinates of the transition i = QPoint(transition.getOrig()[0], transition.getOrig()[1]) o = QPoint(transition.getDest()[0], transition.getDest()[1]) painter.drawPolyline(i, o) #Drawing the arrow at the end of the transition painter.save() #Save_5 painter.setPen(QPen(QColor(Qt.gray), 2)) painter.translate(transition.getDest()[0],transition.getDest()[1]) #Go to the end of the transition painter.rotate(90 - transition.getAngle()*180/math.pi) #Rotate to point in the direction of the transition #coordinates of the arrow (triangle) a = QPoint(0,0) b = QPoint(-5,10) c = QPoint(5,10) #coordinates of the arrow untransformed a1 = painter.worldTransform().map(a) b1 = painter.worldTransform().map(b) c1 = painter.worldTransform().map(c) #Drawin the actual arrow pointer = QPolygon([a,b,c]) painter.drawPolygon(pointer) painter.restore() #Restore_5 #For the animation of the transition painter.save() #Save_6 if transition.isActive(): #if the current transition is the active one the wave function will be running, so it's updating the canvas painter.setPen(QPen(QColor(Qt.green), 3)) painter.drawPolyline(i,o) painter.setPen(QPen(QColor(Qt.gray), 3)) painter.drawPolyline(self.poly(self.pts)) #Draw the arrow in the active state (red arrow) painter.setBrush(QBrush(QColor(255, 0, 0))) painter.setPen(QPen(QColor(Qt.red), 2)) pointer = QPolygon([a1,b1,c1]) painter.drawPolygon(pointer) #Ball that follows the line animation for x, y in self.pts: painter.drawEllipse(QRectF(self.pts[0][0] - 4, self.pts[0][1] - 4, 8, 8)) painter.restore() #Restore_6 #Painting the text of the transition painter.save() #Save_7 pptv = QTransform() painter.setPen(QPen(QColor(Qt.black), 3)) #get the middle point of the transition middleX = (transition.getOrig()[0] + transition.getDest()[0]) /2 middleY = (transition.getOrig()[1] + transition.getDest()[1]) /2 pptv.translate(middleX, middleY) #translate to that point painter.setTransform(pptv) #apply the transformation font = painter.font(); font.setPixelSize(self.state_radius*.2); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) name = str(transition.getId())+ '. ' + transition.getName() painter.drawText(rect, Qt.AlignCenter, name) painter.restore() #Restore_7 #paint the actual canvas painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
class Decision(VerticalSymbol): ''' SDL DECISION Symbol ''' _unique_followers = ['Comment'] _insertable_followers = ['DecisionAnswer', 'Task', 'ProcedureCall', 'Output', 'Decision', 'Label'] _terminal_followers = ['Join', 'State', 'ProcedureStop'] common_name = 'decision' # Define reserved keywords for the syntax highlighter blackbold = SDL_BLACKBOLD + ['\\b{}\\b'.format(word) for word in ('AND', 'OR')] redbold = SDL_REDBOLD def __init__(self, parent=None, ast=None): ast = ast or ogAST.Decision() self.ast = ast # Define the point where all branches of the decision can join again self.connectionPoint = QPoint(ast.width / 2, ast.height + 30) super(Decision, self).__init__(parent, text=ast.inputString, x=ast.pos_x or 0, y=ast.pos_y or 0, hyperlink=ast.hyperlink) self.set_shape(ast.width, ast.height) self.setBrush(QColor(255, 255, 202)) self.minDistanceToSymbolAbove = 0 self.parser = ogParser self.text_alignment = Qt.AlignHCenter if ast.comment: Comment(parent=self, ast=ast.comment) @property def terminal_symbol(self): ''' Compute dynamically if the item is terminal by checking if all its branches end with a terminator ''' for branch in self.branches(): if not branch.last_branch_item.terminal_symbol: return False return True @property def completion_list(self): ''' Set auto-completion list ''' return chain(variables_autocompletion(self), ('length', 'present')) def branches(self): ''' Return the list of decision answers (as a generator) ''' return (branch for branch in self.childSymbols() if isinstance(branch, DecisionAnswer)) def set_shape(self, width, height): ''' Define polygon points to draw the symbol ''' path = QPainterPath() path.moveTo(width / 2, 0) path.lineTo(width, height / 2) path.lineTo(width / 2, height) path.lineTo(0, height / 2) path.lineTo(width / 2, 0) self.setPath(path) super(Decision, self).set_shape(width, height) def resize_item(self, rect): ''' On resize event, make sure connection points are updated ''' delta_y = self.boundingRect().height() - rect.height() super(Decision, self).resize_item(rect) self.connectionPoint.setX(self.boundingRect().center().x()) self.connectionPoint.setY(self.connectionPoint.y() - delta_y) self.update_connections() def update_connections(self): ''' Redefined - update arrows shape below connection point ''' super(Decision, self).update_connections() for branch in self.branches(): for cnx in branch.last_branch_item.connections(): cnx.reshape() def updateConnectionPointPosition(self): ''' Compute the joining point of decision branches ''' new_y = 0 new_x = self.boundingRect().width() / 2.0 answers = False for branch in self.branches(): answers = True last_cnx = None last = branch.last_branch_item try: # To compute the branch length, we must keep only the symbols, # so we must remove the last connection (if any) last_cnx, = (c for c in last.childItems() if isinstance(c, Connection) and not isinstance(c.child, (Comment, HorizontalSymbol))) # Don't set parent item to None to avoid Qt segfault last_cnx.setParentItem(self) except ValueError: pass branch_len = branch.y() + ( branch.boundingRect() | branch.childrenBoundingRect()).height() try: last_cnx.setParentItem(last) except AttributeError: pass # If last item was a decision, use its connection point # position to get the length of the branch: try: branch_len = (last.connectionPoint.y() + self.mapFromScene(0, last.scenePos().y()).y()) except AttributeError: pass # Rounded with int() -> mandatory when view scale has changed new_y = int(max(new_y, branch_len)) if not answers: new_y = int(self.boundingRect().height()) new_y += 15 delta = new_y - self.connectionPoint.y() self.connectionPoint.setY(new_y) self.connectionPoint.setX(new_x) if delta != 0: child = self.next_aligned_symbol() try: child.pos_y += delta except AttributeError: pass self.update_connections()
def drawGrid(self, painter, exposed, gridColor): rect = exposed.toAlignedRect() if (rect.isNull()): return p = RenderParams(self.map()) # Determine the tile and pixel coordinates to start at startTile = self.screenToTileCoords_(rect.topLeft()).toPoint() startPos = self.tileToScreenCoords_(startTile).toPoint() ## Determine in which half of the tile the top-left corner of the area we # need to draw is. If we're in the upper half, we need to start one row # up due to those tiles being visible as well. How we go up one row # depends on whether we're in the left or right half of the tile. ## inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX if (inUpperHalf): startTile.setY(startTile.y() - 1) if (inLeftHalf): startTile.setX(startTile.x() - 1) startTile.setX(max(0, startTile.x())) startTile.setY(max(0, startTile.y())) startPos = self.tileToScreenCoords_(startTile).toPoint() oct = [ QPoint(0, p.tileHeight - p.sideOffsetY), QPoint(0, p.sideOffsetY), QPoint(p.sideOffsetX, 0), QPoint(p.tileWidth - p.sideOffsetX, 0), QPoint(p.tileWidth, p.sideOffsetY), QPoint(p.tileWidth, p.tileHeight - p.sideOffsetY), QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight), QPoint(p.sideOffsetX, p.tileHeight)] lines = QVector() #lines.reserve(8) gridColor.setAlpha(128) gridPen = QPen(gridColor) gridPen.setCosmetic(True) _x = QVector() _x.append(2) _x.append(2) gridPen.setDashPattern(_x) painter.setPen(gridPen) if (p.staggerX): # Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerX(startTile.x())): startPos.setY(startPos.y() - p.rowHeight) while(startPos.x() <= rect.right() and startTile.x() < self.map().width()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) if (p.doStaggerX(startTile.x())): rowPos.setY(rowPos.y() + p.rowHeight) while(rowPos.y() <= rect.bottom() and rowTile.y() < self.map().height()): lines.append(QLineF(rowPos + oct[1], rowPos + oct[2])) lines.append(QLineF(rowPos + oct[2], rowPos + oct[3])) lines.append(QLineF(rowPos + oct[3], rowPos + oct[4])) isStaggered = p.doStaggerX(startTile.x()) lastRow = rowTile.y() == self.map().height() - 1 lastColumn = rowTile.x() == self.map().width() - 1 bottomLeft = rowTile.x() == 0 or (lastRow and isStaggered) bottomRight = lastColumn or (lastRow and isStaggered) if (bottomRight): lines.append(QLineF(rowPos + oct[5], rowPos + oct[6])) if (lastRow): lines.append(QLineF(rowPos + oct[6], rowPos + oct[7])) if (bottomLeft): lines.append(QLineF(rowPos + oct[7], rowPos + oct[0])) painter.drawLines(lines) lines.resize(0) rowPos.setY(rowPos.y() + p.tileHeight + p.sideLengthY) rowTile.setY(rowTile.y() + 1) startPos.setX(startPos.x() + p.columnWidth) startTile.setX(startTile.x() + 1) else: # Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerY(startTile.y())): startPos.setX(startPos.x() - p.columnWidth) while(startPos.y() <= rect.bottom() and startTile.y() < self.map().height()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) if (p.doStaggerY(startTile.y())): rowPos.setX(rowPos.x() + p.columnWidth) while(rowPos.x() <= rect.right() and rowTile.x() < self.map().width()): lines.append(QLineF(rowPos + oct[0], rowPos + oct[1])) lines.append(QLineF(rowPos + oct[1], rowPos + oct[2])) lines.append(QLineF(rowPos + oct[3], rowPos + oct[4])) isStaggered = p.doStaggerY(startTile.y()) lastRow = rowTile.y() == self.map().height() - 1 lastColumn = rowTile.x() == self.map().width() - 1 bottomLeft = lastRow or (rowTile.x() == 0 and not isStaggered) bottomRight = lastRow or (lastColumn and isStaggered) if (lastColumn): lines.append(QLineF(rowPos + oct[4], rowPos + oct[5])) if (bottomRight): lines.append(QLineF(rowPos + oct[5], rowPos + oct[6])) if (bottomLeft): lines.append(QLineF(rowPos + oct[7], rowPos + oct[0])) painter.drawLines(lines) lines.resize(0) rowPos.setX(rowPos.x() + p.tileWidth + p.sideLengthX) rowTile.setX(rowTile.x() + 1) startPos.setY(startPos.y() + p.rowHeight) startTile.setY(startTile.y() + 1)
class ScreenShot(QMainWindow): def __init__(self): super().__init__() #Window settings self.availableGeometry = app.desktop().availableGeometry() self.screenGeometry = QDesktopWidget().screenGeometry(-1) self.left = 0 self.top = 0 self.minWidth = 0 self.minHeight = 0 self.maxWidth = self.availableGeometry.width() self.maxHeight = self.availableGeometry.height() self.width = self.maxWidth self.height = self.maxHeight self.opacity = 0.3 self.color = QColor(255,255,255) #Set RGB colours later self.taking_screenshot = False #Boolean. Set to True when screenshot process is occuring self.statusText = "X1: {} Y1: {} | X2: {} Y2: {} | Width: {} Height: {}" #Step Multipliers self.stepMultiplier = 10 self.stepBigMultipler = 10 self.stepSize = 1 #number of pixels to move the window by #Mouse cursor self.begin = QPoint(0,0) self.end = QPoint(0,0) self.x_compensate = self.availableGeometry.x() - self.screenGeometry.x() self.y_compensate = self.availableGeometry.y() - self.screenGeometry.y() self.begin_x_definitive = None self.begin_y_definitive = None self.end_x_definitive = None self.end_y_definitive = None self.screenshot_width = None self.screenshot_height = None self.initUI() def initUI(self): self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowOpacity(self.opacity) self.setAutoFillBackground(True) #Window Color p = self.palette() p.setColor(self.backgroundRole(), self.color) self.setPalette(p) #Status Bar Color p = self.statusBar().palette() p.setColor(self.backgroundRole(), Qt.white) self.statusBar().setAutoFillBackground(True) self.statusBar().setPalette(p) #Image Previewer self.imagePreviewer = ImagePreviewer(self) self.imagePreviewer.setWindowTitle("Screenshot preview") self.imagePreviewer.hide() self.show() def paintEvent(self, event): qp = QPainter(self) if self.taking_screenshot: br = QBrush(QColor(125, 120, 100, 100)) else: br = QBrush(QColor(255, 15, 123, 40)) qp.setBrush(br) qp.begin(self) qp.drawRect(QRect(self.begin, self.end)) qp.end() self.statusBar().clearMessage() self.statusBar().showMessage(self.statusText.format(self.begin_x_definitive,self.begin_y_definitive,self.end_x_definitive, self.end_y_definitive,self.screenshot_width,self.screenshot_height)) self.statusBar().update() def resizeEvent(self, event): self.width = event.size().width() self.height = event.size().height() self.update() def mousePressEvent(self, event): self.begin = event.pos() self.update() def mouseMoveEvent(self, event): self.end = event.pos() self.update() def mouseReleaseEvent(self, event): self.end = event.pos() #Top Left self.begin_x_definitive = min(self.begin.x(), self.end.x()) self.begin_y_definitive = min(self.begin.y(), self.end.y()) #Bottom Right self.end_x_definitive = max(self.begin.x(), self.end.x()) self.end_y_definitive = max(self.begin.y(), self.end.y()) #This ensures that no matter in which direction the user drags the screenshot box, self.begin always refers to the top left hand corner while self.end always refers to the bottom right hand corner self.begin = QPoint(self.begin_x_definitive, self.begin_y_definitive) self.end = QPoint(self.end_x_definitive, self.end_y_definitive) #Update screenshot width and height self.screenshot_width = self.end.x() - self.begin.x() self.screenshot_height = self.end.y() - self.begin.y() self.update() def keyPressEvent(self, event): modifier = QApplication.keyboardModifiers() key = event.key() stepSize = self.stepSize stepSize *= self.stepBigMultipler if (modifier & Qt.ShiftModifier) else 1 stepSize *= self.stepMultiplier if (modifier & Qt.ControlModifier) else 1 #Resize end point height and width (mouseReleaseEvent) if key == Qt.Key_Left: self.resize_end_point(-stepSize, 0) if key == Qt.Key_Right: self.resize_end_point(stepSize, 0) if key == Qt.Key_Up: self.resize_end_point(0, -stepSize) if key == Qt.Key_Down: self.resize_end_point(0, stepSize) ##Resize begin point height and width (mousePressEvent) if key == Qt.Key_A: self.resize_start_point(-stepSize, 0) if key == Qt.Key_D: self.resize_start_point(stepSize, 0) if key == Qt.Key_W: self.resize_start_point(0, -stepSize) if key == Qt.Key_S: self.resize_start_point(0, stepSize) #Screenshot Functions/Miscellaneous if key == Qt.Key_Space: self.take_screenshot() if key == Qt.Key_Z: self.save_screenshot() if key == Qt.Key_C: self.change_transparent() self.clear_screenshot() if key == Qt.Key_Q: self.close() def resize_start_point(self, inc_x, inc_y): #Top left new_x = self.begin.x() + inc_x new_y = self.begin.y() + inc_y if new_x < 0: new_x = 0 if new_y < 0: new_y = 0 self.begin.setX(new_x) self.begin.setY(new_y) self.screenshot_width = self.end.x() - self.begin.x() self.screenshot_height = self.end.y() - self.begin.y() self.update() def resize_end_point(self, inc_x, inc_y): #Bottom right new_x = self.end.x() + inc_x new_y = self.end.y() + inc_y if new_x > self.maxWidth: new_x = self.maxWidth if new_y > self.maxHeight: new_y = self.maxHeight self.end.setX(new_x) self.end.setY(new_y) self.screenshot_width = self.end.x() - self.begin.x() self.screenshot_height = self.end.y() - self.begin.y() self.update() def clear_screenshot(self): self.imagePreviewer.hide() self.pixmap = None def take_screenshot(self): screen = app.primaryScreen() self.hide() #If not screenshot window is set, the program defaults to taking a screenshot of the entire window if any(i == None for i in [self.begin.x(), self.begin.y(), self.screenshot_height, self.screenshot_width]): self.pixmap = screen.grabWindow(MainWindow.id, 0, 0, self.maxWidth, self.maxHeight) else: self.pixmap = screen.grabWindow(MainWindow.id, self.begin.x(), self.begin.y()+2*self.y_compensate, self.screenshot_width, self.screenshot_height) self.imagePreviewer.setPixmap(self.pixmap) self.imagePreviewer.adjustSize() self.imagePreviewer.resize(self.imagePreviewer.sizeHint()) self.imagePreviewer.show() self.activateWindow() self.done = True def save_screenshot(self): if self.done: filename = QFileDialog.getSaveFileName(self, "Save As", QDir.currentPath(), "PNG Files (*.png)") if filename: self.pixmap.save(filename[0], "png") self.imagePreviewer.hide() else: take_screenshot() save_screenshot() self.done = False def change_transparent(self): self.taking_screenshot = not self.taking_screenshot if self.taking_screenshot: self.opacity = 0 self.initUI() self.update() else: self.opacity = 0.3 self.initUI() self.update()
def drawTileLayer(self, painter, layer, exposed = QRectF()): p = RenderParams(self.map()) rect = exposed.toAlignedRect() if (rect.isNull()): rect = self.boundingRect(layer.bounds()) drawMargins = layer.drawMargins() drawMargins.setBottom(drawMargins.bottom() + p.tileHeight) drawMargins.setRight(drawMargins.right() - p.tileWidth) rect.adjust(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()) # Determine the tile and pixel coordinates to start at startTile = self.screenToTileCoords_(rect.topLeft()).toPoint() # Compensate for the layer position startTile -= layer.position() startPos = self.tileToScreenCoords_(startTile + layer.position()) ## Determine in which half of the tile the top-left corner of the area we # need to draw is. If we're in the upper half, we need to start one row # up due to those tiles being visible as well. How we go up one row # depends on whether we're in the left or right half of the tile. ## inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX if (inUpperHalf): startTile.setY(startTile.y() - 1) if (inLeftHalf): startTile.setX(startTile.x() - 1) renderer = CellRenderer(painter) if (p.staggerX): startTile.setX(max(-1, startTile.x())) startTile.setY(max(-1, startTile.y())) startPos = self.tileToScreenCoords_(startTile + layer.position()).toPoint() startPos.setY(startPos.y() + p.tileHeight) staggeredRow = p.doStaggerX(startTile.x() + layer.x()) while(startPos.y() < rect.bottom() and startTile.y() < layer.height()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) while(rowPos.x() < rect.right() and rowTile.x() < layer.width()): if (layer.contains(rowTile)): cell = layer.cellAt(rowTile) if (not cell.isEmpty()): renderer.render(cell, rowPos, QSizeF(0, 0), CellRenderer.BottomLeft) rowPos.setX(rowPos.x() + p.tileWidth + p.sideLengthX) rowTile.setX(rowTile.x() + 2) if (staggeredRow): startTile.setX(startTile.x() - 1) startTile.setY(startTile.y() + 1) startPos.setX(startPos.x() - p.columnWidth) staggeredRow = False else: startTile.setX(startTile.x() + 1) startPos.setX(startPos.x() + p.columnWidth) staggeredRow = True startPos.setY(startPos.y() + p.rowHeight) else: startTile.setX(max(0, startTile.x())) startTile.setY(max(0, startTile.y())) startPos = self.tileToScreenCoords_(startTile + layer.position()).toPoint() startPos.setY(startPos.y() + p.tileHeight) # Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerY(startTile.y() + layer.y())): startPos.setX(startPos.x() - p.columnWidth) while(startPos.y() < rect.bottom() and startTile.y() < layer.height()): rowTile = QPoint(startTile) rowPos = QPoint(startPos) if (p.doStaggerY(startTile.y() + layer.y())): rowPos.setX(rowPos.x() + p.columnWidth) while(rowPos.x() < rect.right() and rowTile.x() < layer.width()): cell = layer.cellAt(rowTile) if (not cell.isEmpty()): renderer.render(cell, rowPos, QSizeF(0, 0), CellRenderer.BottomLeft) rowPos.setX(rowPos.x() + p.tileWidth + p.sideLengthX) rowTile.setX(rowTile.x() + 1) startPos.setY(startPos.y() + p.rowHeight) startTile.setY(startTile.y() + 1)
def paintEvent(self, event): rect = QRect(10, 20, 80, 60) path = QPainterPath() path.moveTo(20, 80) path.lineTo(20, 30) path.cubicTo(80, 0, 50, 50, 80, 80) startAngle = 30 * 16 arcLength = 120 * 16 painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.brush) if self.antialiased: painter.setRenderHint(QPainter.Antialiasing) angle_step = 360 / self.n_states painter.save() painter.translate(self.dist_center.x(), self.dist_center.y()) #painter.drawRect(- self.dist_radius, - self.dist_radius, self.dist_radius *2,self.dist_radius*2) #painter.drawEllipse(QPoint(0, 0), self.dist_radius , self.dist_radius) painter.rotate(-180) #to start painting from the left side of the circle x = self.dist_radius * math.cos(0) y = self.dist_radius * math.sin(0) for h in range(self.n_states): rot = angle_step * h painter.save() painter.rotate(rot) painter.translate(x,y) if self.machine.getState(h).isActive(): painter.setBrush(self.greenGradientBrush) painter.drawEllipse(QPoint(0,0), self.state_radius, self.state_radius) #global position of transformed coordinates gx = painter.worldTransform().map(QPoint(0,0)).x() gy = painter.worldTransform().map(QPoint(0,0)).y() self.machine.getState(h).setPos(gx, gy) # text transformation painter.save() painter.rotate(180) painter.rotate(-rot) font = painter.font(); font.setPixelSize(self.state_radius*.4); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) painter.drawText(rect, Qt.AlignCenter, self.machine.getState(h).getName()); painter.restore() #end text transformation painter.restore() painter.restore() #drawing transitions. painter.save() pptv = QTransform() pptv.translate(0, self.height()) pptv.rotate(-180, Qt.XAxis) painter.setTransform(pptv) s = self.machine.getStates() for j in s: t = j.getTransitions() for i in t: #get the points in the canvas init = QPoint(j.getPos()[0], j.getPos()[1]) end = QPoint(self.machine.getState(i.getStateEnd()).getPos()[0], self.machine.getState(i.getStateEnd()).getPos()[1]) # get the transformed ponts init2 = QPoint(painter.worldTransform().map(init)) end2 = QPoint(painter.worldTransform().map(end)) #get the angle between states centers angle = math.atan2(end2.y() - init2.y(), end2.x() - init2.x()) #get the coordinates of the starting point of the transition (it starts in the bound, not in the center) newX = self.state_radius * math.cos(angle) + init2.x() newY = self.state_radius * math.sin(angle) + init2.y() init2.setX(newX) init2.setY(newY) #same for the end of the transition angle2 = math.atan2(init2.y() - end2.y(), init2.x() - end2.x()) newX2 = self.state_radius * math.cos(angle2) + end2.x() newY2 = self.state_radius * math.sin(angle2) + end2.y() end2.setX(newX2) end2.setY(newY2) #painter.drawLine(init, end) painter.drawLine(init2, end2) init = QPoint(painter.worldTransform().map(init2)) end = QPoint(painter.worldTransform().map(end2)) i.setOrig(init.x(), init.y()) i.setDest(end.x(), end.y()) i.setAngle(angle) #painter.draw painter.restore() painter.setPen(QPen(QColor(Qt.gray), 3)) for i in machine.getStates(): for j in i.getTransitions(): i = QPoint(j.getOrig()[0], j.getOrig()[1]) o = QPoint(j.getDest()[0], j.getDest()[1]) painter.drawPolyline(i, o) painter.save() painter.setPen(QPen(QColor(Qt.gray), 2)) painter.translate(j.getDest()[0],j.getDest()[1]) painter.rotate(90 - j.getAngle()*180/math.pi) a = QPoint(0,0) b = QPoint(-5,10) c = QPoint(5,10) a1 = painter.worldTransform().map(a) b1 = painter.worldTransform().map(b) c1 = painter.worldTransform().map(c) pointer = QPolygon([a,b,c]) painter.drawPolygon(pointer) painter.restore() painter.save() if j.isActive(): t = self.machine.getTransition(self.t_active) init = QPoint(t.getOrig()[0], t.getOrig()[1]) end = QPoint(t.getDest()[0], t.getDest()[1]) painter.setPen(QPen(QColor(Qt.green), 3)) painter.drawPolyline(init, end) painter.setPen(QPen(QColor(Qt.gray), 3)) painter.drawPolyline(self.poly(self.pts)) painter.setBrush(QBrush(QColor(255, 0, 0))) painter.setPen(QPen(QColor(Qt.red), 2)) pointer = QPolygon([a1,b1,c1]) painter.drawPolygon(pointer) painter.setBrush(QBrush(QColor(255, 0, 0))) painter.setPen(QPen(QColor(Qt.black), 1)) painter.restore() #Ball that follows the line #for x, y in self.pts: #painter.drawEllipse(QRectF(x - 4, y - 4, 8, 8)) painter.save() pptv = QTransform() painter.setPen(QPen(QColor(Qt.black), 3)) middleX = (j.getOrig()[0] + j.getDest()[0]) /2 middleY = (j.getOrig()[1] + j.getDest()[1]) /2 pptv.translate(middleX, middleY) #pptv.rotate(-j.getAngle()*180/math.pi) painter.setTransform(pptv) font = painter.font(); font.setPixelSize(self.state_radius*.3); painter.setFont(font); rect = QRect(-self.state_radius, -self.state_radius, self.state_radius*2, self.state_radius*2) name = str(j.getId())+ '. ' + j.getName() painter.drawText(rect, Qt.AlignCenter, name) painter.restore() painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
def draw_rect_mesh(self, canvas, grid_x, grid_y, grid_width, grid_height): """ Draw rectangular region of mesh. First divide to squares, then draw diagonal and transform them to triangles 'grid_*' arguments is numbers of nodes of the mesh """ x0 = self.pixel_x(grid_x) y0 = self.pixel_y(grid_y) xn = self.pixel_x(grid_x + grid_width) yn = self.pixel_y(grid_y + grid_height) # Horizontal & diagonal lines A = QPoint(x0, y0) B = QPoint(xn, y0) canvas.drawLine(A, B) # first line for j in range(1, grid_height+1): y = self.pixel_y(grid_y+j) A.setY(y) B.setY(y) canvas.drawLine(A, B) # Vertical lines A.setX(x0) B.setX(x0) A.setY(y0) B.setY(yn) canvas.drawLine(A, B) for i in range(1, grid_width+1): x = self.pixel_x(grid_x+i) A.setX(x) B.setX(x) canvas.drawLine(A, B) # Diagonal lines A.setX(x0) A.setY(y0) B.setX(self.pixel_x(grid_x + 1)) # Diagonal B.setY(self.pixel_y(grid_y + 1)) for j in range(1, grid_height+1): for i in range(1, grid_width+1): canvas.drawLine(A, B) A.setX(self.pixel_x(grid_x + i)) B.setX(self.pixel_x(grid_x + i + 1)) A.setX(x0) A.setY(self.pixel_y(grid_y + j)) B.setX(self.pixel_x(grid_x + 1)) B.setY(self.pixel_y(grid_y + j + 1))
def screenToTileCoords(self, x, y): p = RenderParams(self.map()) if (p.staggerX): if p.staggerEven: x -= p.tileWidth else: x -= p.sideOffsetX else: if p.staggerEven: y -= p.tileHeight else: y -= p.sideOffsetY # Start with the coordinates of a grid-aligned tile lenx = p.tileWidth + p.sideLengthX leny = p.tileHeight + p.sideLengthY referencePoint = QPoint(math.floor(x / lenx), math.floor(y / leny)) # Relative x and y position on the base square of the grid-aligned tile rel = QVector2D(x - referencePoint.x() * lenx, y - referencePoint.y() * leny) # Adjust the reference point to the correct tile coordinates if p.staggerX: staggerAxisIndex = referencePoint.x() else: staggerAxisIndex = referencePoint.y() staggerAxisIndex *= 2 if (p.staggerEven): staggerAxisIndex += 1 if p.staggerX: referencePoint.setX(staggerAxisIndex) else: referencePoint.setY(staggerAxisIndex) # Determine the nearest hexagon tile by the distance to the center centers = [0, 0, 0, 0] if (p.staggerX): left = int(p.sideLengthX / 2) centerX = left + p.columnWidth centerY = int(p.tileHeight / 2) centers[0] = QVector2D(left, centerY) centers[1] = QVector2D(centerX, centerY - p.rowHeight) centers[2] = QVector2D(centerX, centerY + p.rowHeight) centers[3] = QVector2D(centerX + p.columnWidth, centerY) else: top = int(p.sideLengthY / 2) centerX = int(p.tileWidth / 2) centerY = top + p.rowHeight centers[0] = QVector2D(centerX, top) centers[1] = QVector2D(centerX - p.columnWidth, centerY) centers[2] = QVector2D(centerX + p.columnWidth, centerY) centers[3] = QVector2D(centerX, centerY + p.rowHeight) nearest = 0 minDist = 1.7976931348623157e+308 for i in range(4): center = centers[i] dc = (center - rel).lengthSquared() if (dc < minDist): minDist = dc nearest = i offsetsStaggerX = [ QPoint( 0, 0), QPoint(+1, -1), QPoint(+1, 0), QPoint(+2, 0), ] offsetsStaggerY = [ QPoint( 0, 0), QPoint(-1, +1), QPoint( 0, +1), QPoint( 0, +2), ] if p.staggerX: offsets = offsetsStaggerX else: offsets = offsetsStaggerY return QPointF(referencePoint + offsets[nearest])
def draw_mesh(self, canvas): """ Split rectangle to smaller rectangles step_x*step_y, then for each draw diagonal """ M = self.mesh X1 = M.NAL # start of figure Y1 = M.NAT # start of figure X2 = M.NAL + M.NFX # start of right air layer Y2 = M.NAT + M.NFY # start of bottom air layer X_NLEN = X2 + M.NAR Y_NLEN = Y2 + M.NAB A = QPoint() B = QPoint() # Horizontal lines (3 segments: air, figure, air) x0 = self.pixel_x(0) x1 = self.pixel_x(X1) x2 = self.pixel_x(X2) x3 = self.pixel_x(X_NLEN) for j in range(Y_NLEN+1): # +1 because N segments defined by N+1 dots y = self.pixel_y(j) A.setY(y) B.setY(y) B.setX(x0) for xi in (x1, x2, x3): A.setX(B.x()) B.setX(xi) if xi == x2 and j >= Y1 and j <= Y2: canvas.setPen(self.COL_FIG) else: canvas.setPen(self.COL_AIR) canvas.drawLine(A, B) # Vertical lines y0 = self.pixel_y(0) y1 = self.pixel_y(Y1) y2 = self.pixel_y(Y2) y3 = self.pixel_y(Y_NLEN) for i in range(X_NLEN+1): x = self.pixel_x(i) A.setX(x) B.setX(x) B.setY(y0) for yi in (y1, y2, y3): A.setY(B.y()) B.setY(yi) if yi == y2 and i >= X1 and i <= X2: canvas.setPen(self.COL_FIG) else: canvas.setPen(self.COL_AIR) canvas.drawLine(A, B) # Diagonal lines for i in range(X_NLEN): # no need +1: one diagonal for every rectangle x = self.pixel_x(i) y = self.pixel_y(0) B.setY(y) A.setX(x) for j in range(Y_NLEN): A.setY(B.y()) x = self.pixel_x(i+1) y = self.pixel_y(j+1) B.setX(x) B.setY(y) if X1 <= i and i < X2 and Y1 <= j and j < Y2: canvas.setPen(self.COL_FIG) else: canvas.setPen(self.COL_AIR) canvas.drawLine(A, B) # Fill the figure A.setX(self.pixel_x(X1)) A.setY(self.pixel_y(Y1)) B.setX(self.pixel_x(X2)) B.setY(self.pixel_y(Y2)) canvas.fillRect(QRect(A, B), self.COL_FIG_INNNER)