def drawBackground(self, painter, rect): # Shadow. sceneRect = self.sceneRect() rightShadow = QRectF(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()) bottomShadow = QRectF(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5) if rightShadow.intersects(rect) or rightShadow.contains(rect): painter.fillRect(rightShadow, Qt.darkGray) if bottomShadow.intersects(rect) or bottomShadow.contains(rect): painter.fillRect(bottomShadow, Qt.darkGray) # Fill. gradient = QLinearGradient(sceneRect.topLeft(), sceneRect.bottomRight()) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, Qt.lightGray) # painter.fillRect(rect.intersect(sceneRect), QBrush(gradient)) painter.setBrush(Qt.NoBrush) painter.drawRect(sceneRect) # Text. textRect = QRectF(sceneRect.left() + 4, sceneRect.top() + 4, sceneRect.width() - 4, sceneRect.height() - 4) message = "Click and drag the nodes around, and zoom with the " \ "mouse wheel or the '+' and '-' keys" font = painter.font() font.setBold(True) font.setPointSize(14) painter.setFont(font) painter.setPen(Qt.lightGray) painter.drawText(textRect.translated(2, 2), message) painter.setPen(Qt.black) painter.drawText(textRect, message)
def drawBackground(self, painter, rect): # Shadow. sceneRect = self.sceneRect() rightShadow = QRectF(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()) bottomShadow = QRectF(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5) if rightShadow.intersects(rect) or rightShadow.contains(rect): painter.fillRect(rightShadow, Qt.darkGray) if bottomShadow.intersects(rect) or bottomShadow.contains(rect): painter.fillRect(bottomShadow, Qt.darkGray) # Fill. gradient = QLinearGradient(sceneRect.topLeft(), sceneRect.bottomRight()) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, Qt.lightGray) painter.fillRect(rect.intersected(sceneRect), QBrush(gradient)) painter.setBrush(Qt.NoBrush) painter.drawRect(sceneRect) # Text. textRect = QRectF(sceneRect.left() + 4, sceneRect.top() + 4, sceneRect.width() - 4, sceneRect.height() - 4) message = "Click and drag the nodes around, and zoom with the " \ "mouse wheel or the '+' and '-' keys" font = painter.font() font.setBold(True) font.setPointSize(14) painter.setFont(font) painter.setPen(Qt.lightGray) painter.drawText(textRect.translated(2, 2), message) painter.setPen(Qt.black) painter.drawText(textRect, message)
def getLinesWithinRect(self, bounds: QRectF): lines = [] halfLines = [] # debug(self.lines, color=3, showFile=True) for l in self.lines: #* You suck if bounds.contains(*l.start.asTL(*self.s).data()) and bounds.contains(*l.end.asTL(*self.s).data()): # if collidePoint(Pointf(bounds.topLeft()), (bounds.width(), bounds.height()), l.start) and \ # collidePoint(Pointf(bounds.topLeft()), (bounds.width(), bounds.height()), l.end): lines.append(l) elif bounds.contains(*l.start.asTL(*self.s).data()) or bounds.contains(*l.end.asTL(*self.s).data()): halfLines.append(l) return lines, halfLines
def _hitTest(self, rc: QRectF, mousePos: QPointF) -> Hit: maxdist = 4 if not rc.adjusted(-maxdist, -maxdist, maxdist, maxdist).contains(mousePos): return Hit.NoHit def dist(p1, p2): return (p1 - p2).manhattanLength() if dist(rc.topLeft(), mousePos) < maxdist: return Hit.TopLeft elif dist(rc.topRight(), mousePos) < maxdist: return Hit.TopRight elif dist(rc.bottomRight(), mousePos) < maxdist: return Hit.BottomRight elif dist(rc.bottomLeft(), mousePos) < maxdist: return Hit.BottomLeft elif abs(rc.left() - mousePos.x()) < maxdist: return Hit.Left elif abs(rc.right() - mousePos.x()) < maxdist: return Hit.Right elif abs(rc.top() - mousePos.y()) < maxdist: return Hit.Top elif abs(rc.bottom() - mousePos.y()) < maxdist: return Hit.Bottom elif rc.contains(mousePos): return Hit.Center else: return Hit.NoHit
def setLine(self, line): """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = line # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom)
def wheelEvent(self, event): if (self.__file_base_name != None) and (event.modifiers() == Qt.ControlModifier): event.accept() # Accumulated mouse wheel steps, bounded to certain limits self.__wheel_steps = self.__qBound( -self.__max_steps, self.__wheel_steps + event.angleDelta().y() / 120, self.__max_steps) newPPI = self.__calc_ppi(self.__wheel_steps) # Do nothing if reached one of the zoom limits if (newPPI == self.__current_ppi): return # Get the cursor's position and translate to pixmap coordinates scenePos = self.mapToScene(event.pos()) # Now find the % offset from pixmap's origin. This doesn't change with zoom percentX = scenePos.x() / self.__scene.itemsBoundingRect().width() percentY = scenePos.y() / self.__scene.itemsBoundingRect().height() # Now perform the zoom by converting from PDF with suitable resolution # Set working dir saveWD = os.getcwd() os.chdir(pycirkuit.__tmpDir__.path()) try: converter = ToolPdfToPng() converter.execute(self.__file_base_name, resolution=newPPI) self.setImage(self.__file_base_name, adjustIGU=True) # If Scene contents area is smaller than current viewport size, center scene in view currentSceneRect = self.__scene.itemsBoundingRect() currentViewportRect = QRectF(self.rect()) if (currentViewportRect.contains(currentSceneRect)): self.setSceneRect(currentSceneRect) self.centerOn(currentSceneRect.center()) # Else, keep scene point under cursor at the same viewport position else: # Calculate the scene coordinates of the position which is (%X,%Y) from origin newScenePos = QPointF(currentSceneRect.width() * percentX, currentSceneRect.height() * percentY) # Calculate pixel offset between mouse position and viewport center offset = QPointF(self.width() / 2, self.height() / 2) - QPointF(event.pos()) # Then adjust things so that this scene position appears under the mouse self.centerOn(newScenePos + offset) except PyCirkuitError as err: self.setText( _translate("PyCirkuitError", "Error creating zoomed image.", "Displayed error message")) self.conversion_failed.emit(err) else: self.__current_ppi = newPPI finally: os.chdir(saveWD) else: event.ignore()
def getCP(self, x, y): s = self.size for r in range(self.line): for c in range(self.line): pt = self.cpt[r][c] _x = pt.x() _y = pt.y() rect = QRectF(_x - s / 2, _y - s / 2, s, s) if rect.contains(QPointF(x, y)): return r, c
def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: rect = self.scene().parent().mapToScene( self.scene().parent().viewport().rect()).boundingRect() restrictedRect = QRectF( rect.x() + (rect.width() - self.scene().roomWidth) * .5, rect.y() + (rect.height() - self.scene().roomHeight) * .5, self.scene().roomWidth, self.scene().roomHeight) if restrictedRect.contains(event.scenePos()): self.scene().update() QGraphicsItem.mouseMoveEvent(self, event)
def mousePressEvent(self, event): if event.button() != Qt.MouseButton.LeftButton: return size = self.height() / 2.0 rect = QRectF(self.width() - size, size * 0.5, size, size) if rect.contains(event.localPos()): self.clear() self.valid = True event.accept()
def mouseMoved(self, event): for i,item in enumerate(self.graphicsLayoutWidget.items()): if isinstance(item, pg.graphicsItems.ViewBox.ViewBox): sbr = item.sceneBoundingRect() tr = item.state['targetRange'] qr = QRectF(QPointF(tr[0][0],tr[1][0]),\ QPointF(tr[0][1],tr[1][1])) mousePoint = item.mapSceneToView(event) contains = qr.contains(mousePoint) p = item.parentItem() a = p.getAxis('top') if contains: setCursorLocationText(a, (mousePoint.x(), mousePoint.y())) else: setCursorLocationText(a, None)
def findConnectionAt(self, pos): items = self.scene.items( QRectF(pos - QPointF(DB, DB), QSizeF(2 * DB, 2 * DB))) for c in items: if isinstance(c, Connection): points = [c.pos1] for el in c.connPoints: points.append(el) points.append(c.pos2) N = len(points) for n in range(0, N - 1): p1 = points[n] p2 = points[n + 1] rect = QRectF(p1 - QPointF(DB, DB), p2 + QPointF(DB, DB)) if rect.contains(pos): return c return None
def mousePressEvent(self, event): self.clicked_object = None self.drag_start = event.localPos() for ettu_obj in self.ettu.all_transports + self.ettu.all_stations: coord = self.get_widget_coordinates(ettu_obj) if coord is not None: rect = QRectF(*coord, 20, 20) rect.translate(-10, -10) if rect.contains(self.drag_start): if isinstance(ettu_obj, Transport): self.clicked_object = TransportContextMenu( ettu_obj, self.drag_start.x(), self.drag_start.y()) else: self.clicked_object = StationContextMenu( ettu_obj, self.drag_start.x(), self.drag_start.y()) self.ettu.get_arrive_time(ettu_obj.station_id) self.update()
def find_exact_pos(self, c, pos): # Find exact point on connection c points = [c.pos1] for el in c.connPoints: points.append(el) points.append(c.pos2) N = len(points) for n in range(0, N - 1): p1 = points[n] p2 = points[n + 1] rect = QRectF(p1 - QPointF(DB, DB), p2 + QPointF(DB, DB)) if rect.contains(pos): if p1.x() == p2.x(): pos.setX(p1.x()) if p1.y() == p2.y(): pos.setY(p1.y()) return n, pos
def __validatePlacer(self): sceneX, sceneY = self.__ghostShipLongSurface() x, y = self.sceneToMap(sceneX, sceneY) self.__placer.setPos((x + 1) * self.tileSize, (y + 1) * self.tileSize) permittedArea = QRectF(self.__ui.graphicsView.viewport().geometry()) permittedArea.setTopLeft(QPointF(self.tileSize, self.tileSize)) permittedArea.setBottomRight( QPointF(self.tileSize * 12, self.tileSize * 12)) placerSize = self.__placer.boundingRect() placerRect = QRectF(sceneX, sceneY, placerSize.width(), placerSize.height()) isPlacerValid = False # first validation - ship can be placed inside game field if permittedArea.contains(self.__ghostShip.pos( )) and permittedArea == permittedArea.united(placerRect): if self.__placer.scene() == None: self.__scene.addItem(self.__placer) x, y = self.sceneToMap(sceneX, sceneY) self.__placer.setPos((x + 1) * self.tileSize, (y + 1) * self.tileSize) isPlacerValid = True else: if self.__placer.scene() == self.__scene: self.__scene.removeItem(self.__placer) # second validation - placer does not intersect with other ships if isPlacerValid: isPlacerValid = self.__validatePosition( x, y, placerSize.width() / self.tileSize, placerSize.height() / self.tileSize) # set color of placer pen = self.__placer.pen() if isPlacerValid: pen.setColor(Qt.GlobalColor.darkGreen) else: pen.setColor(Qt.GlobalColor.red) self.__placer.setPen(pen) self.__placer.setData(0, isPlacerValid)
class RectMarker(QGraphicsRectItem): """Class to draw a rectangular, coloured item. Parameters ---------- x : float x position in scene y : gloat y position in scene width : float length in seconds height : float height in scene units color : str or QColor, optional color of the rectangle """ def __init__(self, x, y, width, height, zvalue, color='blue'): super().__init__() self.color = color self.setZValue(zvalue) buffer = 1 self.marker = QRectF(x, y, width, height) self.b_rect = QRectF(x - buffer / 2, y + buffer / 2, width + buffer, height + buffer) self.params = x, y, width, height, zvalue, color def boundingRect(self): return self.b_rect def paint(self, painter, option, widget): color = QColor(self.color) painter.setBrush(QBrush(color)) p = QPen() p.setWidth(0) p.setColor(color) painter.setPen(p) painter.drawRect(self.marker) super().paint(painter, option, widget) def contains(self, pos): return self.marker.contains(pos)
def adjustGeometry(self): """ Adjust the widget geometry to exactly fit the arrow inside while preserving the arrow path scene geometry. """ # local system coordinate geom = self.geometry().translated(-self.pos()) line = self.__line arrow_rect = self.__arrowItem.shape().boundingRect() if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) geom = geom.intersected(arrow_rect) diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) geom.translate(self.pos()) self.setGeometry(geom) self.setLine(line)
class Callout(QGraphicsItem): def __init__(self, chart): super().__init__(chart) self.m_chart = chart self.m_text = "" self.m_textRect = QRectF() self.m_rect = QRectF() self.m_anchor = QPointF() self.m_font = QFont() def boundingRect(self): anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor)) rect = QRectF() rect.setLeft(min(self.m_rect.left(), anchor.x())) rect.setRight(max(self.m_rect.right(), anchor.x())) rect.setTop(min(self.m_rect.top(), anchor.y())) rect.setBottom(max(self.m_rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget=None): path = QPainterPath() path.addRoundedRect(self.m_rect, 5, 5) anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor)) if not self.m_rect.contains(anchor): point1 = QPointF() point2 = QPointF() # establish the position of the anchor point in relation to m_rect above = anchor.y() <= self.m_rect.top() aboveCenter = (anchor.y() > self.m_rect.top() and anchor.y() <= self.m_rect.center().y()) belowCenter = (anchor.y() > self.m_rect.center().y() and anchor.y() <= self.m_rect.bottom()) below = anchor.y() > self.m_rect.bottom() onLeft = anchor.x() <= self.m_rect.left() leftOfCenter = (anchor.x() > self.m_rect.left() and anchor.x() <= self.m_rect.center().x()) rightOfCenter = (anchor.x() > self.m_rect.center().x() and anchor.x() <= self.m_rect.right()) onRight = anchor.x() > self.m_rect.right() # get the nearest m_rect corner. x = (onRight + rightOfCenter) * self.m_rect.width() y = (below + belowCenter) * self.m_rect.height() cornerCase = ((above and onLeft) or (above and onRight) or (below and onLeft) or (below and onRight)) vertical = abs(anchor.x() - x) > abs(anchor.y() - y) x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * int(not vertical) * (onLeft * 10 - onRight * 20)) y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase * int(vertical) * (above * 10 - below * 20)) point1.setX(x1) point1.setY(y1) x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * int(not vertical) * (onLeft * 20 - onRight * 10)) y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase * int(vertical) * (above * 20 - below * 10)) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self.m_textRect, self.m_text) def mousePressEvent(self, event): event.setAccepted(True) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.setPos( self.mapToParent(event.pos() - event.buttonDownPos(Qt.LeftButton))) event.setAccepted(True) else: event.setAccepted(False) def setText(self, text): self.m_text = text metrics = QFontMetrics(self.m_font) self.m_textRect = QRectF( metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft, self.m_text)) self.m_textRect.translate(5, 5) self.prepareGeometryChange() self.m_rect = self.m_textRect.adjusted(-5, -5, 5, 5) def setAnchor(self, point): self.m_anchor = point def updateGeometry(self): self.prepareGeometryChange() self.setPos( self.m_chart.mapToPosition(self.m_anchor) + QPoint(10, -50))
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.setGeometry(300,300,400,500) self.setWindowTitle("2048 PyQt") self.brushes={ 0:QBrush(QColor(0xcdc1b4)), 1:QBrush(QColor(0x999999)), 2:QBrush(QColor(0xeee4da)), 4:QBrush(QColor(0xede0c8)), 8:QBrush(QColor(0xf2b179)), 16:QBrush(QColor(0xf59563)), 32:QBrush(QColor(0xf67c5f)), 64:QBrush(QColor(0xf65e3b)), 128:QBrush(QColor(0xedcf72)), 256:QBrush(QColor(0xedcc61)), 512:QBrush(QColor(0xedc850)), 1024:QBrush(QColor(0xedc53f)), 2048:QBrush(QColor(0xedc22e)), } self.backgroundBrush=QBrush(QColor(0xbbada0)) self.resetRect=QRectF(290,30,100,40) self.descriptionRect=QRectF(10,30,270,40) self.player1 = Game() self.player1._signal1.connect(self.update) self.player1._signal1.connect(self.showInfo) self.player1.start() def showInfo(self, info): print(info) def mousePressEvent(self,e): self.player1.lastPoint=e.pos() def mouseReleaseEvent(self,e): if self.resetRect.contains(self.player1.lastPoint.x(),self.player1.lastPoint.y()) and self.resetRect.contains(e.pos().x(),e.pos().y()): if QMessageBox.question(self,'','Restart?', QMessageBox.Yes,QMessageBox.No)==QMessageBox.Yes: self.player1.resetGame() def keyPressEvent(self, e): if e.key() in [Qt.Key_A,Qt.Key_W,Qt.Key_D,Qt.Key_S,Qt.Key_Up,Qt.Key_Down,Qt.Key_Left,Qt.Key_Right]: same = self.player1.move(e.key()) if not same: self.player1.new() self.player1.showplate() self.update() print("\nNext move:") else: if self.player1.if_full() == 1: print("Game Over.") def paintEvent(self, event): qp = QPainter() qp.begin(self) qp.setPen(Qt.NoPen) qp.setBrush(self.brushes[1024]) qp.drawRoundedRect(self.resetRect,5,5) qp.setPen(QColor(0xf9f6f2)) qp.setFont(QFont("Thoma",26)) qp.drawText(self.resetRect, "Reset", QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) qp.setPen(QColor(0x776e65)) qp.setFont(QFont("Thoma",13)) qp.drawText(self.descriptionRect,"Join the numbers og get to the 2048 title!", QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) for i in range(4): for j in range(4): rect=QRectF(10+j*100, 110+i*100, 80, 80) qp.setPen(Qt.NoPen) #qp.setBrush(QColor(255,80,0,160)) qp.setBrush(self.brushes[self.player1.a[i,j]]) qp.drawRoundedRect(rect, 5, 5) if self.player1.a[i,j] < 16: qp.setPen(QColor(0x776e65)) else: qp.setPen(QColor(0xf9f6f2)) if self.player1.a[i,j] > 512: qp.setFont(QFont("Tahoma",30)) elif self.player1.a[i,j] > 64: qp.setFont(QFont("Tahoma",40)) else: qp.setFont(QFont("Tahoma",50)) if self.player1.a[i,j] != 0: qp.drawText(rect, str(self.player1.a[i,j]), QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) qp.end()
class Game(QObject): # 클래스 변수 update_signal = pyqtSignal() gameover_signal = pyqtSignal(int) def __init__(self, w): super().__init__() self.parent = w self.rect = w.rect() # 바둑판 사각형 self.outrect = QRectF(self.rect) gap = 10 self.outrect.adjust(gap, gap, -gap, -gap) # 바둑돌 놓는 사각형 self.inrect = QRectF(self.outrect) gap = 20 self.inrect.adjust(gap, gap, -gap, -gap) self.line = 19 self.size = self.inrect.width() / (self.line - 1) # 바둑돌 self.wdol = [] self.bdol = [] self.bTrun = True # 바둑돌 중간 교차점 x = self.inrect.left() y = self.inrect.top() self.cpt = [[ QPointF(x + (self.size * c), y + (self.size * r)) for c in range(self.line) ] for r in range(self.line)] #print(self.cpt) # 바둑판 상태 저장 0:돌없음, 1:흑돌, 2:백돌 self.state = [[0 for c in range(self.line)] for r in range(self.line)] #print(self.state) # 시그널, 슬롯 self.update_signal.connect(self.parent.update) self.gameover_signal.connect(self.parent.gameOver) def draw(self, qp): b = QBrush(QColor(175, 150, 75)) qp.setBrush(b) qp.drawRect(self.outrect) x = self.inrect.left() y = self.inrect.top() x1 = self.inrect.right() y1 = self.inrect.top() x2 = self.inrect.left() y2 = self.inrect.bottom() # 바둑판 줄 그리기 for i in range(self.line): qp.drawLine(x, y + (self.size * i), x1, y1 + (self.size * i)) qp.drawLine(x + (self.size * i), y, x2 + (self.size * i), y2) # 흑돌 그리기 b = QBrush(Qt.black) qp.setBrush(b) for dol in self.bdol: x = dol.x() - self.size / 2 y = dol.y() - self.size / 2 rect = QRectF(x, y, self.size, self.size) qp.drawEllipse(rect) # 백돌 그리기 b = QBrush(Qt.white) qp.setBrush(b) for dol in self.wdol: x = dol.x() - self.size / 2 y = dol.y() - self.size / 2 rect = QRectF(x, y, self.size, self.size) qp.drawEllipse(rect) def mouseDown(self, x, y): # 바둑판 안에 두었는지? #T = self.inrect.top() #B = self.inrect.bottom() #L = self.inrect.left() #R = self.inrect.right() #if (x>L and x<R) and (y>T and y<B): if self.inrect.contains(QPointF(x, y)): row, col = self.getCP(x, y) print('row:', row, 'col:', col) # 돌이 없으면 if self.state[row][col] == 0: if self.bTrun: self.state[row][col] = 1 self.bdol.append(self.cpt[row][col]) else: self.state[row][col] = 2 self.wdol.append(self.cpt[row][col]) self.bTrun = not self.bTrun self.update_signal.emit() # 판정 0:진행중, 1:흑돌승, 2:백돌승, 3:무승부 result = self.panjung() if result != 0: self.gameover_signal.emit(result) else: QMessageBox.warning(self.parent, '오류', '이미 돌이 있습니다', QMessageBox.Ok) else: QMessageBox.warning(self.parent, '오류', '바둑판 안에 돌을 놓으세요', QMessageBox.Ok) def getCP(self, x, y): s = self.size for r in range(self.line): for c in range(self.line): pt = self.cpt[r][c] _x = pt.x() _y = pt.y() rect = QRectF(_x - s / 2, _y - s / 2, s, s) if rect.contains(QPointF(x, y)): return r, c def panjung(self): # 판정 0:진행중, 1:흑돌승, 2:백돌승, 3:무승부 cnt = 0 for r in range(self.line): for c in range(self.line): # 무승부 if self.state[r][c] != 0: cnt += 1 # 흑돌 가로 판정 if c <= 14: if (self.state[r][c] == 1 and self.state[r][c + 1] == 1 and self.state[r][c + 2] == 1 and self.state[r][c + 3] == 1 and self.state[r][c + 4] == 1): return 1 # 흑돌 세로 판정 if r <= 14: if (self.state[r][c] == 1 and self.state[r + 1][c] == 1 and self.state[r + 2][c] == 1 and self.state[r + 3][c] == 1 and self.state[r + 4][c] == 1): return 1 # 흑돌 대각(좌우) 판정 if r <= 14 and c <= 14: if (self.state[r][c] == 1 and self.state[r + 1][c + 1] == 1 and self.state[r + 2][c + 2] == 1 and self.state[r + 3][c + 3] == 1 and self.state[r + 4][c + 4] == 1): return 1 # 흑돌 대각(우좌) 판정 if r <= 14 and c >= 4: if (self.state[r][c] == 1 and self.state[r + 1][c - 1] == 1 and self.state[r + 2][c - 2] == 1 and self.state[r + 3][c - 3] == 1 and self.state[r + 4][c - 4] == 1): return 1 # 백돌 가로 판정 if c <= 14: if (self.state[r][c] == 2 and self.state[r][c + 1] == 2 and self.state[r][c + 2] == 2 and self.state[r][c + 3] == 2 and self.state[r][c + 4] == 2): return 2 # 백돌 세로 판정 if r <= 14: if (self.state[r][c] == 2 and self.state[r + 1][c] == 2 and self.state[r + 2][c] == 2 and self.state[r + 3][c] == 2 and self.state[r + 4][c] == 2): return 2 # 백돌 대각(좌우) 판정 if r <= 14 and c <= 14: if (self.state[r][c] == 2 and self.state[r + 1][c + 1] == 2 and self.state[r + 2][c + 2] == 2 and self.state[r + 3][c + 3] == 2 and self.state[r + 4][c + 4] == 2): return 2 # 백돌 대각(우좌) 판정 if r <= 14 and c >= 4: if (self.state[r][c] == 2 and self.state[r + 1][c - 1] == 2 and self.state[r + 2][c - 2] == 2 and self.state[r + 3][c - 3] == 2 and self.state[r + 4][c - 4] == 2): return 2 if cnt == self.line * self.line: return 3 return 0
class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.m_pressflag = False self.m_touchflag = False self.rectbutton = QRectF(20, 20, 50, 50) self.setMouseTracking(True) def initUI(self): #self.setGeometry(300, 300, 350, 100) palette = QPalette() palette.setColor(QPalette.Window, QColor(102, 205, 170, 160)) self.setPalette(palette) #UI-size self.resize(QDesktopWidget().availableGeometry().width() / 2, QDesktopWidget().availableGeometry().height() / 4 * 3) qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.left(), qr.top() - qr.top() * 0.3) self.setWindowTitle('ChessBoard') self.show() def mouseMoveEvent(self, e): n = e.pos() if (self.rectbutton.contains(n)): self.m_touchflag = True else: self.m_touchflag = False self.update() def paintEvent(self, e): qp = QPainter() qp.begin(self) #chess background color col = QColor(0, 0, 0) col.setNamedColor('#d4d4d4') qp.setPen(col) qp.setBrush(QColor(220, 150, 40, 160)) chess_background_color_top = self.width() / 2 - self.width() / 10 * 4 chess_background_color_left = self.height() / 2 - self.height() / 9 * 4 chess_background_color_width = self.width() / 5 * 4 chess_background_color_height = self.height() / 5 * 4 qp.drawRect(chess_background_color_top, chess_background_color_left, chess_background_color_width, chess_background_color_height) #chess line top_dis = chess_background_color_height / 16 left_dis = chess_background_color_width / 16 grid_width = (chess_background_color_width - 2 * left_dis) / 4 grid_height = (chess_background_color_height - 2 * top_dis) / 4 pen = QPen(Qt.white, 2, Qt.SolidLine) qp.setPen(pen) for i in range(0, 5): qp.drawLine( chess_background_color_top + left_dis, chess_background_color_left + top_dis + i * grid_height, chess_background_color_top - left_dis + chess_background_color_width, chess_background_color_left + top_dis + i * grid_height) qp.drawLine( chess_background_color_top + left_dis + i * grid_width, chess_background_color_left + top_dis, chess_background_color_top + left_dis + i * grid_width, chess_background_color_left - top_dis + chess_background_color_height) #/ qp.drawLine(chess_background_color_top + left_dis, chess_background_color_left + top_dis + 2 * grid_height, chess_background_color_top + left_dis + 2 * grid_width, chess_background_color_left + top_dis) qp.drawLine(chess_background_color_top + left_dis, chess_background_color_left + top_dis + 4 * grid_height, chess_background_color_top + left_dis + 4 * grid_width, chess_background_color_left + top_dis) qp.drawLine(chess_background_color_top + left_dis + 2 * grid_width, chess_background_color_left + top_dis + 4 * grid_height, chess_background_color_top + left_dis + 4 * grid_width, chess_background_color_left + top_dis + 2 * grid_height) #\ qp.drawLine(chess_background_color_top + left_dis + 2 * grid_width, chess_background_color_left + top_dis, chess_background_color_top + left_dis + 4 * grid_width, chess_background_color_left + top_dis + 2 * grid_height) qp.drawLine(chess_background_color_top + left_dis, chess_background_color_left + top_dis, chess_background_color_top + left_dis + 4 * grid_width, chess_background_color_left + top_dis + 4 * grid_height) qp.drawLine(chess_background_color_top + left_dis, chess_background_color_left + top_dis + 2 * grid_height, chess_background_color_top + left_dis + 2 * grid_width, chess_background_color_left + top_dis + 4 * grid_height) #chess qp.setBrush(QColor(0, 0, 0, 160)) self.rectbutton = QRectF(20, 20, 50, 50) qp.drawEllipse(self.rectbutton) if (self.m_touchflag): qp.setBrush(QColor(255, 255, 255, 255)) self.rectbutton = QRectF(20, 100, 50, 50) qp.drawEllipse(self.rectbutton) else: qp.setBrush(QColor(200, 255, 255, 255)) self.rectbutton = QRectF(20, 100, 50, 50) qp.drawEllipse(self.rectbutton) # rectbutton.installEventFilter(self) # def eventFilter(self, qobject, qevent): # qtype = qevent.type() # if qtype == QEvent.HoverMove: # print("sad") # # return QWidget.eventFilter(qobject, qevent) qp.end()
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.brushes={ 0:QBrush(QColor(0xcdc1b4)), 1:QBrush(QColor(0x999999)), 2:QBrush(QColor(0xeee4da)), 4:QBrush(QColor(0xede0c8)), 8:QBrush(QColor(0xf2b179)), 16:QBrush(QColor(0xf59563)), 32:QBrush(QColor(0xf67c5f)), 64:QBrush(QColor(0xf65e3b)), 128:QBrush(QColor(0xedcf72)), 256:QBrush(QColor(0xedcc61)), 512:QBrush(QColor(0xedc850)), 1024:QBrush(QColor(0xedc53f)), 2048:QBrush(QColor(0xedc22e)), } self.backgroundBrush=QBrush(QColor(0xbbada0)) self.resetRect=QRectF(290,30,100,40) self.descriptionRect=QRectF(10,30,270,40) self.resetGame() def mousePressEvent(self,e): self.lastPoint=e.pos() def mouseReleaseEvent(self,e): if self.resetRect.contains(self.lastPoint.x(),self.lastPoint.y()) and self.resetRect.contains(e.pos().x(),e.pos().y()): if QMessageBox.question(self,'','Restart?', QMessageBox.Yes,QMessageBox.No)==QMessageBox.Yes: self.resetGame() def keyPressEvent(self, e): if e.key() in [Qt.Key_A,Qt.Key_W,Qt.Key_D,Qt.Key_S,Qt.Key_Up,Qt.Key_Down,Qt.Key_Left,Qt.Key_Right]: same = self.move(e.key()) if not same: self.new() self.showplate() self.update() print "\nNext move:" else: if self.if_full() == 1: print "Game Over." def resetGame(self): self.a = np.zeros(shape = (4,4), dtype = np.int32) self.max = self.a.max() self.lastPosition=None self.new() self.new() self.showplate() def randrowcol(self): row = random.randint(0,3) col = random.randint(0,3) return (row, col) def rand24(self): if random.randint(1,8) == 4: return 4 else: return 2 def moveleftward(self): #print "left!" b = np.empty_like(self.a) b[:] = self.a #copy, for comparing for r in range(0,4): #by row for c in range(0,3): #bubble1 for i in range(0,3): if self.a[r][i] == 0: self.a[r][i] = self.a[r][i+1] self.a[r][i+1] = 0 for c in range(0,3):#add if self.a[r][c] == self.a[r][c+1] and self.a[r][c]!=0: self.a[r][c]*=2 self.a[r][c+1] = 0 for c in range(0,3): for i in range(0,3): #bubble2 if self.a[r][i] == 0: self.a[r][i] = self.a[r][i+1] self.a[r][i+1] = 0 #print 'row ', r, ' over' #print (b==self.a).all() ,'same?nei' return (b==self.a).all() def moverightward(self): #print "right!" #print self.a temp = np.fliplr(self.a) #print temp self.a[:] = temp #print self.a result = self.moveleftward() #print result, 'same?right' b = np.fliplr(self.a) self.a[:] = b return result def moveupward(self): temp = np.rot90(self.a, 1) #print temp self.a[:] = temp #print self.a result = self.moveleftward() #print result, 'same?up' b = np.rot90(self.a, 3) self.a[:] = b return result pass def movedownward(self): temp = np.rot90(self.a, 3) #print temp self.a[:] = temp #print self.a result = self.moveleftward() #print result, 'same?up' b = np.rot90(self.a, 1) self.a[:] = b return result pass def move(self,mv): if mv == Qt.Key_A or mv == Qt.Key_Left: get = self.moveleftward() if mv == Qt.Key_D or mv == Qt.Key_Right: get = self.moverightward() if mv == Qt.Key_W or mv == Qt.Key_Up: get = self.moveupward() if mv == Qt.Key_S or mv == Qt.Key_Down: get = self.movedownward() return get def new(self): if self.if_full() == 0: newrc = self.randrowcol() while self.a[newrc[0]][newrc[1]] != 0: newrc = self.randrowcol() self.a[newrc[0]][newrc[1]] = self.rand24() else: pass def if_full(self): zero_exist = 0 for r in range(0,4): for c in range(0,4): if self.a[r][c] == 0: zero_exist += 1 #find 0, +1 if zero_exist == 0:#no 0, this keeps 0 #print 'full!' return 1 else: #print 'not full yet!' return 0 def showplate(self): print self.a sys.stdout.flush() def paintEvent(self, event): qp = QPainter() qp.begin(self) qp.setPen(Qt.NoPen) qp.setBrush(self.brushes[1024]) qp.drawRoundedRect(self.resetRect,5,5) qp.setPen(QColor(0xf9f6f2)) qp.setFont(QFont("Thoma",26)) qp.drawText(self.resetRect, "Reset", QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) qp.setPen(QColor(0x776e65)) qp.setFont(QFont("Thoma",13)) qp.drawText(self.descriptionRect,"Join the numbers og get to the 2048 title!", QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) for i in range(4): for j in range(4): rect=QRectF(10+j*100, 110+i*100, 80, 80) qp.setPen(Qt.NoPen) #qp.setBrush(QColor(255,80,0,160)) qp.setBrush(self.brushes[self.a[i,j]]) qp.drawRoundedRect(rect, 5, 5) if self.a[i,j] < 16: qp.setPen(QColor(0x776e65)) else: qp.setPen(QColor(0xf9f6f2)) if self.a[i,j] > 512: qp.setFont(QFont("Tahoma",30)) elif self.a[i,j] > 64: qp.setFont(QFont("Tahoma",40)) else: qp.setFont(QFont("Tahoma",50)) if self.a[i,j] != 0: qp.drawText(rect, str(self.a[i,j]), QTextOption(Qt.AlignHCenter|Qt.AlignVCenter)) qp.end()
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.setGeometry(350, 250, 920, 500) self.setWindowTitle("2048 Cat") self.brushes = { 0:QBrush(QColor(0xcdc1b4)), 1:QBrush(QColor(0x999999)), 2:QBrush(QColor(0xeee4da)), 4:QBrush(QColor(0xede0c8)), 8:QBrush(QColor(0xf2b179)), 16:QBrush(QColor(0xf59563)), 32:QBrush(QColor(0xf67c5f)), 64:QBrush(QColor(0xf65e3b)), 128:QBrush(QColor(0xedcf72)), 256:QBrush(QColor(0xedcc61)), 512:QBrush(QColor(0xedc850)), 1024:QBrush(QColor(0xedc53f)), 2048:QBrush(QColor(0xedc22e)), } self.backgroundBrush = QBrush(QColor(0xbbada0)) self.resetRect = QRectF(290, 30, 100, 40) self.descriptionRect = QRectF(10, 30, 270, 40) self.infoFromSignal = [] self.conceptFromSignal = [] self.codeRackStatFromSignal = [] self.proposalsActivityFromSignal = {} self.structureDepictList = [] self.player1 = gamePlay() self.player1._signal1.connect(self.showInfo) self.player1._signal1.connect(self.update) self.player1.controller1.workspace1._signal2.connect(self.catchInfo) self.player1.controller1.workspace1._signal2.connect(self.update) self.player1.controller1.conceptweb1._signal3.connect(self.catchConcepts) self.player1.controller1.conceptweb1._signal3.connect(self.update) self.player1.controller1.coderack1._signal4.connect(self.catchCodeRackStat) self.player1.controller1.coderack1._signal4.connect(self.update) self.player1.controller1._signal5.connect(self.catchProposalsActivity) self.player1.controller1._signal5.connect(self.update) self.player1.controller1.workspace1._signal6.connect(self.catchDepictList) self.player1.controller1.workspace1._signal6.connect(self.update) self.player1.start() def catchDepictList(self, info): self.structureDepictList = info def showInfo(self, info): #print('Showing info from signal1...') #print(info) pass def catchInfo(self, info): #print('Info got from signal2, new structure') #print(info) self.infoFromSignal = info def catchConcepts(self, info): #print('Concept web from signal3') #print(info) self.conceptFromSignal = info def catchCodeRackStat(self,info): info.sort() self.codeRackStatFromSignal = info #print('Statistics get!') #print info def catchProposalsActivity(self,info): self.proposalsActivityFromSignal = info def mousePressEvent(self, e): self.player1.lastPoint = e.pos() def mouseReleaseEvent(self, e): if self.resetRect.contains(self.player1.lastPoint.x(), self.player1.lastPoint.y()) and self.resetRect.contains(e.pos().x(), e.pos().y()): # if QMessageBox.question(self,'','Restart?', QMessageBox.Yes,QMessageBox.No)==QMessageBox.Yes: self.update() self.player1.game1.resetGame() self.player1.start() def keyPressEvent(self, e): if e.key() in [Qt.Key_A, Qt.Key_W, Qt.Key_D, Qt.Key_S, Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]: same = self.player1.game1.move(e.key()) if not same: self.player1.game1.new() self.player1.game1.showplate() self.update() print("\nNext move:") else: if self.player1.game1.if_full() == 1: print("Game Over.") def len2Font(self, toShow): if len(str(toShow))>5: ln = 5 else: ln = len(str(toShow)) len2font={5:QFont("Tahoma", 20),4:QFont("Tahoma", 30),3:QFont("Tahoma", 40),2:QFont("Tahoma", 50),1:QFont("Tahoma", 50)} return len2font[ln] def paintEvent(self, event): qp = QPainter() qp.begin(self) # Reset box qp.setPen(Qt.NoPen) qp.setBrush(self.brushes[1024]) qp.drawRoundedRect(self.resetRect, 5, 5) qp.setPen(QColor(0xf9f6f2)) qp.setFont(QFont("Tahoma", 25)) qp.drawText(self.resetRect, "Reset", QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # Description qp.setPen(QColor(0x776e65)) qp.setFont(QFont("Tahoma", 12)) qp.drawText(self.descriptionRect, "2048 auto player\nwith Parallel Terraced Scan applied", QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # Titles left (game) for i in range(4): for j in range(4): rect = QRectF(j * 100, 100 + i * 100, 100, 100) qp.setPen(Qt.NoPen) # qp.setBrush(QColor(255,80,0,160)) qp.setBrush(self.brushes[self.player1.game1.chessboard[i, j]]) qp.drawRect(rect) if self.player1.game1.chessboard[i, j] < 10: qp.setPen(QColor(0x776e65)) else: qp.setPen(QColor(0xf9f6f2)) if self.player1.game1.chessboard[i, j] > 999: qp.setFont(QFont("Tahoma", 30)) elif self.player1.game1.chessboard[i, j] > 99: qp.setFont(QFont("Tahoma", 40)) else: # 1 or 2 digits qp.setFont(QFont("Tahoma", 50)) if self.player1.game1.chessboard[i, j] != 0: qp.drawText(rect, str(self.player1.game1.chessboard[i, j]), QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # Titles right (perception space) borderRect =QRectF(400,100,400,400) qp.setPen(QColor(0xffffff)) # the black border qp.setBrush(QColor(0xffffff)) # the white background qp.drawRect(borderRect) # Draw perception space for i in range(4): for j in range(4): rect = QRectF(400 + j * 100, 100 + i * 100, 100, 100) if self.player1.controller1.workspace1.perceptionSpace[i,j] != 0: qp.setPen(QColor(0x000000)) qp.setBrush(QColor(128,128,128,30)) qp.drawRect(rect) qp.setPen(QColor(0x000000)) if self.player1.controller1.workspace1.perceptionSpace[i, j] > 999: qp.setFont(QFont("Tahoma", 30)) elif self.player1.controller1.workspace1.perceptionSpace[i, j] > 99: qp.setFont(QFont("Tahoma", 40)) elif self.player1.controller1.workspace1.perceptionSpace[i, j] > 9: qp.setFont(QFont("Tahoma", 50)) # Draw newly added structure # Draw titles if self.infoFromSignal != [] and type(self.infoFromSignal[0][1])==int: cordinate = self.infoFromSignal[0] structureRect = QRectF(400 + cordinate[1]*100, 100 + cordinate[0]*100, 100,100) qp.setFont(self.len2Font(str(self.infoFromSignal[1]))) qp.setPen(QColor(0x999999)) text = str(self.infoFromSignal[1]) #print("This is the TEXT! "+text) qp.drawText(structureRect,text,QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # TODO: Draw relation # Draw concepts for i in range(len(self.conceptFromSignal)): #print('Drawing Concepts') conceptRect = QRectF(801,100+20*i,120,20) qp.setPen(QColor(0x999999)) qp.setBrush(QColor(0xffffff)) qp.drawRect(conceptRect) conceptActivityRect = QRectF(801,100+20*i,self.conceptFromSignal[i][1]*10,20) qp.setPen(Qt.NoPen) qp.setBrush(QColor(0xf2b179)) qp.drawRect(conceptActivityRect) qp.setPen(QColor(0x000000)) qp.setFont(QFont("Tahoma",15)) qp.drawText(conceptRect,str(self.conceptFromSignal[i][0]),QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # Draw coderack stat if len(self.codeRackStatFromSignal) > 0: statRect = QRectF(401,15,400,40) qp.setPen(QColor(0x555555)) qp.setFont(QFont("Tahoma",20)) statText='' if len(self.codeRackStatFromSignal[1]) > 0: for i in self.codeRackStatFromSignal[1]: statText += str(i)+': '+str(self.codeRackStatFromSignal[0][i])+' ' qp.drawText(statRect,statText) # Draw proposal activities upRect = QRectF(800,15,20,20) downRect = QRectF(800,35,20,20) leftRect = QRectF(780,35,20,20) rightRect = QRectF(820,35,20,20) dirRect = {0:upRect,1:downRect,2:leftRect,3:rightRect} if len(self.proposalsActivityFromSignal) > 0: for proposal in range(4): qp.setBrush(QColor(0xffffff)) qp.drawRect(dirRect[proposal]) if proposal in self.proposalsActivityFromSignal: qp.setPen(QColor(0x000000)) qp.drawText(dirRect[proposal],str(self.proposalsActivityFromSignal[proposal]),QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)) # Draw stuctures strcTypeColor = {'same':Qt.gray, 'next':Qt.yellow} if len(self.structureDepictList) > 0: for strc in self.structureDepictList: pen = QPen(strcTypeColor[strc[4]], 2, Qt.SolidLine) qp.setPen(pen) qp.drawLine(strc[0],strc[1],strc[2],strc[3]) qp.end()
class ZoomSlider(QWidget, updates.UpdateInterface): """ A QWidget used to zoom and pan around a Timeline""" # This method is invoked by the UpdateManager each time a change happens (i.e UpdateInterface) def changed(self, action): # Clear previous rects self.clip_rects.clear() self.clip_rects_selected.clear() self.marker_rects.clear() # Get layer lookup layers = {} for count, layer in enumerate(reversed(sorted(Track.filter()))): layers[layer.data.get('number')] = count # Wait for timeline object and valid scrollbar positions if hasattr(get_app().window, "timeline") and self.scrollbar_position[2] != 0.0: # Get max width of timeline project_duration = get_app().project.get("duration") pixels_per_second = self.width() / project_duration # Determine scale factor vertical_factor = self.height() / len(layers.keys()) for clip in Clip.filter(): # Calculate clip geometry (and cache it) clip_x = (clip.data.get('position', 0.0) * pixels_per_second) clip_y = layers.get(clip.data.get('layer', 0), 0) * vertical_factor clip_width = ( (clip.data.get('end', 0.0) - clip.data.get('start', 0.0)) * pixels_per_second) clip_rect = QRectF(clip_x, clip_y, clip_width, 1.0 * vertical_factor) if clip.id in get_app().window.selected_clips: # selected clip self.clip_rects_selected.append(clip_rect) else: # un-selected clip self.clip_rects.append(clip_rect) for clip in Transition.filter(): # Calculate clip geometry (and cache it) clip_x = (clip.data.get('position', 0.0) * pixels_per_second) clip_y = layers.get(clip.data.get('layer', 0), 0) * vertical_factor clip_width = ( (clip.data.get('end', 0.0) - clip.data.get('start', 0.0)) * pixels_per_second) clip_rect = QRectF(clip_x, clip_y, clip_width, 1.0 * vertical_factor) if clip.id in get_app().window.selected_transitions: # selected clip self.clip_rects_selected.append(clip_rect) else: # un-selected clip self.clip_rects.append(clip_rect) for marker in Marker.filter(): # Calculate clip geometry (and cache it) marker_x = (marker.data.get('position', 0.0) * pixels_per_second) marker_rect = QRectF(marker_x, 0, 0.5, len(layers) * vertical_factor) self.marker_rects.append(marker_rect) # Force re-paint self.update() def paintEvent(self, event, *args): """ Custom paint event """ event.accept() # Paint timeline preview on QWidget painter = QPainter(self) painter.setRenderHints( QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.TextAntialiasing, True) # Fill the whole widget with the solid color (background solid color) painter.fillRect(event.rect(), QColor("#191919")) # Create pens / colors clip_pen = QPen(QBrush(QColor("#53a0ed")), 1.5) clip_pen.setCosmetic(True) painter.setPen(clip_pen) selected_clip_pen = QPen(QBrush(QColor("Red")), 1.5) selected_clip_pen.setCosmetic(True) scroll_color = QColor("#4053a0ed") scroll_pen = QPen(QBrush(scroll_color), 2.0) scroll_pen.setCosmetic(True) marker_color = QColor("#4053a0ed") marker_pen = QPen(QBrush(marker_color), 1.0) marker_pen.setCosmetic(True) playhead_color = QColor(Qt.red) playhead_color.setAlphaF(0.5) playhead_pen = QPen(QBrush(playhead_color), 1.0) playhead_pen.setCosmetic(True) handle_color = QColor("#a653a0ed") handle_pen = QPen(QBrush(handle_color), 1.5) handle_pen.setCosmetic(True) # Get layer lookup layers = Track.filter() # Wait for timeline object and valid scrollbar positions if get_app().window.timeline and self.scrollbar_position[2] != 0.0: # Get max width of timeline project_duration = get_app().project.get("duration") pixels_per_second = event.rect().width() / project_duration project_pixel_width = max(0, project_duration * pixels_per_second) scroll_width = (self.scrollbar_position[1] - self.scrollbar_position[0]) * event.rect().width() # Get FPS info fps_num = get_app().project.get("fps").get("num", 24) fps_den = get_app().project.get("fps").get("den", 1) fps_float = float(fps_num / fps_den) # Determine scale factor vertical_factor = event.rect().height() / len(layers) # Loop through each clip painter.setPen(clip_pen) for clip_rect in self.clip_rects: painter.drawRect(clip_rect) painter.setPen(selected_clip_pen) for clip_rect in self.clip_rects_selected: painter.drawRect(clip_rect) painter.setPen(marker_pen) for marker_rect in self.marker_rects: painter.drawRect(marker_rect) painter.setPen(playhead_pen) playhead_x = ((self.current_frame / fps_float) * pixels_per_second) playhead_rect = QRectF(playhead_x, 0, 0.5, len(layers) * vertical_factor) painter.drawRect(playhead_rect) # Draw scroll bars (if available) if self.scrollbar_position: painter.setPen(scroll_pen) # scroll bar path scroll_x = self.scrollbar_position[0] * event.rect().width() self.scroll_bar_rect = QRectF(scroll_x, 0.0, scroll_width, event.rect().height()) scroll_path = QPainterPath() scroll_path.addRoundedRect(self.scroll_bar_rect, 6, 6) # draw scroll bar rect painter.fillPath(scroll_path, scroll_color) painter.drawPath(scroll_path) # draw handles painter.setPen(handle_pen) handle_width = 12.0 # left handle left_handle_x = (self.scrollbar_position[0] * event.rect().width()) - (handle_width / 2.0) self.left_handle_rect = QRectF(left_handle_x, event.rect().height() / 4.0, handle_width, event.rect().height() / 2.0) left_handle_path = QPainterPath() left_handle_path.addRoundedRect(self.left_handle_rect, handle_width, handle_width) painter.fillPath(left_handle_path, handle_color) # right handle right_handle_x = (self.scrollbar_position[1] * event.rect().width()) - (handle_width / 2.0) self.right_handle_rect = QRectF(right_handle_x, event.rect().height() / 4.0, handle_width, event.rect().height() / 2.0) right_handle_path = QPainterPath() right_handle_path.addRoundedRect(self.right_handle_rect, handle_width, handle_width) painter.fillPath(right_handle_path, handle_color) # Determine if play-head is inside scroll area if get_app().window.preview_thread.player.Mode( ) == openshot.PLAYBACK_PLAY and self.is_auto_center: if not self.scroll_bar_rect.contains(playhead_rect): get_app().window.TimelineCenter.emit() # End painter painter.end() def mousePressEvent(self, event): """Capture mouse press event""" event.accept() self.mouse_pressed = True self.mouse_dragging = False self.mouse_position = event.pos().x() self.scrollbar_position_previous = self.scrollbar_position # Ignore undo/redo history temporarily (to avoid a huge pile of undo/redo history) get_app().updates.ignore_history = True def mouseReleaseEvent(self, event): """Capture mouse release event""" event.accept() self.mouse_pressed = False self.mouse_dragging = False self.left_handle_dragging = False self.right_handle_dragging = False self.scroll_bar_dragging = False def set_handle_limits(self, left_handle, right_handle, is_left=False): """Set min/max limits on the bounds of the handles (to prevent invalid values)""" if left_handle < 0.0: left_handle = 0.0 right_handle = self.scroll_bar_rect.width() / self.width() if right_handle > 1.0: left_handle = 1.0 - (self.scroll_bar_rect.width() / self.width()) right_handle = 1.0 # Don't allow handles to extend past each other diff = right_handle - left_handle # Adjust currently dragged handle (if exceeding min distance) if is_left and diff < self.min_distance: left_handle = right_handle - self.min_distance elif not is_left and diff < self.min_distance: right_handle = left_handle + self.min_distance return left_handle, right_handle def mouseMoveEvent(self, event): """Capture mouse events""" event.accept() # Get current mouse position mouse_pos = event.pos().x() if mouse_pos < 0: mouse_pos = 0 elif mouse_pos > self.width(): mouse_pos = self.width() # Set cursor if not self.mouse_dragging: if self.left_handle_rect.contains(event.pos()): self.setCursor(self.cursors.get('resize_x')) elif self.right_handle_rect.contains(event.pos()): self.setCursor(self.cursors.get('resize_x')) elif self.scroll_bar_rect.contains(event.pos()): self.setCursor(self.cursors.get('move')) else: self.setCursor(Qt.ArrowCursor) # Detect dragging if self.mouse_pressed and not self.mouse_dragging: self.mouse_dragging = True if self.left_handle_rect.contains(event.pos()): self.left_handle_dragging = True elif self.right_handle_rect.contains(event.pos()): self.right_handle_dragging = True elif self.scroll_bar_rect.contains(event.pos()): self.scroll_bar_dragging = True else: self.setCursor(Qt.ArrowCursor) # Dragging handle if self.mouse_dragging: if self.left_handle_dragging: # Update scrollbar position delta = (self.mouse_position - mouse_pos) / self.width() new_left_pos = self.scrollbar_position_previous[0] - delta is_left = True if int(QCoreApplication.instance().keyboardModifiers() & Qt.ShiftModifier) > 0: # SHIFT key pressed (move ) if (self.scrollbar_position_previous[1] + delta) - new_left_pos > self.min_distance: #both handles if we don't exceed min distance new_right_pos = self.scrollbar_position_previous[ 1] + delta else: midpoint = (self.scrollbar_position_previous[1] + self.scrollbar_position_previous) / 2 new_right_pos = midpoint + (self.min_distance / 2) new_left_pos = midpoint - (self.min_distance / 2) else: new_right_pos = self.scrollbar_position_previous[1] # Enforce limits (don't allow handles to go past each other, or out of bounds) new_left_pos, new_right_pos = self.set_handle_limits( new_left_pos, new_right_pos, is_left) self.scrollbar_position = [ new_left_pos, new_right_pos, self.scrollbar_position[2], self.scrollbar_position[3] ] self.delayed_resize_timer.start() elif self.right_handle_dragging: delta = (self.mouse_position - mouse_pos) / self.width() is_left = False new_right_pos = self.scrollbar_position_previous[1] - delta if int(QCoreApplication.instance().keyboardModifiers() & Qt.ShiftModifier) > 0: # SHIFT key pressed (move ) if new_right_pos - (self.scrollbar_position_previous[0] + delta) > self.min_distance: #both handles if we don't exceed min distance new_left_pos = self.scrollbar_position_previous[ 0] + delta else: midpoint = (self.scrollbar_position_previous[1] + self.scrollbar_position_previous) / 2 new_right_pos = midpoint + (self.min_distance / 2) new_left_pos = midpoint - (self.min_distance / 2) else: new_left_pos = self.scrollbar_position_previous[0] # Enforce limits (don't allow handles to go past each other, or out of bounds) new_left_pos, new_right_pos = self.set_handle_limits( new_left_pos, new_right_pos, is_left) self.scrollbar_position = [ new_left_pos, new_right_pos, self.scrollbar_position[2], self.scrollbar_position[3] ] self.delayed_resize_timer.start() elif self.scroll_bar_dragging: # Update scrollbar position delta = (self.mouse_position - mouse_pos) / self.width() new_left_pos = self.scrollbar_position_previous[0] - delta new_right_pos = self.scrollbar_position_previous[1] - delta # Enforce limits (don't allow handles to go past each other, or out of bounds) new_left_pos, new_right_pos = self.set_handle_limits( new_left_pos, new_right_pos) self.scrollbar_position = [ new_left_pos, new_right_pos, self.scrollbar_position[2], self.scrollbar_position[3] ] # Emit signal to scroll Timeline get_app().window.TimelineScroll.emit(new_left_pos) # Force re-paint self.update() # Update mouse position # self.mouse_position = mouse_pos def resizeEvent(self, event): """Widget resize event""" event.accept() self.delayed_size = self.size() self.delayed_resize_timer.start() def delayed_resize_callback(self): """Callback for resize event timer (to delay the resize event, and prevent lots of similar resize events)""" # Get max width of timeline project_duration = get_app().project.get("duration") normalized_scroll_width = self.scrollbar_position[ 1] - self.scrollbar_position[0] scroll_width_seconds = normalized_scroll_width * project_duration tick_pixels = 100 if self.scrollbar_position[3] > 0.0: # Calculate the new zoom factor, based on pixels per tick zoom_factor = scroll_width_seconds / (self.scrollbar_position[3] / tick_pixels) # Set scroll width (and send signal) if zoom_factor > 0.0: self.setZoomFactor(zoom_factor) # Emit signal to scroll Timeline get_app().window.TimelineScroll.emit( self.scrollbar_position[0]) # Capture wheel event to alter zoom/scale of widget def wheelEvent(self, event): event.accept() # Repaint widget on zoom self.repaint() def setZoomFactor(self, zoom_factor): """Set the current zoom factor""" # Force recalculation of clips self.zoom_factor = zoom_factor # Emit zoom signal get_app().window.TimelineZoom.emit(self.zoom_factor) get_app().window.TimelineCenter.emit() # Force re-paint self.repaint() def zoomIn(self): """Zoom into timeline""" if self.zoom_factor >= 10.0: new_factor = self.zoom_factor - 5.0 elif self.zoom_factor >= 4.0: new_factor = self.zoom_factor - 2.0 else: new_factor = self.zoom_factor * 0.8 # Emit zoom signal self.setZoomFactor(new_factor) def zoomOut(self): """Zoom out of timeline""" if self.zoom_factor >= 10.0: new_factor = self.zoom_factor + 5.0 elif self.zoom_factor >= 4.0: new_factor = self.zoom_factor + 2.0 else: # Ensure zoom is reversable when using only keyboard zoom new_factor = min(self.zoom_factor * 1.25, 4.0) # Emit zoom signal self.setZoomFactor(new_factor) def update_scrollbars(self, new_positions): """Consume the current scroll bar positions from the webview timeline""" if self.mouse_dragging: return self.scrollbar_position = new_positions # Check for empty clips rects if not self.clip_rects: self.changed(None) # Disable auto center self.is_auto_center = False # Force re-paint self.repaint() def handle_selection(self): # Force recalculation of clips and repaint self.changed(None) self.repaint() def update_playhead_pos(self, currentFrame): """Callback when position is changed""" self.current_frame = currentFrame # Force re-paint self.repaint() def handle_play(self): """Callback when play button is clicked""" self.is_auto_center = True def connect_playback(self): """Connect playback signals""" self.win.preview_thread.position_changed.connect( self.update_playhead_pos) self.win.PlaySignal.connect(self.handle_play) def __init__(self, *args): # Invoke parent init QWidget.__init__(self, *args) # Translate object _ = get_app()._tr # Init default values self.leftHandle = None self.rightHandle = None self.centerHandle = None self.mouse_pressed = False self.mouse_dragging = False self.mouse_position = None self.zoom_factor = 15.0 self.scrollbar_position = [0.0, 0.0, 0.0, 0.0] self.scrollbar_position_previous = [0.0, 0.0, 0.0, 0.0] self.left_handle_rect = QRectF() self.left_handle_dragging = False self.right_handle_rect = QRectF() self.right_handle_dragging = False self.scroll_bar_rect = QRectF() self.scroll_bar_dragging = False self.clip_rects = [] self.clip_rects_selected = [] self.marker_rects = [] self.current_frame = 0 self.is_auto_center = True self.min_distance = 0.02 # Initialize cursors self.cursors = { "move": QCursor(QPixmap(":/cursors/cursor_move.png")), "resize_x": QCursor(QPixmap(":/cursors/cursor_resize_x.png")), "hand": QCursor(QPixmap(":/cursors/cursor_hand.png")), } # Init Qt widget's properties (background repainting, etc...) super().setAttribute(Qt.WA_OpaquePaintEvent) super().setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Add self as listener to project data updates (used to update the timeline) get_app().updates.add_listener(self) # Set mouse tracking self.setMouseTracking(True) # Get a reference to the window object self.win = get_app().window # Connect zoom functionality self.win.TimelineScrolled.connect(self.update_scrollbars) # Connect Selection signals self.win.SelectionChanged.connect(self.handle_selection) # Show Property timer # Timer to use a delay before sending MaxSizeChanged signals (so we don't spam libopenshot) self.delayed_size = None self.delayed_resize_timer = QTimer(self) self.delayed_resize_timer.setInterval(200) self.delayed_resize_timer.setSingleShot(True) self.delayed_resize_timer.timeout.connect(self.delayed_resize_callback)
def ptInLine(self, pt, p1, p2): rect = QRectF(p1 - QPointF(0.5, 0.5), p2 + QPointF(0.5, 0.5)) if rect.contains(pt): return True else: return False