def InitWindow(self):

		self.button1 = QPushButton("Rotate - ", self)
		self.button1.setGeometry(200,420,100,50)
		self.button1.clicked.connect(self.rotateMinus)

		self.button2 = QPushButton("Rotate +", self)
		self.button2.setGeometry(400,420,100,50)
		self.button2.clicked.connect(self.rotatePlus)

		scene = QGraphicsScene(self)
		redBrush = QBrush(Qt.red)
		blueBrush = QBrush(Qt.blue)
		blackPen = QPen(Qt.black)
		blackPen.setWidth(7)

		ellipse = scene.addEllipse(10,10,200,200, blackPen, redBrush)
		rect = scene.addRect(-100,-100,200,200, blackPen, blueBrush)

		ellipse.setFlag(QGraphicsItem.ItemIsMovable) # set it to movable
		rect.setFlag(QGraphicsItem.ItemIsMovable)

		self.view = QGraphicsView(scene, self)
		self.view.setGeometry(0,0,680,400)


		self.setWindowTitle(self.title)
		self.setGeometry(self.top, self.left, self.width, self.height)
		self.setWindowIcon(QtGui.QIcon('./icon/icon.png'))
		self.show()
Ejemplo n.º 2
0
    def InitWindow(self):

        self.button1 = QPushButton("Rotate - ", self)
        self.button1.setGeometry(200, 420, 100, 50)
        self.button1.clicked.connect(self.rotateminus)

        self.button2 = QPushButton("Rotate +", self)
        self.button2.setGeometry(320, 420, 100, 50)
        self.button2.clicked.connect(self.rotateplus)

        scene = QGraphicsScene()  #the scene

        redbrush = QBrush(Qt.red)
        bluebrush = QBrush(Qt.blue)
        blackpen = QPen(Qt.black)
        blackpen.setWidth(7)

        ellipse = scene.addEllipse(10, 10, 200, 200, blackpen, redbrush)
        rect = scene.addRect(-100, -100, 200, 200, blackpen, bluebrush)
        line = scene.addLine(-100, -100, 200, 200, blackpen)

        ellipse.setFlag(QGraphicsItem.ItemIsMovable)
        rect.setFlag(QGraphicsItem.ItemIsMovable)
        line.setFlag(QGraphicsItem.ItemIsMovable)

        self.view = QGraphicsView(scene, self)
        self.view.setGeometry(0, 0, 680, 400)

        self.setWindowIcon(QtGui.QIcon("mongol.jpg"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.show()
Ejemplo n.º 3
0
class View(QGraphicsView):
    
    def __init__(self):
        super().__init__()
        
        self.setGeometry(300, 300, 300, 300)
        self.setRenderHint(QPainter.Antialiasing)
       
        self.init()
        
        
    def init(self):

        self.scene = QGraphicsScene()
        
        r1 = self.scene.addRect(150, 40, 100, 100)
        r1.setBrush(QColor(250, 50, 0))
        r1.setPen(QColor(250, 50, 0))
               
        el = self.scene.addEllipse(40, 70, 80, 80)
        el.setBrush(QColor(0, 50, 250))
        el.setPen(QColor(0, 50, 250))
        
        r2 = self.scene.addRect(60, 180, 150, 70)
        r2.setBrush(QColor(0, 250, 50))
        r2.setPen(QColor(0, 250, 50))
        
        self.setScene(self.scene)  
Ejemplo n.º 4
0
class GameWindow(QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.sx = Settings.width
        self.sy = Settings.height
        self.lines = []
        #self.draw_grid()
        #self.set_opacity(0.3)

        self.scene = QGraphicsScene(0, 0, Settings.width, Settings.height)
        self.setScene(self.scene)

        self.x = 0
        self.y = 0
        self.w = 5
        self.h = 5
        pen = QPen(QColor('dodgerblue'))
        #pen   = QPen(QColor(Qt.green))
        brush = QBrush(pen.color())
        #brush = QBrush(pen.color().darker(150))

        # As opposed to using QPen and QBrush, this colors the periphery only
        #dot = scene.addEllipse(self.x, self.y, self.w, self.h, QColor('dodgerblue'))
        self.dot = self.scene.addEllipse(self.x, self.y, self.w, self.h, pen,
                                         brush)
        self.dot.setFlag(QGraphicsItem.ItemIsMovable)

    def draw_grid(self):
        width = Settings.NUM_BLOCKS_X * Settings.BLOCK_WIDTH
        height = Settings.NUM_BLOCKS_Y * Settings.BLOCK_HEIGHT
        #self.setSceneRect(0,0,width,height)

        #self.setItemIndexMethod(QTwidgets.QgraphicsScene.NoIndex)
        pen = QPen(QColor(0, 0, 0), 1, Qt.SolidLine)
        for x in range(-320, Settings.NUM_BLOCKS_X + 1):
            xc = x * Settings.BLOCK_WIDTH
            self.lines.append(
                self.scene.addLine(xc, 0 - height / 2, xc, height, pen))

        for y in range(-240, Settings.NUM_BLOCKS_Y + 1):
            yc = y * Settings.BLOCK_HEIGHT
            self.lines.append(
                self.scene.addLine(0 - width / 2, yc, width, yc, pen))

    def set_visible(self, visible=True):
        for line in self.lines:
            line.setVisible(visible)

    def delete_grid(self):
        for line in self.lines:
            self.removeItem(line)
        del self.lines[:]

    def set_opacity(self, opacity):
        for line in self.lines:
            line.setOpacity(opacity)
Ejemplo n.º 5
0
    def ItemsInit(self, scene: QGraphicsScene):
        ic = len(self.Inputs())
        oc = len(self.Outputs())
        m = max(ic, oc) * 10
        self.windowRect.setHeight(m * 2 + 20)
        ins = self.Inputs()
        ino = 20 + m - ic * 10
        ouo = 20 + m - oc * 10

        pix = scene.addPixmap(self.icon)
        pix.setPos(
            (self.windowRect.width() - self.icon.width()) * 0.5,
            20 + (self.windowRect.height() - 20 - self.icon.height()) * 0.5)
        pix.setParentItem(self.item)

        for i in range(0, ic):
            ti = scene.addText(ins[i])
            ti.setPos(0, i * 20 + ino)
            ti.setParentItem(self.item)
            ie = scene.addEllipse(
                QRectF(QPointF(-5, i * 20 + 5 + ino), QSizeF(10, 10)))
            ie.setParentItem(self.item)
            ie.setFlag(QGraphicsItem.ItemNegativeZStacksBehindParent)
            ie.setZValue(-1)

        ins = self.Outputs()
        for i in range(0, oc):
            ti = scene.addText(ins[i])
            ti.setPos(
                QPointF(self.windowRect.width() - ti.boundingRect().width(),
                        i * 20 + ouo))
            ti.setParentItem(self.item)
            ie = scene.addEllipse(
                QRectF(QPointF(self.windowRect.width() - 5, i * 20 + 5 + ouo),
                       QSizeF(10, 10)))
            ie.setParentItem(self.item)
            ie.setFlag(QGraphicsItem.ItemNegativeZStacksBehindParent)
            ie.setZValue(-1)

        self.inputs = []
        for i in range(0, ic):
            self.inputs.append(NodeConnector())
Ejemplo n.º 6
0
class PointerApp:
    def __init__(self, point_color, point_size):
        self.app = QApplication(sys.argv)

        self.window = QWidget()
        self.window.setWindowTitle('PyQt5 Pointer App')
        self.window.setGeometry(100, 100, point_size + 2, point_size + 2)
        self.window.setWindowFlags(Qt.FramelessWindowHint
                                   | Qt.WindowStaysOnTopHint)
        self.window.setAttribute(Qt.WA_TranslucentBackground, True)

        self.scene = QGraphicsScene()
        self.scene.setBackgroundBrush(QBrush(QColor(0, 0, 0, 0)))
        self.scene.update()
        self.scene.addEllipse(0,
                              0,
                              point_size,
                              point_size,
                              brush=QBrush(QColor(*point_color)))
        self.view = QGraphicsView(self.scene, parent=self.window)
        self.view.setStyleSheet("background-color:transparent;")
        self.view.show()

        self.timer = QTimer(self.app)
        self.timer.timeout.connect(self.updateFunc)

        signal.signal(signal.SIGINT, self.sigint_handler)

    def sigint_handler(*args):
        QApplication.quit()

    def spin(self):
        print("Hit ctrl+c in the terminal to stop the pointer app.")
        self.window.show()
        self.timer.start(50)
        return self.app.exec_()

    def updateFunc(self):
        data = display.Display().screen().root.query_pointer()._data
        self.window.move(data["root_x"] + 5, data["root_y"] + 5)
Ejemplo n.º 7
0
    def initUi(self):

        layout = QGridLayout()

        graphics_view = QGraphicsView()
        layout.addWidget(graphics_view)

        width = graphics_view.frameGeometry().width()
        height = graphics_view.frameGeometry().height()

        scene = QGraphicsScene()
        scene.setSceneRect(0.0, 0.0, float(width), float(height))

        scene.addRect(100, 100, 150, 150)

        pen = QPen(Qt.SolidLine)
        pen.setColor(Qt.red)
        brush = QBrush(Qt.Dense3Pattern)
        brush.setColor(Qt.darkGreen)
        scene.addEllipse(300, 300, 100, 100, pen, brush)

        graphics_view.setScene(scene)

        self.setLayout(layout)
    def init(self):
        scene = QGraphicsScene()

        redBrush = QBrush(Qt.red)
        blueBrush = QBrush(Qt.blue)
        blackPen = QPen(Qt.black)
        blackPen.setWidth(7)

        ellipse = scene.addEllipse(10, 10, 200, 200, blackPen, redBrush)
        rectange = scene.addRect(-100, -100, 200, 200, blackPen, blueBrush)

        ellipse.setFlag(QGraphicsItem.ItemIsMovable)  #使图像可移动
        rectange.setFlag(QGraphicsItem.ItemIsMovable)

        self.graphicsView.setScene(scene)
        self.graphicsView.scale(1.2, -1.2)
class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.title = "PyQt5 QGraphicView"
        self.top = 200
        self.left = 500
        self.width = 600
        self.height = 500

        self.InitWindow()

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("icon.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.createGraphicView()

        self.show()

    def createGraphicView(self):
        self.scene = QGraphicsScene()
        self.greenBrush = QBrush(Qt.green)
        self.grayBrush = QBrush(Qt.gray)

        self.pen = QPen(Qt.red)

        graphicView = QGraphicsView(self.scene, self)
        graphicView.setGeometry(0, 0, 600, 500)

        self.shapes()

    def shapes(self):
        ellipse = self.scene.addEllipse(20, 20, 200, 200, self.pen,
                                        self.greenBrush)
        rect = self.scene.addRect(-100, -100, 200, 200, self.pen,
                                  self.grayBrush)

        ellipse.setFlag(QGraphicsItem.ItemIsMovable)
        rect.setFlag(QGraphicsItem.ItemIsMovable)
        ellipse.setFlag(QGraphicsItem.ItemIsSelectable)
    def InitWindow(self):

        scene = QGraphicsScene(self)
        redBrush = QBrush(Qt.red)
        blueBrush = QBrush(Qt.blue)
        blackPen = QPen(Qt.black)
        blackPen.setWidth(7)

        ellipse = scene.addEllipse(10, 10, 200, 200, blackPen, redBrush)
        rect = scene.addRect(-100, -100, 200, 200, blackPen, blueBrush)

        ellipse.setFlag(QGraphicsItem.ItemIsMovable)  # set it to movable
        rect.setFlag(QGraphicsItem.ItemIsMovable)

        view = QGraphicsView(scene, self)
        view.setGeometry(0, 0, 680, 500)

        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.setWindowIcon(QtGui.QIcon('./icon/icon.png'))
        self.show()
Ejemplo n.º 11
0
class MyView(QGraphicsView):
    
    def __init__(self):
        super().__init__()
        
        self.initView()
        self.initScene()
        self.checkCollisions()        
        
        
    def initView(self):
    
        self.setWindowTitle("Collision detection")
        self.setRenderHint(QPainter.Antialiasing)
        self.setGeometry(300, 300, 300, 250)

        
    def initScene(self):
    
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, 300, 250)
        
        self.item = Item()
        
        self.scene.addEllipse(160, 60, 40, 40)
        self.scene.addEllipse(80, 80, 80, 80)
        self.scene.addEllipse(190, 120, 60, 60)
        self.scene.addEllipse(150, 165, 50, 50)

        self.scene.addItem(self.item)
        self.setScene(self.scene)
        
        
    def checkCollisions(self):
        
        items = self.scene.items()
        
        brush = QBrush(Qt.SolidPattern)
        brush.setStyle(Qt.HorPattern)
        
        for i in range(len(items)):
            item = items[i]

            if self.scene.collidingItems(item):
                item.setBrush(brush)
Ejemplo n.º 12
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self.sx = 635
        self.sy = 475

        scene = QGraphicsScene(0, 0, self.sx, self.sy)
        self.setScene(scene)

        self.x = 0
        self.y = 0
        self.w = 30
        self.h = 30
        pen = QPen(QColor('dodgerblue'))
        #pen   = QPen(QColor(Qt.green))
        brush = QBrush(pen.color())
        #brush = QBrush(pen.color().darker(150))

        # As opposed to using QPen and QBrush, this colors the periphery only
        #dot = scene.addEllipse(self.x, self.y, self.w, self.h, QColor('dodgerblue'))

        self.dot = scene.addEllipse(self.x, self.y, self.w, self.h, pen, brush)
        self.dot.setFlag(QGraphicsItem.ItemIsMovable)
Ejemplo n.º 13
0
    def mostrar(self, raiz):
        scene = QGraphicsScene()

        elipse = scene.addEllipse(0, 0, 100, 50)
        elipse.setBrush(QColor(245, 235, 255))

        text = scene.addText(raiz.getRaiz())

        text1 = scene.addText("RAIZ")

        self.raiz = Nodo(elipse, [text, text1])

        self.conteo = np.zeros(self.controlador.getNAtributos() + 1)
        self.conteo[0] = 2

        if (raiz.getHijos()):
            self.recurrir(raiz.getHijos(), 0, scene, self.raiz)
            self.redim(self.raiz, 0, scene)
            self.unir(self.raiz, scene)

        self.ui.viewer.setScene(scene)
        self.ui.viewer.show()
        self.ui.viewer.verticalScrollBar().setValue(self.ui.viewer.verticalScrollBar().minimum())
        self.ui.viewer.horizontalScrollBar().setValue(int(self.ui.viewer.horizontalScrollBar().maximum() / 2))
Ejemplo n.º 14
0
class BoardGUI(QWidget):
    """cointain the graphical representation of the Board"""

    # ratio of bordersize compared to the size of one base square
    borderRatio = 0.8
    baseRectRatio = 14/15  # 12/13 for normal ratio but looks weird
    stoneScale = 0.46

    # siganl
    stoneClicked = pyqtSignal(tuple)

    def __init__(self, parent, game):
        super().__init__()

        self.initUI(game)

    def initUI(self, game):
        self.board = game.currentBoard
        self.game = game

        self.showCoords = True
        self.scene = QGraphicsScene()

        # grid containing coordinates for the scene
        self.grid = []
        self.drawGrid()

        # initialize and set layout + view
        self.view = QGraphicsView(self.scene)
        self.view.setMouseTracking(True)
        self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        self.setMouseTracking(True)
        box = QHBoxLayout()
        box.addWidget(self.view)
        self.setLayout(box)

        # stones for all positions are created and listed in self.pos dict
        self.createPosition()
        self.makeCoords()  # has to be called after drawGrid!

    def resizeEvent(self, e):
        self.view.fitInView(self.view.scene().sceneRect(), Qt.KeepAspectRatio)

    def boardWidth(self):
        """returns the max width fitting into widget"""
        width = self.contentsRect().width()*0.95
        height = self.contentsRect().height()*0.95

        return min(width, height*self.baseRectRatio)

    def boardHeight(self):
        """returns the max width fitting into widget """
        return self.boardWidth()*(1/self.baseRectRatio)

    def makeGrid(self):
        """
        returns coords [[(x, y)]] for the Grid according
         to current window mesures
        """
        # set scenesize to window size
        self.scene.setSceneRect(0, 0, self.boardWidth(), self.boardHeight())
        denom = self.board.size + 2*self.borderRatio
        baseWidth = self.boardWidth() / denom
        baseHeight = self.boardHeight() / denom

        leftOffset = 0.5*baseWidth  # (self.contentsRect().width()-self.boardWidth())/2
        topOffset = 0  # (self.contentsRect().height()-self.boardHeight())/2

        partionWidth = [leftOffset+(self.borderRatio+x)*baseWidth
                        for x in range(self.board.size)]
        partionHeight = [topOffset+(self.borderRatio+x)*baseHeight
                         for x in range(self.board.size)]

        grid = [[(x, y) for x in partionWidth] for y in partionHeight]
        self.grid = grid
        self.baseWidth = baseWidth

    def drawGrid(self):
        """draws the background grid"""
        self.makeGrid()
        for line in self.grid:
            self.scene.addLine(*line[0], *line[-1])
        for (pointT, pointB) in zip(self.grid[0], self.grid[-1]):
            self.scene.addLine(*pointT, *pointB)
        self.drawHoshis()

    def makeCoords(self):
        """ draws Coordinates """
        xLabels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
        yLabels = list(range(1, 26))
        botGrid = []
        leftGrid = []
        # generate pixel coordinates grids
        for n in range(self.board.size):
            (xBot, yBot) = self.grid[self.board.size-1][n]
            yBot += self.baseWidth*0.4/self.baseRectRatio
            xBot -= self.baseWidth*0.1
            botGrid.append((xBot, yBot))
            (xLeft, yLeft) = self.grid[n][0]
            xLeft -= self.baseWidth*1.2
            yLeft -= self.baseWidth*0.3/self.baseRectRatio
            leftGrid.append((xLeft, yLeft))
        # generate Text items and add them to group
        self.coordGroup = QGraphicsItemGroup()
        for n in range(self.board.size):
            leftText = QGraphicsSimpleTextItem(str(yLabels[n]))
            leftText.setPos(*leftGrid[n])
            self.coordGroup.addToGroup(leftText)
            bottomText = QGraphicsSimpleTextItem(xLabels[n])
            bottomText.setPos(*botGrid[n])
            self.coordGroup.addToGroup(bottomText)
        # draw coordinates and update visibility according to self.showCoords
        self.scene.addItem(self.coordGroup)
        self.updateCoords()

    def updateCoords(self):
        """ slot that updates the visibility os the coordiantes. """
        self.coordGroup.setVisible(self.showCoords)

    def setCoordVis(self, visibility):
        """ set the self.showCoords boolean """
        self.showCoords = visibility
        self.updateCoords()

    def drawHoshis(self):
        """ Draws Hoshi dots"""
        hoshis = []
        rad = self.baseWidth*0.15
        for (x, y) in self.board.getHoshis():
            hoshis.append(self.grid[x][y])
        for point in hoshis:
            (x, y) = point
            self.scene.addEllipse(x-rad, y-rad, rad*2.0, rad*2.0,
                                  QPen(), QBrush(Qt.SolidPattern))

    def updatePosition(self):
        """
        sets the colors for all stones in self.pos according
        to the status in self.board
        """
        for (x, y) in self.pos:
            color = self.game.currentBoard.getPosition(x, y)
            self.pos[(x, y)].setMark(None)
            self.pos[(x, y)].setColor(color)
        lastMove = self.game.currentBoard.lastMove
        if lastMove:
            self.pos[lastMove].setMark(GoMarks.circel)
        ko = self.game.currentBoard.ko
        if ko:
            self.pos[ko].setMark(GoMarks.square)

    def createPosition(self):
        """
        Creates the self.pos dictionary containing all possible stones on the
        board initialized as empty stones

        also connects a signal form each stone to ???
        """
        self.pos = {}
        radius = self.stoneScale*self.baseWidth
        for row in range(self.board.size):
            for col in range(self.board.size):
                (x, y) = self.grid[row][col]
                newStone = Stone(x, y, radius)
                self.pos[(row, col)] = newStone
                self.scene.addItem(newStone)
        self.updatePosition()
        self.connecting()

    def connecting(self):
        for key in self.pos:
            self.pos[key].clicked.connect(lambda key=key: self.resend(key))

    def resend(self, pos):
        """
        emits the captured signal again,
        with (int, in) parameter for stone clicked
        """
        self.stoneClicked.emit(pos)
Ejemplo n.º 15
0
class panel(QGraphicsView):
    def __init__(self):
        super(panel, self).__init__()

        self.arbolito = None  #arbol de entornos

        self.y = 50  #posicion en y inicial
        self.escena = QGraphicsScene()  #escena de dibujo

        self.setScene(
            self.escena)  #asignamos la escena al QGraphicsView de la clase

    # -------------------------------------------------------------------------------------------------
    #           metodo que verifica cuando se hace click en la escena
    # -------------------------------------------------------------------------------------------------
    def mousePressEvent(self, event):
        print("clicked")
        x = event.pos().x()
        y = event.pos().y()
        print(x, y)
        pt = self.mapToScene(
            event.pos()
        )  #se escala la posicion de click del QGraphicsView a la escena (QGraphicsScene)

        root = self.arbolito.get_root()  #raiz del arbol
        if (root != None):
            rect = QRect(
                int(pt.x()), int(pt.y()), root.tam,
                root.tam)  # se crea un rectangulo para la colision con el nodo
            self.__colision(root, rect)

    # -------------------------------------------------------------------------------------------------
    #           metodo que verifica si el evento del click se realizo sobre algun nodo
    # -------------------------------------------------------------------------------------------------
    def __colision(self, nodo, rect):

        #si el nodo entrante fue el clickeado
        if nodo.rect.intersects(rect):

            #se muestra un mensaje
            #con la informacion del nodo-> nombre del procedimiento o funcion
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)

            msg.setText("Nombre Ambiente: " + str(nodo.info))
            msg.exec_()

            return True
        else:
            #si no se mira si se hizo el click en alguno de los hijos
            for i in nodo.childrens:
                self.__colision(i, rect)

    # -------------------------------------------------------------------------------------------------
    #       metodo que limpia la escena y llama al metodo de pintado del arbol
    # -------------------------------------------------------------------------------------------------
    def dibujar(self):

        #self.arbolito.get_root().print_tree()
        self.escena.clear()
        self.pintar()

    # -------------------------------------------------------------------------------------------------
    #       metodo publico que llama el pintado del arbol y sus lineas desde la razi
    # -------------------------------------------------------------------------------------------------
    def pintar(self):

        root = self.arbolito.get_root()
        self.y = 50
        self.__pintar_arbol(root, 10, self.y)
        self.__lineas(root)

    # -------------------------------------------------------------------------------------------------
    #      metodo que pinta todos los nodos del arbol
    # -------------------------------------------------------------------------------------------------
    def __pintar_arbol(self, nodo, x, y):

        pen = QPen(Qt.black)  #lapiz de nodo normal
        pen2 = QPen(Qt.green)  #lapiz de nodo actual
        nodo.x = x  #se asigna posicion x al nodo
        nodo.y = self.y  #se asigna posicion y al nodo

        nodo.rect = QRect(
            nodo.x, nodo.y, nodo.tam, nodo.tam
        )  # se crea un rectangulo para el nodo,para los eventos click

        #print("Pos x : ",nodo.x,"Pos y : ",nodo.y," Dato :",nodo.data," Info : ",nodo.info)

        xp = nodo.tam / 2
        #self.escena.addRect(nodo.rect,pen)
        if nodo.activo:
            self.escena.addEllipse(nodo.x, nodo.y, nodo.tam, nodo.tam, pen2)
        else:
            self.escena.addEllipse(nodo.x, nodo.y, nodo.tam, nodo.tam, pen)

        #texto del nodo
        text = self.escena.addText(str(nodo.data))
        text.setPos(QPointF(nodo.x + 2, nodo.y - 3))

        x += 50

        ##pintar los hijos
        for i in nodo.childrens:
            self.y += 40
            self.__pintar_arbol(i, x, self.y)

    # -------------------------------------------------------------------------------------------------
    #   metodo que pinta las lineas de relacion en el arbol
    # -------------------------------------------------------------------------------------------------
    def __lineas(self, nodo):

        pen = QPen(Qt.black)
        xp = nodo.tam / 2
        for i in nodo.childrens:
            xl1_a = nodo.x + nodo.tam + 5
            yl1_a = nodo.y + nodo.tam - 5

            ylb = i.y + xp
            self.escena.addLine(nodo.x + nodo.tam, yl1_a, xl1_a, yl1_a)
            self.escena.addLine(xl1_a, yl1_a, xl1_a, ylb, pen)
            self.escena.addLine(xl1_a, ylb, i.x, ylb, pen)
            self.__lineas(i)
Ejemplo n.º 16
0
class MapPainter(object):
    def __init__(self, parent, view, displayCities, displayConnections,
                 displayBestUnit):
        super().__init__()
        self.view = view
        self.displayCities = displayCities
        self.displayConnections = displayConnections
        self.displayBestUnit = displayBestUnit
        self.problemMap = None
        self.bestUnit = None

        self.scene = QGraphicsScene(parent)
        self.resizeScene()

        self.view.setScene(self.scene)
        self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

    def resizeScene(self):
        height = self.view.size().height()
        width = self.view.size().width()
        self.scene.setSceneRect(0.0, 0.0, width, height)

    def setProblemMap(self, problemMap):
        self.problemMap = problemMap

    def setBestUnit(self, unit):
        self.bestUnit = unit

    def setDisplayCities(self, enabled=False):
        self.displayCities = bool(enabled)

    def setDisplayConnections(self, enabled=False):
        self.displayConnections = bool(enabled)

    def setDisplayBestUnit(self, enabled=False):
        self.displayBestUnit = bool(enabled)

    def repaint(self):
        if self.problemMap is None:
            return

        self.scene.clear()
        self.resizeScene()
        height = self.scene.height()
        width = self.scene.width()

        if self.displayCities:
            cityBrush = QBrush(QColor(0, 0, 0), Qt.SolidPattern)
            cityPen = QPen(cityBrush, 5.0)
            for city in self.problemMap.cities:
                x = width * city.positionX
                y = height * city.positionY
                self.scene.addEllipse(x, y, 4, 4, cityPen, cityBrush)

        if self.displayConnections:
            connectionBrush = QBrush(QColor(0, 0, 255), Qt.SolidPattern)
            connectionPen = QPen(connectionBrush, 1.0)
            for city in self.problemMap.cities:
                for neighbour in city.connections:
                    x = width * city.positionX
                    y = height * city.positionY
                    x2 = width * self.problemMap.cities[neighbour].positionX
                    y2 = height * self.problemMap.cities[neighbour].positionY
                    self.scene.addLine(x, y, x2, y2, connectionPen)

        if self.displayBestUnit and self.bestUnit is not None:
            bestUnitBrush = QBrush(QColor(255, 0, 0), Qt.SolidPattern)
            bestUnitPen = QPen(bestUnitBrush, 2.0)
            for i in range(-1, len(self.bestUnit.path) - 1):
                currCity = self.problemMap.cities[self.bestUnit.path[i]]
                nextCity = self.problemMap.cities[self.bestUnit.path[i + 1]]
                x = width * currCity.positionX
                y = height * currCity.positionY
                x2 = width * nextCity.positionX
                y2 = height * nextCity.positionY
                self.scene.addLine(x, y, x2, y2, bestUnitPen)

        self.view.fitInView(self.scene.sceneRect())
Ejemplo n.º 17
0
class SunMoonWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setupGraphicsScene()
        self.configuration = tombo.configfile.ConfigFile('sunmoon.conf')
        self.getConfiguration()
        self.minimum_interval = self.miscellaneous['minimum_interval']
        self.setLocation()
        self.timer = QTimer()
        self.setupMethods()
        self.setCurrentDate()
        self.setConfigurationText()
        self.displayedDate = QDateTime(self.ui.deDate.date())
        self.show()

    def setLocation(self):
        self.location = Location((self.astral['name'], self.astral['region'], float(self.astral['latitude']), float(self.astral['longitude']), self.astral['timezone'], self.astral['elevation']))

    def getConfiguration(self):
        self.astral = self.configuration.getItems('ASTRAL')
        self.miscellaneous = self.configuration.getItems('MISCELLANEOUS')

    def setConfigurationText(self):
        config_label_text_color = "#" + self.miscellaneous['config_text_color']
        self.ui.leLatitude.setText(self.astral['latitude'])
        self.ui.lblLatitude.setText("<font color='" + config_label_text_color + "'>" + self.astral['latitude'] + "</font>")
        self.ui.leLongitude.setText(self.astral['longitude'])
        self.ui.lblLongitude.setText("<font color='" + config_label_text_color + "'>" + self.astral['longitude'] + "</font>")
        self.ui.leElevation.setText(self.astral['elevation'])
        self.ui.lblElevation.setText("<font color='" + config_label_text_color + "'>" + self.astral['elevation'] + "</font>")
        self.ui.leLocation.setText(self.astral['name'])
        self.ui.lblLocation.setText("<font color='" + config_label_text_color + "'>" + self.astral['name'] + "</font>")
        self.ui.leCountry.setText(self.astral['region'])
        self.ui.lblRegion.setText("<font color='" + config_label_text_color + "'>" + self.astral['region'] + "</font>")
        self.ui.leTimeZone.setText(self.astral['timezone'])
        self.ui.lblTimeZone.setText("<font color='" + config_label_text_color + "'>" + self.astral['timezone'] + "</font>")
        self.ui.leMinimumInterval.setText(self.miscellaneous['minimum_interval'])
        self.ui.leTextColor.setText(self.miscellaneous['config_text_color'])

    def setCurrentDate(self):
        self.ui.deDate.setDate(QDate.currentDate())
        self.displayedDate = QDateTime(self.ui.deDate.date())

    def setupGraphicsScene(self):
        self.scene = QGraphicsScene()
        self.scene.setBackgroundBrush(Qt.black)
        self.scene.setSceneRect(0, 0, 209, 169)
        self.ui.gvMoon.setScene(self.scene)
        self.brushWhite = QBrush(QColor(Qt.white))
        self.brushBlack = QBrush(QColor(Qt.black))
        self.pen = QPen(Qt.NoPen)
        self.ellipseWhite = self.scene.addEllipse(50, 30, 100, 100, self.pen, self.brushWhite)
        self.ellipseBlack = self.scene.addEllipse(50, 30, 100, 100, self.pen, self.brushBlack)

    def setupMethods(self):
        self.ui.deDate.dateChanged.connect(self.setTimes)
        self.ui.pbStart.clicked.connect(lambda: self.autoStartStop("start"))
        self.ui.pbStop.clicked.connect(lambda: self.autoStartStop("stop"))
        self.ui.pbSave.clicked.connect(lambda: self.configActions("save"))
        self.ui.pbDiscard.clicked.connect(lambda: self.configActions("discard"))
        self.ui.pbClear.clicked.connect(lambda: self.configActions("clear"))
        self.timer.timeout.connect(self.advanceDate)
        self.ui.pbSetCurrentDate.clicked.connect(self.setCurrentDate)

    #----------------------------------------------------------------------
    def configActions(self, action):
        """Some pushbutton actions route here."""
        #print(action)
        if action == 'clear':
            self.clearConfigFields()
        elif action == 'discard':
            self.clearConfigFields()
            self.setConfigurationText()
        elif action == 'save':
            self.saveConfiguration()

    #----------------------------------------------------------------------
    def saveConfiguration(self):
        """Save info from config fields."""
        self.configuration.setValue('MISCELLANEOUS', 'minimum_interval', self.ui.leMinimumInterval.text())
        self.configuration.setValue('MISCELLANEOUS', 'config_text_color', self.ui.leTextColor.text())
        self.configuration.setValue('ASTRAL', 'latitude', self.ui.leLatitude.text())
        self.configuration.setValue('ASTRAL', 'longitude', self.ui.leLongitude.text())
        self.configuration.setValue('ASTRAL', 'elevation', self.ui.leElevation.text())
        self.configuration.setValue('ASTRAL', 'timezone', self.ui.leTimeZone.text())
        self.configuration.setValue('ASTRAL', 'name', self.ui.leLocation.text())
        self.configuration.setValue('ASTRAL', 'region', self.ui.leCountry.text())
        self.getConfiguration()
        self.setConfigurationText()

    #----------------------------------------------------------------------
    def clearConfigFields(self):
        """Clear text from all config tab fields."""
        self.ui.leLatitude.setText('')
        self.ui.leLongitude.setText('')
        self.ui.leElevation.setText('')
        self.ui.leLocation.setText('')
        self.ui.leCountry.setText('')
        self.ui.leTimeZone.setText('')
        self.ui.leMinimumInterval.setText('')
        self.ui.leTextColor.setText('')
        
    #----------------------------------------------------------------------
    def discardConfigFields(self):
        """Clear all config fields and repopulate with original text."""
        self.clearConfigFields()
        self.setConfigurationText()
        

    def autoStartStop(self, action):
        if action == 'start':
            if self.ui.sbInterval.value() == 0:
                self.timer.setInterval(int(self.miscellaneous['minimum_interval']))
            else:
                self.timer.setInterval(self.ui.sbInterval.value() * 1000)
            self.timer.start()
        elif action == 'stop':
            self.timer.stop()

    def advanceDate(self):
        self.displayedDate = self.displayedDate.addDays(1)
        self.ui.deDate.setDate(self.displayedDate.date())

    def setTimes(self):
        date_displayed = self.ui.deDate.date().toPyDate()
        astral_info = self.location.sun(date_displayed)
        self.ui.leSunrise.setText(astral_info['sunrise'].strftime('%I:%M %p'))
        self.ui.leSunset.setText(astral_info['sunset'].strftime('%I:%M %p'))
        self.ui.leDaylight.setText(self.calcDaylight(astral_info['sunset'] - astral_info['sunrise']))
        self.ui.leMoonPhase.setText('Day ' + str(self.location.moon_phase(date_displayed, type(float))))
        self.setMoonPhase(self.location.moon_phase(date_displayed, type(float)))
        #print(self.location.moon_phase(date=None, rtype=type(float)))

    def calcDaylight(self, timedelta):
        return '{} hours, {} minutes'.format(timedelta.seconds // 3600, (timedelta.seconds // 60) % 60)

    def setMoonPhase(self, moon_phase):
        #print(moon_phase)
        increment = 100 / 14
        self.scene.removeItem(self.ellipseBlack)

        if moon_phase < 15:
            self.ellipseBlack = self.scene.addEllipse((moon_phase * -increment) + 50, 30, 100, 100, self.pen, self.brushBlack)
        else:
            self.ellipseBlack = self.scene.addEllipse(((moon_phase - 28) * -increment) + 50, 30, 100, 100, self.pen, self.brushBlack)
Ejemplo n.º 18
0
class Battlefield(QGraphicsView):
    """The graphical battlefield."""

    click = pyqtSignal(int)
    start = pyqtSignal()
    stop = pyqtSignal()

    def __init__(self, path: str):
        super().__init__()

        self.load_from_file(path)
        self.possible_colors = {"health": 0, "strength": 1, "braveness": 2}
        self.unit_size = 10
        self.scene = QGraphicsScene()
        self.grid_size = 50
        self.colormap = 0
        self.background = QPixmap("gui/fond.png")
        self.zoom_level = 1
        self.selected_unit = 0
        self.edit = False
        self.simu = False

        self.wait = False

        self.mousePressEvent = self.on_mousePressEvent
        self.mouseMoveEvent = self.on_mouseMoveEvent
        self.mouseReleaseEvent = self.on_mouseReleaseEvent

        self.setGeometry(300, 300, self.grid_size * 10, self.grid_size * 10)
        self.setScene(self.scene)
        self.show()
        self.draw()

    def get_specs_tables(self):
        SPECS = [[[], []], [[], []], [[], []]]

        for i in range(self.size):
            speci = [[0, 0], [0, 0], [0, 0], [0, 0]]
            for unit in self.simulation.units(i):
                speci[0][unit.side] += 1
                speci[1][unit.side] += unit.health
                speci[2][unit.side] += unit.strength
                speci[3][unit.side] += unit.braveness

            for j in range(3):
                for k in range(2):
                    SPECS[j][k].append(speci[j + 1][k] / speci[0][k])
        return SPECS

    def load_from_file(self, path: str):
        self.simulation = read_battle(path)
        self._state = 0
        self._size = self.simulation.size

    def update(self, state_step: int):
        """Update the graphics and the grid between two steps."""
        step_validity = 0 <= self._state + state_step < self.simulation.size
        if step_validity:
            self._state += state_step
            self.draw()
        return step_validity

    def go_to_state(self, state):
        """Move animation to given state."""
        if 0 <= state < self.simulation.size:
            self._state = int(state)
            self.draw()

    def zoom(self, precision: float):
        """Zoom in on the picture."""
        self.zoom_level *= precision
        self.resetCachedContent()
        self.draw()

    def get_unit(self, index: int):
        """Access specific unit."""
        return self.simulation.units(self._state)[index]

    @property
    def size(self):
        """Get the size of the simulation."""
        return self._size

    @property
    def state(self):
        """Get the current state."""
        return self._state

    def change_colormap(self, color: str):
        """Change the colormap."""
        if color in self.possible_colors:
            self.colormap = self.possible_colors[color]
            self.draw()

    def unit_position(self, unit):
        """Get screen position of unit."""
        return (unit.coords + 10) * self.unit_size * self.zoom_level

    def on_mousePressEvent(self, event):
        pos = self.mapToScene(event.pos())
        click = np.array((pos.x(), pos.y()))
        for i, unit in enumerate(self.simulation.units(self.state)):
            unit_pos = self.unit_position(unit)
            if np.all(unit_pos <= click) and np.all(
                    click <= unit_pos + self.unit_size):
                self.click.emit(i)
                self.selected_unit = i
                self.draw()
                break
        else:  # no unit found under pointer
            pos = event.pos()
            self.centerOn(pos.x(), pos.y())

    def on_mouseMoveEvent(self, event):
        if self.edit:
            self.draw()
            pos = self.mapToScene(event.pos())
            self.scene.addRect(pos.x(), pos.y(), self.unit_size,
                               self.unit_size, QPen(),
                               QBrush(QColor(0, 255, 0, 125)))
            QTest.qWait(10)

    def on_mouseReleaseEvent(self, event):
        if self.edit:
            pos = self.mapToScene(event.pos())
            new_x = (pos.x() / (self.zoom_level * self.unit_size)) - 10
            new_y = (pos.y() / (self.zoom_level * self.unit_size)) - 10
            self.simulation.units(
                self.state)[self.selected_unit].coords = np.array(
                    [new_x, new_y])
            self.draw()
            if self.simu:
                self.instant_export()

    def change_mod(self):
        self.edit = not (self.edit)

    def change_simu(self):
        self.simu = not (self.simu)

    def gen_color(self, index, unit):
        """Generate a colormap for unit."""
        def specs(unit):
            if not unit.is_centurion:
                return [unit.health, unit.strength, unit.braveness]
            return [0, 0, 0]

        max_val = max(
            [specs(unit)[index] for unit in self.simulation.units(0)])
        shade = 150 * (specs(unit)[index] / max_val) + 105
        color = [0, 0, 0]
        color[2 * unit.side] = shade
        return QColor(*color)

    def draw_unit(self, unit, pen, brush):
        position = self.unit_position(unit)
        if unit.reach >= 5:
            self.scene.addEllipse(*position, *[self.unit_size] * 2, pen, brush)
        else:
            self.scene.addRect(*position, *[self.unit_size] * 2, pen, brush)

    def draw_image(self, image):
        def shape(dim):
            return int(dim * (1 + self.zoom_level))

        self.scene.addPixmap(
            image.scaled(*map(shape, (image.width(), image.height()))))

    def draw(self):
        """Draw the units and background."""
        self.scene.clear()
        self.draw_image(self.background)

        # shuffle so that we also see blue units
        state = self.simulation.units(self.state)
        for unit in state:
            if not unit.is_dead:
                if not unit.is_centurion:
                    color = self.gen_color(self.colormap, unit)
                else:
                    if unit.side == 0:
                        color = QColor(255, 0, 0)
                    else:
                        color = QColor(0, 0, 255)
                self.draw_unit(unit, QPen(), QBrush(color))
        self.draw_unit(state[self.selected_unit], QPen(),
                       QBrush(QColor(0, 255, 0)))

    def export(self, name):
        """To export the current state"""
        if not (self.wait):
            self.wait = True
            self.scene.addRect(
                -10, -10, int(self.background.width() * (1 + self.zoom_level)),
                int(self.background.height() * (1 + self.zoom_level)), QPen(),
                QBrush(QColor(255, 255, 255)))
            loading = QLabel()
            gif_load = QMovie("gui/loading.gif")
            loading.setMovie(gif_load)
            gif_load.start()
            self.scene.addWidget(loading)
            QTest.qWait(200)
            make_battle(self.simulation.state(self.state), name)
            QTest.qWait(200)
            self.draw()
            self.wait = False

    def instant_export(self):
        if not (self.wait):
            self.export("data/new.txt")
            self.load_from_file("data/new.txt")
Ejemplo n.º 19
0
class IdpRecording(QWidget):
    def __init__(self):
        super().__init__()
        # -------------------- First class --------------------
        self.main_page = QHBoxLayout(self)
        self.setLayout(self.main_page)

        # -------------------- Second class --------------------
        # 1. input block (vertical)
        # 2. instruction block (horizontal)
        self.input_block = init_container(parent=self.main_page,
                                          vertical=True,
                                          style=None)

        self.instruction_block = init_container(parent=self.main_page,
                                                vertical=False,
                                                style="background-color: white;",
                                                size=config.instruction_block_size)
        # -------------------- third class --------------------
        #   1. Input block
        #       1-1. Interval last
        #       1-2. Repeats
        #       1-3. Classes
        #       1-4. Subject name
        #       1-5. Training data directory
        #       1-6. Buttons + help

        self.interval_last_block, self.interval_slider_view = init_slider_bar_box(self.input_block,
                                                                                  label=config.operation_interval_label,
                                                                                  max_value=config.recording_interval)

        self.repeats_block, self.repeat_slider_view = init_slider_bar_box(self.input_block,
                                                                          label=config.operation_repeats_label,
                                                                          max_value=config.repeat_times)

        self.classes_block, self.classes_textbox = init_inputBox(self.input_block,
                                                                 label=config.operation_classes_label,
                                                                 label_bold=False,
                                                                 default_input=config.indexPen_classes_default)

        self.subject_name_block, self.subject_names_textbox = init_inputBox(self.input_block,
                                                                            label=config.operation_subject_name_label,
                                                                            label_bold=False,
                                                                            default_input=
                                                                            config.indexPen_subjectName_default)

        self.training_dir_block, self.training_dir_textbox = init_inputBox(self.input_block,
                                                                           label=config.trainingDataPath_label,
                                                                           label_bold=False,
                                                                           default_input=
                                                                           config.indexPen_trainingDataDir_default)

        # -------------------- fourth class --------------------
        #   1-6. Buttons + help (horizontally distributed)
        #       1-6-1. Buttons
        #       1-6-2. Help (message box)

        self.buttons_block = init_container(self.input_block, vertical=False)
        self.help_block = init_container(self.input_block)

        # -------------------- fifth class --------------------
        #       1-6-1. Buttons
        #           1-6-1-1. Interrupt
        #           1-6-1-2. Start/end test
        #           1-6-1-3. Start Recording

        self.interrupt_btn = init_button(parent=self.buttons_block,
                                         label=config.interrupt_btn_label,
                                         function=self.interrupt_btn_action)

        self.test_btn = init_button(parent=self.buttons_block,
                                    label=config.test_btn_start_label,
                                    function=self.test_btn_action)

        self.recording_btn = init_button(parent=self.buttons_block,
                                         label=config.record_btn_start_label,
                                         function=self.recording_btn_action)

        self.help_btn = init_button(parent=self.buttons_block,
                                    label=config.help_btn_label,
                                    function=help_btn_action)

        # -------------------- third class --------------------
        #   1. Instruction block (horizontal)
        #       1-1. circles block (vertical)
        #       1-2. text block (vertical)

        self.counter_block = init_container(parent=self.instruction_block, vertical=True,
                                            size=config.counter_block_size)
        self.ist_text_block = init_container(parent=self.instruction_block, vertical=True,
                                             size=config.ist_text_block_size)
        # -------------------- fourth class --------------------
        #       1-1. circles block (vertical)
        #           1-1-1. circles_view
        #               1-1-1-1. circles_scene
        #                   1-1-1-1. 4 circles drawn to the scene

        self.metronome_scene = QGraphicsScene()
        self.metronome_view = QGraphicsView(self.metronome_scene)
        # positions of the four circles
        # stored for redraw
        self.x1, self.x2, self.x3, self.x4, self.y1, self.y2, self.y3, self.y4, self.circle_scene_width, \
        self.circle_scene_height = self.setup_canvas()
        # show the circles
        self.paint(first_circle_colored=False)

        # -------------------- fourth class --------------------
        #       1-2. text block (vertical)
        #           ------- preparation -------
        #           1-1-1. "You will be writing:
 "
        #                  char_set ::= A sequence of text the user will write
        #                  "Press Enter To Continue"
        #
        #           ------- forecast ------
        #           1-1-1. Label1: Forecast
        #
        #           ------- record ------
        #           1-1-1. Label1: "Write"
        #                  character to write
        #                  "...next" + next character to write

        # will be initialized when the user presses enter/return after preparation
        self.countdown_block, self.countdown_label = None, None
        # will be initialized when the forecast animation is over
        self.lb_char_to_write, self.lb_char_next = None, None

        self.show()

        # ============================= others ==========================

        # get input values
        self.interval = self.interval_slider_view.slider.value()
        self.repeat_times = self.repeat_slider_view.slider.value()
        # stored in a list
        self.classes = self.get_classes()
        self.subject_name = self.get_subject_name()
        self.training_dir = self.get_training_data_dir()
        self.char_set = generate_char_set(self.classes, self.repeat_times)

        # ======================= indicators, counters ==========================
        self.state = ['idle']  # see the docstring of self.update_state for details

        # tracking if the user pressed the return key to start recording
        self.is_dir_valid = False
        self.cur_countdown, self.tempo_counter = 0, 0

        self.reset_instruction()

        # =========================== timers =============================
        self.timer = QtCore.QTimer()
        self.timer.setTimerType(QtCore.Qt.PreciseTimer)
        self.timer.setInterval(self.interval * 1000)
        self.timer.timeout.connect(self.ticks)
        self.timer.start()
        # self.count = 0
        # self.start_time = time.time()


    def update_state(self, action):
        """
        update the current state based on action
        The working states, as oppose to 'idle' include that of 'pending', 'testing', 'countingDown', 'writing'
        @param action: str: issued with the following functions with the corresponding value:
            * self.keyPressEvent(): 'enter_pressed'
            * self.countdown_tick(): 'countdown_over'
            * self.test_btn_action(): 'start_test'
            * self.update_state: 'countdown_over'  @@for restarting writing when in test mode
        @note: you will see that there's a slight pause at the start of writing and the instruction says writing '...',
                this is an expected behavior as we are not updating the states in a clock, but rather posting to the
                state changes in function class. It's not a bug, it's a feature!
        """
        if action == 'test_pressed':
            if 'idle' in self.state:  # start the test mode
                self.idle_to_pending()
                self.state = ['testing', 'pending']
            else:  # back to idle
                self.update_state('interrupt')  # this is equivalent to issuing an interrupt action
        # break pending state and start count down
        elif action == 'enter_pressed':
            if 'pending' in self.state:
                self.state.remove('pending')
                self.state.append('countingDown')
                self.pending_to_countdown()
        elif action == 'countdown_over':
            if 'countingDown' in self.state:  # countingDown may not be in the states if looping in test mode
                self.state.remove('countingDown')
            self.state.append('writing')
            self.countdown_to_writing()
        elif action == 'writing_over':
            self.state.remove('writing')
            if 'testing' in self.state:  # restart writing if in test mode
                self.update_state('countdown_over')
            elif '':
                pass  # TODO implement writing over when in recording mode
            else:
                raise Exception('Unknown State change')
        elif action == 'interrupt':
            self.working_to_idle()  # working includes that
            self.state = ['idle']
        else:
            raise Exception('Unknown State change')
        self.resolve_state()

    def resolve_state(self):
        if 'testing' in self.state:
            self.test_btn.setText(config.test_btn_end_label)
            self.recording_btn.setDisabled(True)
        else:
            self.test_btn.setText(config.test_btn_start_label)
            self.recording_btn.setDisabled(False)

    def idle_to_pending(self):
        self.get_experiment_config()
        self.char_set = generate_char_set(self.classes, self.repeat_times)
        init_preparation_block(parent=self.ist_text_block, text=self.char_set)

    def working_to_idle(self):
        self.reset_instruction()

    def pending_to_countdown(self):
        # clear the preparation text block
        self.reset_instruction()
        # create the forecast block
        self.countdown_block, self.countdown_label = init_countdown_block(self.ist_text_block,
                                                                          label="   ",
                                                                          font=36,
                                                                          bold=True)

    def countdown_to_writing(self):
        clear_layout(self.ist_text_block)
        self.reset_instruction()
        self.lb_char_to_write, self.lb_char_next = init_instruction_text_block(self.ist_text_block)

    def keyPressEvent(self, key_event):
        print(key_event)
        if is_enter_key_event(key_event):
            self.update_state('enter_pressed')

    @pg.QtCore.pyqtSlot()
    def ticks(self):
        """
        check the current state
        ticks every 'refresh' milliseconds
        """
        # duration = time.time() - self.start_time
        # self.count += 1
        if 'pending' in self.state:
            pass
        elif 'countingDown' in self.state:
            self.countdown_tick()
        elif 'writing' in self.state:
            self.metronome_tick()
        pass

    @pg.QtCore.pyqtSlot()
    def countdown_tick(self):
        # after the text block shows all countdown texts, stop updating, do nothing and return
        if self.cur_countdown == len(config.countdown_animation_text):
            self.cur_countdown += 1
            return
        # wait for a given interval and start the input timer
        elif self.cur_countdown > len(config.countdown_animation_text):  # end of counting down
            self.update_state('countdown_over')
        else:
            self.countdown_label.setText(config.countdown_animation_text[self.cur_countdown])
            self.cur_countdown += 1

    def metronome_tick(self):
        # tempo: dah, dih, dih,dih
        self.repaint(circle=self.tempo_counter % 4 + 1)
        if not self.tempo_counter % 4:
            dah()
            char_count = int(self.tempo_counter / 4)
            if char_count < len(self.char_set):
                # draw a new one
                cur_char = self.char_set[char_count]
                next_char = 'no Next' if (char_count + 1) == len(self.char_set) else self.char_set[char_count + 1]
                self.lb_char_to_write.setText(cur_char)
                self.lb_char_next.setText(config.instruction_next_text + next_char)
            # finish a recording loop
            else:
                self.update_state('writing_over')
                # must return here to avoid further incrementing the tempo counter, it is reset within update_state()
                return
        else:
            dih()

        self.tempo_counter += 1

    def setup_canvas(self):

        self.counter_block.addWidget(self.metronome_view)
        self.metronome_view.resize(config.unit_size, config.WINDOW_HEIGHT / 3)
        position = self.metronome_view.pos()

        self.metronome_scene.setSceneRect(position.x(), position.y(), self.metronome_view.width(),
                                          self.metronome_view.height())

        # size of the scene
        width = self.metronome_scene.width()
        height = self.metronome_scene.height()

        # positions of circles
        x1, y1 = position.x() + width / 3, position.y()
        x2, y2 = position.x() + width / 3, position.y() + 3 * (height / 10)
        x3, y3 = position.x() + width / 3, position.y() + 6 * (height / 10)
        x4, y4 = position.x() + width / 3, position.y() + 9 * (height / 10)

        return x1, x2, x3, x4, y1, y2, y3, y4, width, height

    def repaint(self, circle=1):

        x = self.x1
        y = self.y1

        if circle == 1:
            # remove all current circles
            for item in self.metronome_scene.items():
                self.metronome_scene.removeItem(item)
            # paint them light gray
            self.paint()

        else:
            if circle == 2:
                x = self.x2
                y = self.y2
            elif circle == 3:
                x = self.x3
                y = self.y3
            elif circle == 4:
                x = self.x4
                y = self.y4

        # locate the circle
        circle = self.metronome_scene.itemAt(x, y, QTransform())
        # remove the original circle
        if circle:
            self.metronome_scene.removeItem(circle)

        # repaint a blue one
        pen = QPen(Qt.black, 5, Qt.SolidLine)
        brush = QBrush(Qt.blue, Qt.SolidPattern)
        self.metronome_scene.addEllipse(x, y,
                                        self.circle_scene_width / 3, self.circle_scene_width / 3,
                                        pen, brush)

    def paint(self, first_circle_colored=False):

        pen = QPen(Qt.black, 5, Qt.SolidLine)
        brush = QBrush(Qt.lightGray, Qt.SolidPattern)

        self.metronome_scene.addEllipse(self.x2, self.y2,
                                        self.circle_scene_width / 3, self.circle_scene_width / 3,
                                        pen, brush)
        self.metronome_scene.addEllipse(self.x3, self.y3,
                                        self.circle_scene_width / 3, self.circle_scene_width / 3,
                                        pen, brush)
        self.metronome_scene.addEllipse(self.x4, self.y4,
                                        self.circle_scene_width / 3, self.circle_scene_width / 3,
                                        pen, brush)

        if first_circle_colored:
            brush = QBrush(Qt.blue, Qt.SolidPattern)

        self.metronome_scene.addEllipse(self.x1, self.y1,
                                        self.circle_scene_width / 3, self.circle_scene_width / 3,
                                        pen, brush)

    def get_experiment_config(self):
        self.interval = self.interval_slider_view.slider.value()
        self.repeat_times = self.repeat_slider_view.slider.value()
        self.classes = self.get_classes()
        self.subject_name = self.get_subject_name()
        self.training_dir = self.get_training_data_dir()

    def get_training_data_dir(self):
        _user_input = self.training_dir_textbox.text()
        if not _user_input:
            _user_input = config.indexPen_trainingDataDir_default

        return _user_input

    def get_subject_name(self):
        _user_input = self.subject_names_textbox.text()
        if not _user_input:
            _user_input = config.indexPen_subjectName_default
        return _user_input

    def get_classes(self):
        _user_input = self.classes_textbox.text()
        if not _user_input:
            _user_input = config.indexPen_classes_default

        # change to a list
        classes = _user_input.split(" ")
        return classes

    def interrupt_btn_action(self):
        self.update_state('interrupt')

    def test_btn_action(self):
        self.update_state('test_pressed')

    def recording_btn_action(self):
        # TODO implement this action
        pass
        # if self.is_recording:
        #     self.reset()
        #
        # # if not recording yet
        # elif not self.is_recording:
        #
        #     self.get_experiment_config()
        #     # try starting recording
        #     # check the data path first
        #     self.is_dir_valid = self.check_dir_valid()
        #
        #     if self.is_dir_valid:
        #         # if valid data path, show preparation page
        #         # start recording
        #         self.is_recording = True
        #         self.prepare()
        #         self.recording_btn.setText(config.record_btn_end_label)
        #         self.countdown_timer.start()
        #
        #         msg = QMessageBox()
        #         msg.setIcon(QMessageBox.Information)
        #         msg.setText("Recording")
        #         msg.exec()

    def check_dir_valid(self):
        print(self.training_dir)
        if os.path.exists(self.training_dir):
            return True
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText(config.datapath_invalid_message)
            msg.exec()
            return False

    def reset_instruction(self):
        clear_layout(self.ist_text_block)
        for item in self.metronome_scene.items():
            self.metronome_scene.removeItem(item)
        self.paint()
        self.lb_char_next, self.lb_char_to_write = None, None
        self.cur_countdown, self.tempo_counter = 0, 0
Ejemplo n.º 20
0
 def paint(self, scene: QtWidgets.QGraphicsScene):
     scene.addEllipse(self.x(), self.y(), 1, 1, self.color, self.color)
Ejemplo n.º 21
0
class MainFunction(QMainWindow, QObject):
    def __init__(self):
        QMainWindow.__init__(self)

        # define values file upload.
        value.set_value()
        self.measureData = []
        self.tempMessage = []
        self.xlist, self.ylist, self.rlist, self.xclist, self.yclist, self.laserlist = [], [], [], [], [], []
        self.tempData = [self.measureData, self.xlist, self.ylist, self.rlist, self.xclist, self.yclist, self.laserlist]
        self.resultData = data_set.MeasureData(None)

        # start ui drawing.
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # set window view size maximum.
        self.showMaximized()

        self.message_list = [self.ui.msg_1, self.ui.msg_2, self.ui.msg_3, self.ui.msg_4, self.ui.msg_5]

        # laser connect state ui values list.
        self.uiList = [self.ui.img_Rsock, self.ui.img_Lsock, self.ui.img_Bsock]
        self.uiBList = [self.ui.img_B1, self.ui.img_B2, self.ui.laser_state_B]

        # laser state ui values list.
        self.uiLaserList = [self.ui.img_R1, self.ui.img_R2, self.ui.img_R3, self.ui.img_R4, self.ui.img_L1, self.ui.img_L2, self.ui.img_L3, self.ui.img_L4]
        self.layerlist = [self.ui.layer_R1, self.ui.layer_R2, self.ui.layer_R3, self.ui.layer_R4, self.ui.layer_L1,
                          self.ui.layer_L2, self.ui.layer_L3, self.ui.layer_L4]

        # set range.
        self.gScene = QGraphicsScene(0, 0, value.get_frame()/4, value.get_frame()/4,
                                     self.ui.graphicsView)
        self.ui.graphicsView.setScene(self.gScene)

        # socket connection start
        self.th = Socket(self, self.uiList)
        self.th.start()
        self.dialog = Connection(self.th)
        self.calculation = Calculation()

        # setting window set.
        Setting.setting = Setting(self.th, self.uiBList)
        Setting.setting.ui = Ui_SettingWindow()
        Setting.setting.ui.setupUi(Setting.setting)
        Setting.setting.btnList = [Setting.setting.ui.btn_laser, Setting.setting.ui.btn_chuck_default,
                        Setting.setting.ui.btn_frame_set, Setting.setting.ui.btn_coor_set,
                        Setting.setting.ui.btn_chuck_set, Setting.setting.ui.btn_laser_set]
        Setting.setting.ui.setting_info.setText('척 기본값 : %s\n프레임 길이 : %d\n좌표계 보정값 : %s\n척 보정값 : %s\n레이저 사이 간격 : %s'
                                                % (value.get_chuck(), value.get_frame(), value.get_coor(), value.get_chuck_scale(), value.get_laser()))

        # drawing basic view ---------------------------------------------------------------------------
        # -------------------------------------------------------------------------------------------------
        # pen, brush setting
        inside_color = QBrush(Qt.white)
        pen = QPen(Qt.red)
        pen.setWidth(4)

        # make 8 laser lines
        self.laser = []
        line = self.calculation.get_laser_location()
        for i in range(len(line)):
            line[i] = line[i] * 0.25
            self.laser.append(QGraphicsLineItem(0, (self.gScene.height() / 2-line[i]), self.gScene.width(), (self.gScene.height() / 2-line[i])))
            self.laser[i].setPen(pen)
            self.gScene.addItem(self.laser[i])

        # make circle
        pen.setColor(Qt.blue)
        self.circle = self.gScene.addEllipse(self.gScene.width() / 2 - 50,  self.gScene.height() / 2 - 50, 100, 100, pen, inside_color)
        self.circle_pot = self.gScene.addEllipse(self.gScene.width() / 2 - 2.25, self.gScene.height() / 2 - 2.25, 5, 5, pen, Qt.blue)

        # make chuck pot
        pen.setColor(Qt.red)
        self.chuck_pot = self.gScene.addEllipse(self.gScene.width() / 2 - 2.25, self.gScene.height() / 2 - 2.25, 5,
                                                5, pen, Qt.red)

        # make x, y lines
        self.x_line = QGraphicsLineItem(0, self.gScene.height() / 2, self.gScene.width(), self.gScene.height() / 2)
        self.gScene.addItem(self.x_line)
        self.y_line = QGraphicsLineItem(self.gScene.width() / 2, 0, self.gScene.width() / 2, self.gScene.height())
        self.gScene.addItem(self.y_line)

    def slot_menu(self):
        Setting.setting.show()

    def slot_exit(self):
        self.close()

    def closeEvent(self, event):
        result = QMessageBox.question(self, 'exit message', '종료하시겠습니까?', QMessageBox.Yes|QMessageBox.No)
        event.ignore()

        if result == QMessageBox.Yes:
            self.th.closet_socket()
            event.accept()

    @staticmethod
    def math_code_distinction(number):
        if number == 0:
            return '0'
        elif number > 0:
            return '+'
        else:
            return '-'

    def message_setting(self, message):
        # reset message list : new first old next.
        for i in range(len(self.message_list)-1, 0, -1):
            self.message_list[i].setText(self.message_list[i-1].text())
        self.message_list[0].setText(message)

    def double_arr(self, i, fot_int):
        temp_result = []
        for j in range(fot_int):
            temp = []
            for k in range(len(self.tempData[i])):
                temp.append(self.tempData[i][k][j])
            temp.sort()
            half = int(len(temp) / 2)
            temp_result.append(temp[half + 1])

        return temp_result[:]

    # 알고리즘 후 max choice.
    def slot_ok(self):
        self.chuck_define = Setting.setting.get_chuck()

        if len(self.chuck_define) != 2:
            # if system don't have chuck information, you can't start measure program.
            QMessageBox.question(self, 'Alert Box', '척 기본값을 먼저 셋팅해 주세요.', QMessageBox.Yes)

        else:
            # [ change ] image -> text.
            self.slot_ok_time = time.time()

            for_int = 0
            del self.measureData[:]
            del self.tempMessage[:]

            for i in range(len(self.tempData)):
                del self.tempData[i][:]

            object_name = self.sender().objectName()

            if object_name == 'btn_one':
                for_int = 1
            elif object_name == 'btn_all_ten':
                for_int = 10
            else:
                for_int = 5

            circle_scale = value.get_coor()
            chuck_scale = value.get_chuck_scale()
            self.resultData = data_set.MeasureData(None)

            for i in range(for_int):
                self.measureData.append(self.th.message('$MEASURE\0'))
                if self.measureData[i] == 'error':
                    while True:
                        self.measureData[i] = self.th.message('$MEASURE\0')
                        if self.measureData[i] != 'error':
                            break

            for i in range(for_int):
                laser_length = self.measureData[i]

                if len(laser_length) == 10:
                    pipe = self.calculation.func_calculation(laser_length)

                    # Scale pipeY, pipeZ, chuck_x, chuck_y.
                    pipeY = pipe[0] - circle_scale[0]
                    pipeZ = pipe[1] - circle_scale[1]

                    chuck_x = (laser_length[-2] - self.chuck_define[0]) - chuck_scale[0]
                    chuck_y = (laser_length[-1] - self.chuck_define[1]) - chuck_scale[1]
                    #chuck_y = (self.chuck_define[1] - laser_length[-1]) - chuck_scale[1]

                    self.tempData[1].append(pipeY)
                    self.tempData[2].append(pipeZ)
                    self.tempData[3].append(pipe[2])
                    self.tempData[4].append(chuck_x)
                    self.tempData[5].append(chuck_y)
                    self.tempData[6].append(pipe[3])

                    self.tempMessage.append('\t파이프 좌표 y, z (%d, %d) / 파이프 지름 : %d \n\t척 y, z (%d, %d)\n\t%02d:%02d:%02d'
                                            % (-pipeY, pipeZ, pipe[2] * 2, -chuck_x, chuck_y, time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec))

                else:
                    self.tempData[1].append('error')
                    self.tempData[2].append('error')
                    self.tempData[3].append(0)
                    self.tempData[4].append('error')
                    self.tempData[5].append('error')
                    self.tempData[6].append([0, 0, 0, 0, 0, 0])

                    self.tempMessage.append('\t측정이 잘못되었습니다. 측정을 다시 시도해주세요.\n\t%02d:%02d:%02d' %(time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec))

            result = []
            half = int(for_int/2)
            for i in range(len(self.tempData)):

                if object_name == 'btn_one':
                    if self.tempData[i][0] == 'error':
                        self.resultData.errorFlag = True
                        break

                    else:
                        result.append(self.tempData[i][0])

                else:
                    if i == 0:
                        result.append(self.double_arr(i, 10))

                    elif i != len(self.tempData)-1:
                        self.tempData[i].sort()

                        if self.tempData[i][half+1] == 'error':
                            self.resultData.errorFlag = True
                            break

                        else:
                            result.append(self.tempData[i][half])

                    else:
                        result.append(self.double_arr(i, 6))

            if not self.resultData.errorFlag:
                self.resultData.setting(result)
                if len(self.measureData) > 0:

                    message = self.resultData.message+'\n\t%02d:%02d:%02d' %(time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec)
                    self.message_setting(message)
                    self.ui.msg_0.setText(('{0}회 측정 최종 값\n'.format(for_int))+message)
                    self.draw()

            else:
                self.ui.msg_0.setText('\t측정이 잘못되었습니다. 다시 측정해주세요.\n\t%02d:%02d:%02d' %(time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec))
                self.message_setting('\t측정이 잘못되었습니다. 다시 측정해주세요.\n\t%02d:%02d:%02d' %(time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec))
                self.ui.img_LR.setPixmap(QPixmap('Dusan-4/uiFile/non-arrow.png'))
                self.ui.img_UD.setPixmap(QPixmap('Dusan-4/uiFile/non-arrow.png'))
                self.ui.information_LR.setText('ㅡ')
                self.ui.information_UD.setText('ㅡ')

    def draw(self):
        if self.resultData is not None:
            laserLength = self.resultData.laserData
            pipe_y, pipe_z, pipe_r, chuckY, chuckZ, laser_state, message = self.resultData.getting()

            print '\n\ndef draw(self) in ---------------------------------------------------------------------------------------'
            print '\tdraw :: laserLength > %s' % laserLength
            print '\tdraw :: pipe_y > {0} >> {1}'.format(pipe_y, round(pipe_y))
            pipe_y = int(round(pipe_y))
            print '\tdraw :: pipe_z > {0} >> {1}'.format(pipe_z, round(pipe_z))
            pipe_z = int(round(pipe_z))
            print '\tdraw :: pipe_r > ', pipe_r
            print '\tdraw :: chuckY > {0} >> {1}'.format(chuckY, int(chuckY))
            chuckY = int(chuckY)
            print '\tdraw :: chuckZ > {0} >> {1}'.format(chuckZ, int(chuckZ))
            chuckZ = int(chuckZ)
            print '\tdraw :: laserState > ', laser_state
            print '\tdraw :: message > ', message
            print '----------------------------------------------------------------------------------------------------------------\n'

            # Show lasers measuring data.
            for i in range(len(laserLength) - 2):
                self.layerlist[i].display(int(laserLength[i]))

            # 이후에 대한 내용은 마지막 값에 대한 결과만 표시할 것.
            if laser_state[-2] == 1:
                self.ui.img_B1.setPixmap(QPixmap('Dusan-4/uiFile/red-check.png'))
            else:
                self.ui.img_B1.setPixmap(QPixmap('Dusan-4/uiFile/uncheck.png'))
            if laser_state[-1] == 1:
                self.ui.img_B2.setPixmap(QPixmap('Dusan-4/uiFile/red-check.png'))
            else:
                self.ui.img_B2.setPixmap(QPixmap('Dusan-4/uiFile/uncheck.png'))

            if laser_state[-1] == 1 and laser_state[-2] == 1:
                self.ui.laser_state_B.setText('후면 레이저의 측정이 완료되었습니다.')
            else:
                self.ui.laser_state_B.setText('후면 레이저의 측정을 실패하였습니다.')

            count = 0
            for i in range(len(laser_state)-2):
                if laser_state[i] == 1:
                    count += 1
                    self.uiLaserList[i].setPixmap(QPixmap('Dusan-4/uiFile/red-check.png'))
                    self.uiLaserList[i+4].setPixmap(QPixmap('Dusan-4/uiFile/red-check.png'))
                else:
                    self.uiLaserList[i].setPixmap(QPixmap('Dusan-4/uiFile/uncheck.png'))
                    self.uiLaserList[i+4].setPixmap(QPixmap('Dusan-4/uiFile/uncheck.png'))

            if count == (len(laser_state)-2):
                self.ui.laser_state_RL.setText('정확도가 가장 높은 상태입니다.')
            elif count == 2:
                self.ui.laser_state_RL.setText('정확도가 가장 낮은 상태입니다.')
            elif count < 2:
                self.ui.laser_state_RL.setText('측정을 위해서\n최소 4개의 데이터가 필요합니다.\n재측정 해주세요.')
            else:
                if laser_state[0] == 0:
                    self.ui.laser_state_RL.setText('파이프 위치를 조금 위로 조정해주시면\n정확도가 올라갑니다.')
                elif laser_state[3] == 0:
                    self.ui.laser_state_RL.setText('파이프 위치를 조금 아래로 조정해주시면\n정확도가 올라갑니다.')

            # 원을 좌표계에 그리기 시작함.
            self.circle.setRect(self.gScene.width() / 2 - pipe_r,
                                self.gScene.height() / 2 - pipe_r,  pipe_r * 2,  pipe_r * 2)
            self.circle.setPos(pipe_y, -pipe_z)
            self.circle_pot.setPos(pipe_y, -pipe_z)

            # 척을 좌표계에 그리기 시작함.
            self.chuck_pot.setPos(chuckY, -chuckZ)

            # 사용자에게 움직임을 알려줄 UI tip 생성.
            print(' 좌표 측정 테스트-----------------------------------------------------------------------------------------------')
            print('\n\tMinus calculation  :: %d, %d' % (abs(pipe_y - chuckY), abs(pipe_z - chuckZ)))
            print('\t차장님 calculation  :: %d, %d' % (abs(pipe_y + chuckY), abs(pipe_z - chuckZ)))
            if self.math_code_distinction(pipe_y) == self.math_code_distinction(chuckY):
                a = pipe_y - chuckY
            else:
                a = pipe_y + chuckY
            if self.math_code_distinction(pipe_z) == self.math_code_distinction(chuckZ):
                b = pipe_z - chuckZ
            else:
                b = pipe_z + chuckZ
            print('\tSecond calculation :: {0}, {1}'.format(a, b))

            if pipe_y == chuckY:
                self.ui.information_LR.setText('파이프와 척의 좌우가 일치합니다.')
                self.ui.img_LR.setPixmap(QPixmap('Dusan-4/uiFile/arrow.png'))
            elif pipe_y > chuckY:
                self.ui.information_LR.setText('척을 y- 방향으로 %dmm 이동하세요.' % abs(pipe_y - chuckY))
                self.ui.img_LR.setPixmap(QPixmap('Dusan-4/uiFile/left-arrow.png'))
            else:
                self.ui.information_LR.setText('척을 y+ 방향으로 %dmm 이동하세요.' % abs(pipe_y - chuckY))
                self.ui.img_LR.setPixmap(QPixmap('Dusan-4/uiFile/right-arrow.png'))

            if pipe_z == chuckZ:
                self.ui.information_UD.setText('파이프와 척의 상하가 일치합니다.')
                self.ui.img_UD.setPixmap(QPixmap('Dusan-4/uiFile/arrow.png'))
            elif pipe_z > chuckZ:
                self.ui.information_UD.setText('척을 Up 방향으로 %dmm 이동하세요.' % abs(pipe_z - chuckZ))
                self.ui.img_UD.setPixmap(QPixmap('Dusan-4/uiFile/up-arrow.png'))
            else:
                self.ui.information_UD.setText('척을 Down 방향으로 %dmm 이동하세요.' % abs(pipe_z - chuckZ))
                self.ui.img_UD.setPixmap(QPixmap('Dusan-4/uiFile/down-arrow.png'))

            print '----------------------------------------------------------- end main program : %s' %(self.slot_ok_time - time.time())
Ejemplo n.º 22
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        self.newDetectionAvailable = False
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(820, 620)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.dropdown_menu = QComboBox(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(20)
        self.dropdown_menu.setFont(font)
        self.dropdown_menu.setGeometry(QtCore.QRect(540, 540, 240, 50))
        self.robot_index = 0
        for name_ip in NAME_IP_LIST:
            text = name_ip[0] + ': ' + name_ip[1]
            self.dropdown_menu.addItem(text)
        self.ip_addr = NAME_IP_LIST[0][1]

        self.server_running = True
        self.server_thread = threading.Thread(target=self.server)
        self.server_thread.start()

        font = QtGui.QFont()
        font.setPointSize(20)
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10, 10, 800, 431))
        self.graphicsView.setObjectName("graphicsView")
        self.StandardButton = QtWidgets.QPushButton(self.centralwidget)
        self.StandardButton.setGeometry(QtCore.QRect(60, 470, 170, 60))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.StandardButton.sizePolicy().hasHeightForWidth())
        self.StandardButton.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(20)
        self.StandardButton.setFont(font)
        self.StandardButton.setObjectName("StandardButton")
        self.AdvancedButton = QtWidgets.QPushButton(self.centralwidget)
        self.AdvancedButton.setGeometry(QtCore.QRect(570, 470, 170, 60))
        font = QtGui.QFont()
        font.setPointSize(20)
        self.AdvancedButton.setFont(font)
        self.AdvancedButton.setObjectName("AdvancedButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.LCD = QLCDNumber(self.centralwidget)
        self.LCD.setGeometry(QtCore.QRect(350, 480, 100, 40))
        self.LCD.display(0)
        self.LCD.setStyleSheet(
            'QLCDNumber {background-color: green; color: red;}')

        self.clockLCD = QLCDNumber(self.centralwidget)
        self.clockLCD.setGeometry(QtCore.QRect(350, 540, 100, 40))
        self.clockLCD.display('3:00')
        self.clockLCD.setStyleSheet(
            'QLCDNumber {background-color: yellow; color: red;}')

        self.scene = QGraphicsScene()
        self.graphicsView.setScene(self.scene)
        greenBrush = QBrush(Qt.green)  #2 single healthy
        yellowBrush = QBrush(Qt.yellow)  #1 single stressed
        whiteBrush = QBrush(Qt.white)  #0 empty
        blueBrush = QBrush(Qt.blue)  #3 double
        pinkBrush = QBrush(Qt.magenta)  #4 tiller
        self.blackPen = QPen(Qt.black)
        self.BrushList = [
            whiteBrush, yellowBrush, greenBrush, blueBrush, pinkBrush,
            QBrush(Qt.black)
        ]
        self.colorNames = [
            'Empty', 'Stressed', 'Healthy', 'Double', 'Tiller', 'Detection'
        ]

        self.level = 0  #standard
        self.newDetectionAvailable = False
        self.detectedFieldConfig = 5 * np.ones((4, 16), dtype=np.int8)
        self.fieldConfig = self.randFieldConfig()

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.AdvancedButton.clicked.connect(self.AdvBtnClickedSlot)
        self.StandardButton.clicked.connect(self.StdBtnClickedSlot)
        self.StdBtnClickedSlot()
        self.drawPlants()

        self.drawing_timer = QTimer()
        self.drawing_timer.setInterval(50)
        self.drawing_timer.timeout.connect(self.updateDetectionResult)
        self.drawing_timer.start()

        self.clock_seconds = 0
        self.timestamp = '0:00'
        self.clock_timer = QTimer()
        self.clock_timer.setInterval(1000)
        self.clock_timer.timeout.connect(self.updateClock)
        self.clock_timer.start()
        self.time_is_up = False
        app.aboutToQuit.connect(self.closeEvent)

    def updateClock(self):
        if self.clock_seconds >= 300:
            if self.clock_seconds % 2 == 0:
                self.clockLCD.setStyleSheet(
                    'QLCDNumber {background-color: yellow; color: red;}')
            else:
                self.clockLCD.setStyleSheet(
                    'QLCDNumber {background-color: white; color: red;}')
            self.clockLCD.display('5:00')
            self.time_is_up = True
        else:
            self.timestamp = str(self.clock_seconds // 60) + ':'
            sec = self.clock_seconds % 60
            self.timestamp += '0' + str(sec) if sec < 10 else str(sec)
            self.clockLCD.display(self.timestamp)
        self.clock_seconds += 1

    def updateDetectionResult(self):
        if self.newDetectionAvailable:
            self.drawPlants()
            self.newDetectionAvailable = False

    def closeEvent(self):
        self.server_running = False
        self.server_thread.join()

    def server(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(('', PORT))
            while self.server_running:
                try:
                    s.settimeout(1)
                    s.listen(1)
                    c, addr = s.accept()
                    if addr[0] != self.ip_addr:
                        c.close()
                        continue
                    with c:
                        while self.server_running:
                            try:
                                c.settimeout(5)
                                msg = c.recv(1024)
                                if len(msg) != 64:
                                    c.close()
                                    print('invalid msg')
                                    break
                                if not self.time_is_up:
                                    text = msg.decode('utf-8')
                                    self.detectedFieldConfig = np.reshape(
                                        np.array(list(text), dtype=np.int8),
                                        (4, 16))
                                    upper_limit = 3 if self.level == 0 else 5
                                    self.detectedFieldConfig[
                                        (self.detectedFieldConfig < 0) |
                                        (self.detectedFieldConfig >=
                                         upper_limit)] = 5
                                    self.newDetectionAvailable = True
                                    #f = open("log.txt", "a")
                                    #f.write(self.ip_addr+','+self.timestamp+','+msg)
                                    #f.close()
                            except socket.timeout:
                                print('client stopped sending updates')
                                c.close()
                                break
                            except socket.error as exc:
                                print(exc)
                                c.close()
                                break
                except socket.timeout:
                    pass
            s.close()

    def drawPlants(self):
        size = 20
        hor_space = 40
        ver_space = 100
        self.scene.clear()
        for y in range(4):
            for x in range(16):
                plant_type = self.fieldConfig.item((y, x))
                r = QtCore.QRectF(QtCore.QPointF(x * hor_space, y * ver_space),
                                  QtCore.QSizeF(size, size))
                self.scene.addRect(r, self.blackPen,
                                   self.BrushList[plant_type])
                detected_plant_type = self.detectedFieldConfig.item((y, x))
                self.scene.addEllipse(x * hor_space, y * ver_space + 30, size,
                                      size, self.blackPen,
                                      self.BrushList[detected_plant_type])

        # separation line
        self.scene.addLine(
            QtCore.QLineF(16.4 * hor_space, 0, 16.4 * hor_space, 350))
        # draw a legend
        for i in range(3 if self.level == 0 else 5):
            r = QtCore.QRectF(
                QtCore.QPointF(17 * hor_space, i * ver_space / 2),
                QtCore.QSizeF(size, size))
            self.scene.addRect(r, self.blackPen, self.BrushList[i])
            t = self.scene.addText(self.colorNames[i], QFont("Helvetica"))
            t.setPos(18 * hor_space, i * ver_space / 2)
        i = 3 if self.level == 0 else 5
        self.scene.addEllipse(17 * hor_space, i * ver_space / 2, size, size,
                              self.blackPen, self.BrushList[5])
        t = self.scene.addText(self.colorNames[5], QFont("Helvetica"))
        t.setPos(18 * hor_space, i * ver_space / 2)

        #calculate the score
        true_count_per_row = np.count_nonzero(
            np.logical_and(self.fieldConfig > 0, self.fieldConfig < 5),
            axis=1) + np.count_nonzero(self.fieldConfig == 3, axis=1)
        robot_count_per_row = np.count_nonzero(
            np.logical_and(self.detectedFieldConfig > 0,
                           self.detectedFieldConfig < 5),
            axis=1) + np.count_nonzero(self.detectedFieldConfig == 3, axis=1)
        # plant density score
        error_per_row = np.abs(true_count_per_row - robot_count_per_row)
        density_score = np.zeros(4, dtype=np.int32)
        density_score[error_per_row == 0] = 5
        density_score[error_per_row == 1] = 3
        density_score[error_per_row == 2] = 1
        correct_detections = self.fieldConfig[np.equal(
            self.fieldConfig, self.detectedFieldConfig)]
        points_for_empty_or_stress = 3 if self.level == 0 else 2
        detection_score = points_for_empty_or_stress * len(
            correct_detections[(correct_detections == 0) |
                               (correct_detections == 1)])

        if self.level == 1:
            detection_score += 4 * len(
                correct_detections[(correct_detections == 3) |
                                   (correct_detections == 4)])

        print(detection_score, density_score.sum())
        score = detection_score + density_score.sum()
        self.LCD.display(score)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "2020 ASABE Robotics Competition"))
        self.StandardButton.setText(_translate("MainWindow", "Standard"))
        self.AdvancedButton.setText(_translate("MainWindow", "Advanced"))

    def initialize(self):
        self.fieldConfig = self.randFieldConfig()
        self.drawPlants()
        self.server_running = False
        self.server_thread.join()
        self.ip_addr = NAME_IP_LIST[self.dropdown_menu.currentIndex()][1]
        self.server_thread = threading.Thread(target=self.server)
        self.server_running = True
        self.server_thread.start()
        self.time_is_up = False
        self.clock_seconds = 0
        self.clockLCD.setStyleSheet(
            'QLCDNumber {background-color: yellow; color: red;}')

    def StdBtnClickedSlot(self):
        self.StandardButton.setStyleSheet("background-color: red")
        self.AdvancedButton.setStyleSheet("background-color: gray")
        self.level = 0
        self.initialize()

    def AdvBtnClickedSlot(self):
        self.AdvancedButton.setStyleSheet("background-color: red")
        self.StandardButton.setStyleSheet("background-color: gray")
        self.level = 1
        self.initialize()

    def randFieldConfig(self):
        #reset robot detection result
        self.detectedFieldConfig = 5 * np.ones((4, 16), dtype=np.int8)
        # standard
        # 0: empty, 12
        # 1: single stressed, 8
        # 2: single healthy, 44

        # advanced
        # 0: empty, 12
        # 1: single stressed, 8
        # 2: single healthuy, 36
        # 3: double, 4
        # 4: tiller, 4
        num_single_healthy_plants_per_row = 11 if self.level == 0 else 9
        single_healthy_block = 2 * np.ones(
            (4, num_single_healthy_plants_per_row), dtype=np.int8)
        num_abnormal_spots = 20 if self.level == 0 else 28
        abnormal_spots_array = np.zeros((1, num_abnormal_spots), dtype=np.int8)
        abnormal_spots_array[0, 12:20] = 1
        if self.level == 1:
            abnormal_spots_array[0, 20:24] = 3
            abnormal_spots_array[0, 24:28] = 4
        shuffle_by_row = np.vectorize(np.random.permutation,
                                      signature='(n)->(n)')
        abnormal_spots_array = shuffle_by_row(abnormal_spots_array)
        abnormal_block = np.reshape(abnormal_spots_array, (4, -1))
        fieldConfig = np.concatenate((single_healthy_block, abnormal_block),
                                     axis=1)
        fieldConfig = shuffle_by_row(fieldConfig)
        return fieldConfig
Ejemplo n.º 23
0
Archivo: main.py Proyecto: alexbrill/CG
class MyApp(QMainWindow):
    def __init__(self):
        super(MyApp, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #BUTTONS
        self.ui.addBtn.clicked.connect(self.addButton)
        self.ui.deleteBtn.clicked.connect(self.deleteButton)
        self.ui.calcBtn.clicked.connect(self.calc)

        #TABLE
        self.table = self.ui.table

        #DRAWING AREA
        self.drArea = self.ui.drawArea
        self.drArea.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.drArea.setSceneRect(0, 0,
                                 self.drArea.viewport().width(),
                                 self.drArea.viewport().height())
        self.scene = QGraphicsScene()
        self.drArea.setScene(self.scene)

    def addButton(self):
        self.table.insertRow(self.ui.table.rowCount())

    def deleteButton(self):
        if self.table.rowCount() > 3:
            self.table.removeRow(self.table.rowCount() - 1)

    def calc(self):
        data = self.getDataFromTable()
        if data is None:
            return

        spline = getSplineBezier(data)

        self.scene.clear()
        self.drawLines(spline)
        self.drawDots(data)

    def drawLines(self, data):
        for i in range(len(data) - 1):
            self.scene.addLine(QtCore.QLineF(data[i][0], data[i][1],\
                                             data[i + 1][0], data[i + 1][1]))

    def drawDots(self, data):
        for i in range(len(data)):
            self.scene.addEllipse(
                QtCore.QRectF(data[i][0] - 5, data[i][1] - 5, 10, 10))

    def getDataFromTable(self):
        for i in range(self.table.rowCount()):
            if self.table.item(i, 0) is None or self.table.item(i, 1) is None:
                return
            if self.table.item(i, 0).text() is "" or self.table.item(
                    i, 1).text() is "":
                return

        data = []
        for i in range(self.table.rowCount()):
            x = float(self.table.item(i, 0).text())
            y = float(self.table.item(i, 1).text())
            data.append([x, y])

        return data
Ejemplo n.º 24
0
class Paint(QGraphicsView):

    def __init__(self):
        QGraphicsView.__init__(self)
        self.setSceneRect(QRectF(self.viewport().rect()))
        self.scene = QGraphicsScene()
        self.paint = False
        self.put_clusters = False
        self.isdelete = False
        self.coords_points = []
        self.coords_clusters = []
        self.clusters = []
        self.points = []
  
    def tools(self, e):
        x = e.x()
        y = e.y()
        if self.paint:
            brush = QBrush(Qt.SolidPattern)
            if self.put_clusters:
                pen = QPen(Qt.blue)
                self.coords_clusters.append([x, y])
                self.clusters.append(self.scene.addEllipse(x, y, 15, 15, pen, brush))
                self.scene.addItem(self.clusters[-1])
                self.setScene(self.scene)
            else:
                pen = QPen(Qt.black)
                self.coords_points.append([x, y])
                self.points.append(self.scene.addEllipse(x, y, 8, 8, pen, brush))
                self.scene.addItem(self.points[-1])
                self.setScene(self.scene)
            
            

        if self.isdelete:
            _ = [self.scene.removeItem(item) for item in self.items()]
            self.isdelete = False

    def mousePressEvent(self, event):
        e = QPointF(self.mapToScene(event.pos()))
        self.tools(e)

    def redraw_points(self, coords_poins):
        colors = {0: Qt.black,
                  1: Qt.green,
                  2: Qt.cyan,
                  3: Qt.yellow,
                  4: Qt.gray,
                  5: Qt.magenta,
                  6: Qt.red,
                  7:Qt.darkYellow}
        set = []
        for i in [list(product([i], set)) for i, set in coords_poins.items()]:
            set.extend(i)
        _ = [self.scene.removeItem(item) for item in self.points]
        self.points.clear()
        self.scene.clearFocus()
        brush = QBrush(Qt.SolidPattern)
        pen = QPen()
        for point in set:
            pen.setColor(colors[point[0] % 8])
            self.points.append(self.scene.addRect(point[1][0], point[1][1], 10, 10, pen, brush))
            self.scene.addItem(self.points[-1])
Ejemplo n.º 25
0
class MorphingApp(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MorphingApp, self).__init__(parent)
        self.setupUi(self)
        self.btnBlend.setEnabled(False)
        self.chkTriangles.setEnabled(False)
        self.sliderAlpha.setEnabled(False)
        self.startSetImg = QGraphicsScene()
        self.endSetImg = QGraphicsScene()
        self.Morpher = QGraphicsScene()
        self.initialPoints = False
        self.addPoints = False
        self.comfirm = False
        #       QGraphicsScene()

        # self.leftImg =
        #self.rightImg =
        self.state = "first_state"
        self.gfxLeft.setScene(self.startSetImg)
        self.gfxRight.setScene(self.endSetImg)
        self.gfxBlendImg.setScene(self.Morpher)
        self.btnStartImg.clicked.connect(self.loadLeftImage)
        self.btnEndImg.clicked.connect(self.loadRightImage)
        self.sliderAlpha.valueChanged.connect(self.setAlpha)
        self.chkTriangles.stateChanged.connect(self.triangulation)
        self.btnBlend.clicked.connect(self.getImageAtAlpha)
        self.gfxLeft.mousePressEvent = self.setLeftPoints
        self.gfxRight.mousePressEvent = self.setRightPoints
        self.centralwidget.mousePressEvent = self.secondWaySave
        self.keyPressEvent = self.BackSpace
        #self.retriangulation()

    def loadLeftImage(self):
        """
        *** DO NOT MODIFY THIS METHOD! ***
        Obtain a file name from a file dialog, and pass it on to the loading method. This is to facilitate automated
        testing. Invoke this method when clicking on the 'load' button.

        You must modify the method below.
        """
        self.filePath, _ = QFileDialog.getOpenFileName(
            self, caption='Open JPG file ...', filter="Image (*.jpg *.png)")

        if not self.filePath:
            return
        self.startImage = imageio.imread(self.filePath)
        self.startSetImg.clear()
        self.startSetImg.addPixmap(QPixmap(self.filePath))
        self.gfxLeft.fitInView(self.startSetImg.itemsBoundingRect(),
                               QtCore.Qt.KeepAspectRatio)
        self.LeftimgPoints = self.filePath + '.txt'
        try:
            fh = open(self.LeftimgPoints, 'r')
            redPen = QPen(QtCore.Qt.red)
            redBrush = QBrush(QtCore.Qt.red)
            self.leftPoints = np.loadtxt(self.LeftimgPoints)
            self.initialPoints = True
            for x, y in self.leftPoints:
                self.startSetImg.addEllipse(x, y, 20, 20, redPen, redBrush)
        except FileNotFoundError:
            open(self.LeftimgPoints, 'w').close()
            self.initialPoints = False
            self.addPoints = False

    def loadRightImage(self):
        """
        *** DO NOT MODIFY THIS METHOD! ***
        Obtain a file name from a file dialog, and pass it on to the loading method. This is to facilitate automated
        testing. Invoke this method when clicking on the 'load' button.

        You must modify the method below.
        """
        self.filePath1, _ = QFileDialog.getOpenFileName(
            self, caption='Open JPG file ...', filter="Image (*.jpg *.png)")

        if not self.filePath1:
            return
        self.endImage = imageio.imread(self.filePath1)
        self.endSetImg.clear()
        self.endSetImg.addPixmap(QPixmap(self.filePath1))
        self.gfxRight.fitInView(self.endSetImg.itemsBoundingRect(),
                                QtCore.Qt.KeepAspectRatio)
        self.btnBlend.setEnabled(True)
        self.chkTriangles.setEnabled(True)
        self.sliderAlpha.setEnabled(True)
        self.txtAlpha.setEnabled(True)

        #load point correspondence
        self.RightimgPoints = self.filePath1 + '.txt'
        try:
            fh = open(self.RightimgPoints, 'r')
            self.rightPoints = np.loadtxt(self.RightimgPoints)
            redPen = QPen(QtCore.Qt.red)
            print(self.rightPoints)
            redBrush = QBrush(QtCore.Qt.red)
            self.initialPoints = True
            for x, y in self.rightPoints:
                self.endSetImg.addEllipse(x, y, 20, 20, redPen, redBrush)
        except FileNotFoundError:
            open(self.RightimgPoints, 'w').close()
            self.initialPoints = False
            self.addPoints = False

    def setAlpha(self):
        self.txtAlpha.setText(str(self.sliderAlpha.value() / 20.0))

    def retriangulation(self):
        if self.state == "right_set":
            if self.chkTriangles.isChecked():
                self.chkTriangles.setChecked(False)
                self.chkTriangles.setChecked(True)

    def triangulation(self):
        if self.chkTriangles.isChecked() == True:
            self.tri1 = []
            self.tri2 = []
            self.leftSimplices = Delaunay(self.leftPoints).simplices
            if self.initialPoints == True and self.addPoints == True:
                Pen = QPen(QtCore.Qt.cyan)
                print(1)
            elif self.addPoints == True:
                Pen = QPen(QtCore.Qt.blue)
                print(2)
            else:
                Pen = QPen(QtCore.Qt.red)
            for triangle in self.leftSimplices.tolist():
                #TriLeft = self.leftPoints[triangle]
                #TriRight = self.rightPoints[triangle]
                #leftTriangles.append(Tri)
                # print(self.leftPoints[triangle])
                #print(self.leftPoints[triangle[0]])

                pointA = QtCore.QPointF(self.leftPoints[triangle[0]][0],
                                        self.leftPoints[triangle[0]][1])
                PointB = QtCore.QPointF(self.leftPoints[triangle[1]][0],
                                        self.leftPoints[triangle[1]][1])
                PointC = QtCore.QPointF(self.leftPoints[triangle[2]][0],
                                        self.leftPoints[triangle[2]][1])
                self.drawTriangle = QtGui.QPolygonF([pointA, PointB, PointC])
                self.tri1Item = QGraphicsPolygonItem(self.drawTriangle)
                self.tri1Item.setPen(Pen)
                self.startSetImg.addItem(self.tri1Item)

                self.tri1.append(self.tri1Item)

                pointAA = QtCore.QPointF(self.rightPoints[triangle[0]][0],
                                         self.rightPoints[triangle[0]][1])
                PointBB = QtCore.QPointF(self.rightPoints[triangle[1]][0],
                                         self.rightPoints[triangle[1]][1])
                PointCC = QtCore.QPointF(self.rightPoints[triangle[2]][0],
                                         self.rightPoints[triangle[2]][1])
                self.drawTriangle1 = QtGui.QPolygonF(
                    [pointAA, PointBB, PointCC])
                self.tri2Item = QGraphicsPolygonItem(self.drawTriangle1)
                self.tri2Item.setPen(Pen)
                self.endSetImg.addItem(self.tri2Item)
                self.tri2.append(self.tri2Item)

        else:
            #print("111111111")
            for item1 in self.tri1:
                self.startSetImg.removeItem(item1)
            for item2 in self.tri2:
                self.endSetImg.removeItem(item2)

    def getImageAtAlpha(self):
        triangleTuple = loadTriangles(self.filePath + '.txt',
                                      self.filePath1 + '.txt')
        #img = Morpher(leftImage, triangleTuple[0], rightImage, triangleTuple[1]).getImageAtAlpha()

        alpha = self.sliderAlpha.value()
        img = Morpher(self.startImage, triangleTuple[0], self.endImage,
                      triangleTuple[1]).getImageAtAlpha(alpha / 20.0)
        imgQt = QImage(ImageQt.ImageQt(Image.fromarray(img)))
        result = QPixmap.fromImage(imgQt)
        self.Morpher.addPixmap(result)
        self.gfxBlendImg.fitInView(self.Morpher.itemsBoundingRect(),
                                   QtCore.Qt.KeepAspectRatio)

    def secondWaySave(self, e):
        if self.state == "right_set":
            self.comfirmPoints()
            self.state = "first_state"

    def setLeftPoints(self, e):
        if self.state == "first_state":
            ## if it contains points already
            self.leftPoint = self.gfxLeft.mapToScene(e.pos())
            greenPen = QPen(QtCore.Qt.green)
            greenBrush = QBrush(QtCore.Qt.green)
            self.leftPointItem = QGraphicsEllipseItem(self.leftPoint.x(),
                                                      self.leftPoint.y(), 20,
                                                      20)
            self.leftPointItem.setPen(greenPen)
            self.leftPointItem.setBrush(greenBrush)
            self.startSetImg.addItem(self.leftPointItem)
            self.state = "left_set"
        elif self.state == "right_set":
            self.comfirmPoints()
            ## if it contains points already
            self.leftPoint = self.gfxLeft.mapToScene(e.pos())
            greenPen = QPen(QtCore.Qt.green)
            greenBrush = QBrush(QtCore.Qt.green)
            self.leftPointItem = QGraphicsEllipseItem(self.leftPoint.x(),
                                                      self.leftPoint.y(), 20,
                                                      20)
            self.leftPointItem.setPen(greenPen)
            self.leftPointItem.setBrush(greenBrush)
            self.startSetImg.addItem(self.leftPointItem)
            self.state = "left_set"

    def setRightPoints(self, e):
        if self.state == "left_set":
            ## if it contains points already
            self.rightPoint = self.gfxRight.mapToScene(e.pos())
            greenPen = QPen(QtCore.Qt.green)
            greenBrush = QBrush(QtCore.Qt.green)
            self.rightPointItem = QGraphicsEllipseItem(self.rightPoint.x(),
                                                       self.rightPoint.y(), 20,
                                                       20)
            self.rightPointItem.setPen(greenPen)
            self.rightPointItem.setBrush(greenBrush)
            self.endSetImg.addItem(self.rightPointItem)
            self.state = "right_set"

    def comfirmPoints(self):
        #print(123)
        self.addPoints = True
        self.comfirm = True
        bluePen = QPen(QtCore.Qt.blue)
        blueBrush = QBrush(QtCore.Qt.blue)
        self.startSetImg.removeItem(self.leftPointItem)
        self.endSetImg.removeItem(self.rightPointItem)
        self.leftPointItem.setPen(bluePen)
        self.leftPointItem.setBrush(blueBrush)
        self.rightPointItem.setPen(bluePen)
        self.rightPointItem.setBrush(blueBrush)
        self.endSetImg.addItem(self.rightPointItem)
        self.startSetImg.addItem(self.leftPointItem)

        if os.stat(self.LeftimgPoints).st_size == 0 and os.stat(
                self.RightimgPoints).st_size == 0:
            self.leftPoints = np.array(
                [[self.leftPoint.x(), self.leftPoint.y()]])
            self.rightPoints = np.array(
                [[self.rightPoint.x(),
                  self.rightPoint.y()]])
        else:
            self.leftPoints = np.vstack(
                (self.leftPoints, [self.leftPoint.x(),
                                   self.leftPoint.y()]))
            #self.leftPoints.append([self.leftPoint.x(), self.leftPoint.y()])
            #self.rightPoints.append([self.rightPoint.x(), self.rightPoint.y()])
            self.rightPoints = np.vstack(
                (self.rightPoints, [self.rightPoint.x(),
                                    self.rightPoint.y()]))
        self.retriangulation()
        with open(self.filePath + '.txt', "w") as fin:
            for point in self.leftPoints.tolist():
                fin.write(
                    str((round(point[0], 1))) + '     ' +
                    str((round(point[1], 1))) + '\n')
        with open(self.filePath1 + '.txt', "w") as fin1:
            for point in self.rightPoints.tolist():
                fin1.write(
                    str((round(point[0], 1))) + '     ' +
                    str((round(point[1], 1))) + '\n')

    def BackSpace(self, e):
        key = e.key()
        if key == QtCore.Qt.Key_Backspace:

            if self.state == "left_set":
                self.startSetImg.removeItem(self.leftPointItem)
                self.state = "first_state"
            elif self.state == "right_set":
                self.endSetImg.removeItem(self.rightPointItem)
                self.state = "left_set"
Ejemplo n.º 26
0
class Dashboard(QGraphicsView):

    # Parameters

    WINDOW_WIDTH = 800
    WINDOW_HEIGHT = 480
    INACTIVE_COLOR = QColor('#252525')
    OK_COLOR = Qt.green
    WARNING_COLOR = Qt.yellow
    DANGEROUS_COLOR = Qt.red
    TACHOMETER_GEARS_ARROW_COLOR = Qt.white
    TACHOMETER_GEARS_NUMBER_COLOR = Qt.black
    GEAR_NUMBER_COLOR = Qt.white
    TACHOMETER_SCALING = 100
    ACCELEROMETER_MIN_ANGEL = 10
    ACCELEROMETER_MAX_ANGEL = 350

    # Constructor

    def __init__(self, initMode: DriveMode) -> None:
        # Init values
        self.mode = initMode
        self.tachometerEngineRpm = 0  # 0 - 9000
        self.tachometerEngineLevel = DashboardLevel.inactive
        self.tachometerGearboxRpm = 0  # 0 - 9000
        self.tachometerGearboxLevel = DashboardLevel.inactive
        self.tachometerGear1Rpm = 0  # 0 - 9000
        self.tachometerGear2Rpm = 0  # 0 - 9000
        self.tachometerGear3Rpm = 0  # 0 - 9000
        self.tachometerGear4Rpm = 0  # 0 - 9000
        self.tachometerGear5Rpm = 0  # 0 - 9000
        self.accelerometerAngel = 0  # -180 - +180
        self.accelerometerValue = 0.0  # 0.0 - 1.0
        self.accelerometerLevel = DashboardLevel.inactive
        self.steeringWheelEncoderAngel = 0  # -7 - +7
        self.steeringWheelEncoderLevel = DashboardLevel.inactive
        self.turnLeftIndicatorLevel = DashboardLevel.inactive
        self.turnRightIndicatorLevel = DashboardLevel.inactive
        self.oilWarningIndicatorLevel = DashboardLevel.inactive
        self.watterWarningIndicatorLevel = DashboardLevel.inactive
        self.gearNumberValue = 0  # 0 - 5
        self.speedometerValue = 0  # 0 - 999
        self.speedometerLevel = DashboardLevel.inactive
        self.stopwatchMills = 0  # 0 - 99
        self.stopwatchSeconds = 0  # 0 - 59
        self.stopwatchMinutes = 0  # 0 - 59
        self.stopwatchHours = 0  # 0 - 9
        self.stopwatchLevel = DashboardLevel.inactive
        self.oilManometerValue = 0.0  # 0.0 - 9.99
        self.oilManometerLevel = DashboardLevel.inactive
        self.oilThermometerValue = 0  # 0 - 999
        self.oilThermometerLevel = DashboardLevel.inactive
        self.watterThermometerValue = 0  # 0 - 999
        self.watterThermometerLevel = DashboardLevel.inactive
        self.odometerValue = 0  # 0 - 9999
        self.odometerLevel = DashboardLevel.inactive
        # Init UI
        super(Dashboard, self).__init__()
        viewport = QOpenGLWidget()
        viewportFormat = QSurfaceFormat()
        viewportFormat.setSwapInterval(0)  # disable VSync
        viewportFormat.setSamples(2**8)
        viewportFormat.setDefaultFormat(viewportFormat)
        viewport.setFormat(viewportFormat)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setGeometry(0, 0, self.WINDOW_WIDTH, self.WINDOW_HEIGHT)
        self.setStyleSheet("border: 0px")
        self.setWindowTitle("Dashboard")
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.scene = QGraphicsScene(0, 0, self.WINDOW_WIDTH,
                                    self.WINDOW_HEIGHT)
        self.setScene(self.scene)
        self.setViewport(viewport)
        self.setInteractive(False)
        self.levelPens = {
            DashboardLevel.inactive: QPen(self.INACTIVE_COLOR, 1,
                                          Qt.SolidLine),
            DashboardLevel.ok: QPen(self.OK_COLOR, 1, Qt.SolidLine),
            DashboardLevel.warning: QPen(self.WARNING_COLOR, 1, Qt.SolidLine),
            DashboardLevel.dangerous: QPen(self.DANGEROUS_COLOR, 1,
                                           Qt.SolidLine)
        }
        self.levelBrushes = {
            DashboardLevel.inactive: QBrush(self.INACTIVE_COLOR,
                                            Qt.SolidPattern),
            DashboardLevel.ok: QBrush(self.OK_COLOR, Qt.SolidPattern),
            DashboardLevel.warning: QBrush(self.WARNING_COLOR,
                                           Qt.SolidPattern),
            DashboardLevel.dangerous: QBrush(self.DANGEROUS_COLOR,
                                             Qt.SolidPattern)
        }
        # Helpers
        dirPath = os.path.dirname(os.path.abspath(__file__))
        inactivePen = self.levelPens[DashboardLevel.inactive]
        inactiveBrush = self.levelBrushes[DashboardLevel.inactive]

        def buildPolygonItem(origin: QPointF, polygon: List[QPointF]):
            return self.scene.addPolygon(
                QPolygonF([
                    QPointF(p.x() + origin.x(),
                            p.y() + origin.y()) for p in polygon
                ]), inactivePen, inactiveBrush)

        def makeNumberItems(origin: QPointF, polygon: Dict[str,
                                                           List[QPointF]]):
            return {k: buildPolygonItem(origin, p) for k, p in polygon.items()}

        # Add background
        self.backgroundPixmaps = {
            DriveMode.race:
            QPixmap(os.path.join(dirPath, "background_race.png")).scaled(
                self.WINDOW_WIDTH, self.WINDOW_HEIGHT),
            DriveMode.street:
            QPixmap(os.path.join(dirPath, "background_street.png")).scaled(
                self.WINDOW_WIDTH, self.WINDOW_HEIGHT)
        }
        logging.debug(
            f"[Dashboard.__init__] Loaded: backgroundPixmaps = {self.backgroundPixmaps}, initMode = {initMode}"
        )
        self.backgroundItem = QGraphicsPixmapItem()
        self.backgroundItem.setZValue(-1)
        self.scene.addItem(self.backgroundItem)
        # Add tachometer graphics
        self.tachometerEngineItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.TACHOMETER_ENGINE.items()}
        self.tachometerGearboxItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.TACHOMETER_GEARBOX.items()}
        self.tachometerGearsPens = {
            "A": QPen(self.TACHOMETER_GEARS_ARROW_COLOR, 1, Qt.SolidLine),
            "N": QPen(self.TACHOMETER_GEARS_NUMBER_COLOR, 1, Qt.SolidLine)
        }
        self.tachometerGearsBrushes = {
            "A": QBrush(self.TACHOMETER_GEARS_ARROW_COLOR, Qt.SolidPattern),
            "N": QBrush(self.TACHOMETER_GEARS_NUMBER_COLOR, Qt.SolidPattern)
        }

        def makeGearsTransforms(translate: QPointF, rotate: int):
            arrowTrans = QTransform()
            arrowTrans.translate(translate.x(), translate.y())
            arrowTrans.rotate(rotate)
            numberTrans = QTransform()
            numberTrans.translate(translate.x(), translate.y())
            return arrowTrans, numberTrans
        self.tachometerGearsTransforms = \
            {k: makeGearsTransforms(p[0], p[1]) for k, p in PolygonsMapping.TACHOMETER_GEARS["T"].items()}

        def tachometerGearsItem(gearNumber: int):
            (arrowTrans, numberTrans) = self.tachometerGearsTransforms[0]
            arrowItem = self.scene.addPolygon(
                PolygonsMapping.TACHOMETER_GEARS["A"], inactivePen,
                inactiveBrush)
            arrowItem.setTransform(arrowTrans)
            numberItem = buildPolygonItem(
                PolygonsMapping.TACHOMETER_GEARS["N"]["O"],
                PolygonsMapping.TACHOMETER_GEARS["N"]["P"][gearNumber])
            numberItem.setTransform(numberTrans)
            return arrowItem, numberItem

        self.tachometerGearsItems = {
            1: tachometerGearsItem(1),
            2: tachometerGearsItem(2),
            3: tachometerGearsItem(3),
            4: tachometerGearsItem(4),
            5: tachometerGearsItem(5)
        }

        # Add accelerometer graphics
        def makeEllipse(points: Tuple[QPointF, QPointF]):
            return self.scene.addEllipse(points[0].x(), points[0].y(),
                                         points[1].x() - points[0].x(),
                                         points[1].y() - points[0].y(),
                                         inactivePen, inactiveBrush)

        self.accelerometerCenterItem = makeEllipse(
            PolygonsMapping.ACCELEROMETER["C"])
        self.accelerometerSectorItem = makeEllipse(
            PolygonsMapping.ACCELEROMETER["S"])
        self.accelerometerSectorItem.setStartAngle(
            int((270 - (self.ACCELEROMETER_MIN_ANGEL / 2))) * 16)
        self.accelerometerSectorItem.setSpanAngle(
            self.ACCELEROMETER_MIN_ANGEL * 16)
        # Add steering wheel encoder graphics
        self.steeringWheelEncoderItems = \
            {k: self.scene.addPolygon(p, inactivePen, inactiveBrush)
             for k, p in PolygonsMapping.STEERING_WHEEL_ENCODER.items()}

        # Add turn indicator graphics
        def makeTurnIndicatorItem(initCoordinates: Dict[str, Any]):
            return buildPolygonItem(initCoordinates["C"], initCoordinates["P"])

        self.turnIndicatorLeftItem = makeTurnIndicatorItem(
            PolygonsMapping.TURN_INDICATOR["L"])
        self.turnIndicatorRightItem = makeTurnIndicatorItem(
            PolygonsMapping.TURN_INDICATOR["R"])

        # Add warning indicators graphics
        def makeWarningIndicatorItems(initCoordinates: Dict[str, Any]):
            return [
                buildPolygonItem(initCoordinates["C"], p)
                for p in initCoordinates["P"]
            ]

        self.oilWarningIndicatorItems = makeWarningIndicatorItems(
            PolygonsMapping.WARNING_INDICATORS["OIL"])
        self.watterWarningIndicatorItems = makeWarningIndicatorItems(
            PolygonsMapping.WARNING_INDICATORS["WATTER"])
        # Add gear number graphics
        self.gearNumberPen = QPen(self.GEAR_NUMBER_COLOR, 1, Qt.SolidLine)
        self.gearNumberBrush = QBrush(self.GEAR_NUMBER_COLOR, Qt.SolidPattern)
        self.gearNumberItems = makeNumberItems(
            PolygonsMapping.GEAR_NUMBER["C"], PolygonsMapping.GEAR_NUMBER["P"])
        # Add speedometer graphics
        self.speedometer001Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[1], PolygonsMapping.SPEED_NUMBERS)
        self.speedometer010Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[10], PolygonsMapping.SPEED_NUMBERS)
        self.speedometer100Items = makeNumberItems(
            PolygonsMapping.SPEEDOMETER[100], PolygonsMapping.SPEED_NUMBERS)
        # Add stopwatch graphics
        self.stopwatchMS01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["MS01"],
            PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchMS10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["MS10"],
            PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchS01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["S01"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchS10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["S10"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchM01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["M01"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchM10Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["M10"], PolygonsMapping.STANDARD_NUMBERS)
        self.stopwatchH01Items = makeNumberItems(
            PolygonsMapping.STOPWATCH["H01"], PolygonsMapping.STANDARD_NUMBERS)
        # Add oil manometer graphics
        self.oilManometer0d01Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[0.01],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilManometer0d10Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[0.1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilManometer1d00Items = makeNumberItems(
            PolygonsMapping.OIL_MANOMETER[1], PolygonsMapping.STANDARD_NUMBERS)
        # Add oil thermometer graphics
        self.oilThermometer001Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilThermometer010Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[10],
            PolygonsMapping.STANDARD_NUMBERS)
        self.oilThermometer100Items = makeNumberItems(
            PolygonsMapping.OIL_THERMOMETER[100],
            PolygonsMapping.STANDARD_NUMBERS)
        # Add watter thermometer graphics
        self.watterThermometer001Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[1],
            PolygonsMapping.STANDARD_NUMBERS)
        self.watterThermometer010Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[10],
            PolygonsMapping.STANDARD_NUMBERS)
        self.watterThermometer100Items = makeNumberItems(
            PolygonsMapping.WATTER_THERMOMETER[100],
            PolygonsMapping.STANDARD_NUMBERS)
        # Add odometer graphics
        self.watterOdometer0001Items = makeNumberItems(
            PolygonsMapping.ODOMETER[1], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer0010Items = makeNumberItems(
            PolygonsMapping.ODOMETER[10], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer0100Items = makeNumberItems(
            PolygonsMapping.ODOMETER[100], PolygonsMapping.STANDARD_NUMBERS)
        self.watterOdometer1000Items = makeNumberItems(
            PolygonsMapping.ODOMETER[1000], PolygonsMapping.STANDARD_NUMBERS)
        # Initial rendering
        self.renderBackground()
        self.renderTachometerScale(self.tachometerEngineItems,
                                   self.tachometerEngineRpm,
                                   self.tachometerEngineLevel)
        self.renderTachometerScale(self.tachometerGearboxItems,
                                   self.tachometerGearboxRpm,
                                   self.tachometerGearboxLevel)
        self.renderAccelerometer()
        self.renderSteeringWheelEncoder()
        self.renderTurnLeftIndicator()
        self.renderTurnRightIndicator()
        self.renderOilWarningIndicator()
        self.renderWatterWarningIndicator()
        self.renderGearNumber()
        self.renderSpeedometer()
        self.renderStopwatch()
        self.renderOilManometer()
        self.renderOilThermometer()
        self.renderWatterThermometer()
        self.renderOdometer()

    # Helpers

    def renderNumberHelper(self, number: int, items: Dict[str, QStandardItem],
                           level: DashboardLevel) -> None:
        def setLevel(p: QStandardItem, l: DashboardLevel):
            p.setPen(self.levelPens[l])
            p.setBrush(self.levelBrushes[l])

        if level != DashboardLevel.inactive:
            for s in PolygonsMapping.NUMBER_TO_SEGMENTS[number][0]:
                setLevel(items[s], level)
            for s in PolygonsMapping.NUMBER_TO_SEGMENTS[number][1]:
                setLevel(items[s], DashboardLevel.inactive)
        else:
            for _, p in items.items():
                setLevel(p, DashboardLevel.inactive)

    def renderTripleNumberHelper(self, value: int,
                                 items001: Dict[str, QStandardItem],
                                 items010: Dict[str, QStandardItem],
                                 items100: Dict[str, QStandardItem],
                                 level: DashboardLevel) -> None:
        v001 = value % 10
        v010 = (value % 100) // 10
        v100 = value // 100
        self.renderNumberHelper(v001, items001, level)
        self.renderNumberHelper(
            v010, items010,
            level if v010 > 0 or v100 > 0 else DashboardLevel.inactive)
        self.renderNumberHelper(v100, items100,
                                level if v100 > 0 else DashboardLevel.inactive)

    # Rendering

    def renderBackground(self) -> None:
        logging.debug(f"[Dashboard.renderBackground] For mode = {self.mode}")
        # Render background pixmap
        self.backgroundItem.setPixmap(self.backgroundPixmaps[self.mode])
        # Re-render all indicators
        self.renderTachometerScale(self.tachometerEngineItems,
                                   self.tachometerEngineRpm,
                                   self.tachometerEngineLevel)
        self.renderTachometerScale(self.tachometerGearboxItems,
                                   self.tachometerGearboxRpm,
                                   self.tachometerGearboxLevel)
        self.renderTachometerGear(1, self.tachometerGear1Rpm)
        self.renderTachometerGear(2, self.tachometerGear2Rpm)
        self.renderTachometerGear(3, self.tachometerGear3Rpm)
        self.renderTachometerGear(4, self.tachometerGear4Rpm)
        self.renderTachometerGear(5, self.tachometerGear5Rpm)
        self.renderAccelerometer()
        self.renderSteeringWheelEncoder()
        self.renderTurnLeftIndicator()
        self.renderTurnRightIndicator()
        self.renderOilWarningIndicator()
        self.renderWatterWarningIndicator()
        self.renderGearNumber()
        self.renderSpeedometer()
        self.renderStopwatch()
        self.renderOilManometer()
        self.renderOilThermometer()
        self.renderWatterThermometer()
        self.renderOdometer()

    def renderTachometerScale(self, items: Dict[int, QStandardItem], rpm: int,
                              level: DashboardLevel) -> None:
        segment = round(rpm / self.TACHOMETER_SCALING)
        for k, p in items.items():
            if k <= segment:
                p.setPen(self.levelPens[level])
                p.setBrush(self.levelBrushes[level])
            else:
                p.setPen(self.levelPens[DashboardLevel.inactive])
                p.setBrush(self.levelBrushes[DashboardLevel.inactive])

    def renderTachometerGear(self, gearNumber: int, rpm: int) -> None:
        (arrowItem, numberItem) = self.tachometerGearsItems[gearNumber]
        segment = ((rpm if rpm <= 8600 else 8600) // 200) * 2
        (arrowTrans, numberTrans) = self.tachometerGearsTransforms[segment]
        arrowItem.setTransform(arrowTrans)
        arrowItem.setPen(self.tachometerGearsPens["A"])
        arrowItem.setBrush(self.tachometerGearsBrushes["A"])
        numberItem.setTransform(numberTrans)
        numberItem.setPen(self.tachometerGearsPens["N"])
        numberItem.setBrush(self.tachometerGearsBrushes["N"])

    def renderAccelerometer(self) -> None:
        newPen = self.levelPens[self.accelerometerLevel]
        newBrush = self.levelBrushes[self.accelerometerLevel]
        self.accelerometerCenterItem.setPen(newPen)
        self.accelerometerCenterItem.setBrush(newBrush)
        self.accelerometerSectorItem.setPen(newPen)
        self.accelerometerSectorItem.setBrush(newBrush)
        span = ((self.ACCELEROMETER_MAX_ANGEL - self.ACCELEROMETER_MIN_ANGEL) * self.accelerometerValue)\
            + self.ACCELEROMETER_MIN_ANGEL
        startAngel = self.accelerometerAngel - (span / 2)
        correctedAngel = ((startAngel - 90) if startAngel >= 90 else
                          (270 + startAngel))
        self.accelerometerSectorItem.setStartAngle(int(correctedAngel) * 16)
        self.accelerometerSectorItem.setSpanAngle(int(span) * 16)

    def renderSteeringWheelEncoder(self) -> None:
        angel = self.steeringWheelEncoderAngel
        for k, p in self.steeringWheelEncoderItems.items():
            if (angel == 0 and k == 0) or (abs(k) <= abs(angel) and k != 0 and
                                           (k * angel) > 0):
                p.setPen(self.levelPens[self.steeringWheelEncoderLevel])
                p.setBrush(self.levelBrushes[self.steeringWheelEncoderLevel])
            else:
                p.setPen(self.levelPens[DashboardLevel.inactive])
                p.setBrush(self.levelBrushes[DashboardLevel.inactive])

    def renderTurnLeftIndicator(self) -> None:
        self.turnIndicatorLeftItem.setPen(
            self.levelPens[self.turnLeftIndicatorLevel])
        self.turnIndicatorLeftItem.setBrush(
            self.levelBrushes[self.turnLeftIndicatorLevel])

    def renderTurnRightIndicator(self) -> None:
        self.turnIndicatorRightItem.setPen(
            self.levelPens[self.turnRightIndicatorLevel])
        self.turnIndicatorRightItem.setBrush(
            self.levelBrushes[self.turnRightIndicatorLevel])

    def renderOilWarningIndicator(self) -> None:
        for p in self.oilWarningIndicatorItems:
            p.setPen(self.levelPens[self.oilWarningIndicatorLevel])
            p.setBrush(self.levelBrushes[self.oilWarningIndicatorLevel])

    def renderWatterWarningIndicator(self) -> None:
        for p in self.watterWarningIndicatorItems:
            p.setPen(self.levelPens[self.watterWarningIndicatorLevel])
            p.setBrush(self.levelBrushes[self.watterWarningIndicatorLevel])

    def renderGearNumber(self) -> None:
        for s in PolygonsMapping.GEAR_NUMBER["M"][self.gearNumberValue][0]:
            segment = self.gearNumberItems[s]
            segment.setPen(self.gearNumberPen)
            segment.setBrush(self.gearNumberBrush)
        for s in PolygonsMapping.GEAR_NUMBER["M"][self.gearNumberValue][1]:
            segment = self.gearNumberItems[s]
            segment.setPen(self.levelPens[DashboardLevel.inactive])
            segment.setBrush(self.levelBrushes[DashboardLevel.inactive])

    def renderSpeedometer(self) -> None:
        self.renderTripleNumberHelper(self.speedometerValue,
                                      self.speedometer001Items,
                                      self.speedometer010Items,
                                      self.speedometer100Items,
                                      self.speedometerLevel)

    def renderStopwatch(self) -> None:
        self.renderNumberHelper(self.stopwatchMills % 10,
                                self.stopwatchMS01Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchMills // 10,
                                self.stopwatchMS10Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchSeconds % 10,
                                self.stopwatchS01Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchSeconds // 10,
                                self.stopwatchS10Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchMinutes % 10,
                                self.stopwatchM01Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchMinutes // 10,
                                self.stopwatchM10Items, self.stopwatchLevel)
        self.renderNumberHelper(self.stopwatchHours, self.stopwatchH01Items,
                                self.stopwatchLevel)

    def renderOilManometer(self) -> None:
        intValue = int(self.oilManometerValue * 100)
        self.renderNumberHelper(intValue % 10, self.oilManometer0d01Items,
                                self.oilManometerLevel)
        self.renderNumberHelper((intValue % 100) // 10,
                                self.oilManometer0d10Items,
                                self.oilManometerLevel)
        self.renderNumberHelper(intValue // 100, self.oilManometer1d00Items,
                                self.oilManometerLevel)

    def renderOilThermometer(self) -> None:
        self.renderTripleNumberHelper(self.oilThermometerValue,
                                      self.oilThermometer001Items,
                                      self.oilThermometer010Items,
                                      self.oilThermometer100Items,
                                      self.oilThermometerLevel)

    def renderWatterThermometer(self) -> None:
        self.renderTripleNumberHelper(self.watterThermometerValue,
                                      self.watterThermometer001Items,
                                      self.watterThermometer010Items,
                                      self.watterThermometer100Items,
                                      self.watterThermometerLevel)

    def renderOdometer(self) -> None:
        v0001 = (self.odometerValue % 10)
        v0010 = (self.odometerValue % 100) // 10
        v0100 = (self.odometerValue % 1000) // 100
        v1000 = self.odometerValue // 1000

        def level(isActive: bool):
            return self.odometerLevel if isActive > 0 else DashboardLevel.inactive

        self.renderNumberHelper(v0001, self.watterOdometer0001Items,
                                self.odometerLevel)
        self.renderNumberHelper(v0010, self.watterOdometer0010Items,
                                level(v0010 > 0 or v0100 > 0 or v1000 > 0))
        self.renderNumberHelper(v0100, self.watterOdometer0100Items,
                                level(v0100 > 0 or v1000 > 0))
        self.renderNumberHelper(v1000, self.watterOdometer1000Items,
                                level(v1000 > 0))

    # Methods

    @pyqtSlot(DriveMode)
    def inMode(self, mode: DriveMode) -> None:
        logging.debug(f"[Dashboard.inMode] New mode = {mode}")
        # Store new state
        self.mode = mode
        # Redraw UI
        self.renderBackground()

    @pyqtSlot(int, DashboardLevel)
    def inTachometerEngine(self, rpm: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inTachometerEngine] New rpm = {rpm}, level = {level}")
        # Store new state
        self.tachometerEngineRpm = 0 if rpm < 0 else (
            9000 if rpm > 9000 else rpm)
        self.tachometerEngineLevel = level
        # Redraw UI
        self.renderTachometerScale(self.tachometerEngineItems,
                                   self.tachometerEngineRpm,
                                   self.tachometerEngineLevel)

    @pyqtSlot(int, DashboardLevel)
    def inTachometerGearbox(self, rpm: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inTachometerGearbox] New rpm = {rpm}, level = {level}"
        )
        # Store new state
        self.tachometerGearboxRpm = 0 if rpm < 0 else (
            9000 if rpm > 9000 else rpm)
        self.tachometerGearboxLevel = level
        # Redraw UI
        self.renderTachometerScale(self.tachometerGearboxItems,
                                   self.tachometerGearboxRpm,
                                   self.tachometerGearboxLevel)

    @pyqtSlot(int, int, int, int, int)
    def inTachometerGears(self, rpm1: int, rpm2: int, rpm3: int, rpm4: int,
                          rpm5: int) -> None:
        logging.debug(
            f"[Dashboard.inTachometerGears] New rpm1 = {rpm1}, rpm2 = {rpm2}, rpm3 = {rpm3}, "
            f"rpm4 = {rpm4}, rpm5 = {rpm5}")
        # Store new state
        self.tachometerGear1Rpm = 0 if rpm1 < 0 else (
            9000 if rpm1 > 9000 else rpm1)
        self.tachometerGear2Rpm = 0 if rpm2 < 0 else (
            9000 if rpm2 > 9000 else rpm2)
        self.tachometerGear3Rpm = 0 if rpm3 < 0 else (
            9000 if rpm3 > 9000 else rpm3)
        self.tachometerGear4Rpm = 0 if rpm4 < 0 else (
            9000 if rpm4 > 9000 else rpm4)
        self.tachometerGear5Rpm = 0 if rpm5 < 0 else (
            9000 if rpm5 > 9000 else rpm5)
        # Redraw UI
        self.renderTachometerGear(1, self.tachometerGear1Rpm)
        self.renderTachometerGear(2, self.tachometerGear2Rpm)
        self.renderTachometerGear(3, self.tachometerGear3Rpm)
        self.renderTachometerGear(4, self.tachometerGear4Rpm)
        self.renderTachometerGear(5, self.tachometerGear5Rpm)

    @pyqtSlot(int, float, DashboardLevel)
    def inAccelerometer(self, angel: int, value: float,
                        level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inAccelerometer] New angel = {angel}, value = {value}, level = {level}"
        )
        # Store new state
        self.accelerometerAngel = -180 if angel < -180 else (
            180 if angel > 180 else angel)
        self.accelerometerValue = 0.0 if value < 0.0 else (
            1.0 if value > 1.0 else value)
        self.accelerometerLevel = level
        # Redraw UI
        self.renderAccelerometer()

    @pyqtSlot(int, DashboardLevel)
    def inSteeringWheelEncoder(self, angel: int,
                               level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inSteeringWheelEncoder] New angel = {angel}, level = {level}"
        )
        # Store new state
        self.steeringWheelEncoderAngel = -7 if angel < -7 else (
            7 if angel > 7 else angel)
        self.steeringWheelEncoderLevel = level
        # Redraw UI
        self.renderSteeringWheelEncoder()

    @pyqtSlot(DashboardLevel)
    def inTurnLeftIndicator(self, level: DashboardLevel) -> None:
        logging.debug(f"[Dashboard.inTurnLeftIndicator] New level = {level}")
        # Store new state
        self.turnLeftIndicatorLevel = level
        # Redraw UI
        self.renderTurnLeftIndicator()

    @pyqtSlot(DashboardLevel)
    def inTurnRightIndicator(self, level: DashboardLevel) -> None:
        logging.debug(f"[Dashboard.inTurnRightIndicator] New level = {level}")
        # Store new state
        self.turnRightIndicatorLevel = level
        # Redraw UI
        self.renderTurnRightIndicator()

    @pyqtSlot(int)
    def inGearNumber(self, value: int) -> None:
        logging.debug(f"[Dashboard.inGearNumber] New value = {value}")
        # Store new state
        self.gearNumberValue = 0 if value < 0 else (5 if value > 5 else value)
        # Redraw UI
        self.renderGearNumber()

    @pyqtSlot(DashboardLevel)
    def inOilWarningIndicator(self, level: DashboardLevel) -> None:
        logging.debug(f"[Dashboard.inOilWarningIndicator] New level = {level}")
        # Store new state
        self.oilWarningIndicatorLevel = level
        # Redraw UI
        self.renderOilWarningIndicator()

    @pyqtSlot(DashboardLevel)
    def inWatterWarningIndicator(self, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inWatterWarningIndicator] New level = {level}")
        # Store new state
        self.watterWarningIndicatorLevel = level
        # Redraw UI
        self.renderWatterWarningIndicator()

    @pyqtSlot(int, DashboardLevel)
    def inSpeedometer(self, value: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inSpeedometer] New value = {value}, level = {level}")
        # Store new state
        self.speedometerValue = 0 if value < 0 else (
            999 if value > 999 else value)
        self.speedometerLevel = level
        # Redraw UI
        self.renderSpeedometer()

    @pyqtSlot(int, int, int, int, DashboardLevel)
    def inStopwatch(self, mills: int, seconds: int, minutes: int, hours: int,
                    level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inStopwatch] New mills = {mills}, seconds = {seconds}, minutes = {minutes}, "
            f"hours = {hours}, level = {level}")
        # Store new state
        self.stopwatchMills = 0 if mills < 0 else (99 if mills > 99 else mills)
        self.stopwatchSeconds = 0 if seconds < 0 else (
            59 if seconds > 59 else seconds)
        self.stopwatchMinutes = 0 if minutes < 0 else (
            59 if minutes > 59 else minutes)
        self.stopwatchHours = 0 if hours < 0 else (9 if hours > 9 else hours)
        self.stopwatchLevel = level
        # Redraw UI
        self.renderStopwatch()

    @pyqtSlot(float, DashboardLevel)
    def inOilManometer(self, value: float, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inOilManometer] New value = {value}, level = {level}")
        # Store new state
        self.oilManometerValue = 0.0 if value < 0.0 else (
            9.99 if value > 9.99 else value)
        self.oilManometerLevel = level
        # Redraw UI
        self.renderOilManometer()

    @pyqtSlot(int, DashboardLevel)
    def inOilThermometer(self, value: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inOilThermometer] New value = {value}, level = {level}"
        )
        # Store new state
        self.oilThermometerValue = 0 if value < 0 else (
            999 if value > 999 else value)
        self.oilThermometerLevel = level
        # Redraw UI
        self.renderOilThermometer()

    @pyqtSlot(int, DashboardLevel)
    def inWatterThermometer(self, value: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inWatterThermometer] New value = {value}, level = {level}"
        )
        # Store new state
        self.watterThermometerValue = 0 if value < 0 else (
            999 if value > 999 else value)
        self.watterThermometerLevel = level
        # Redraw UI
        self.renderWatterThermometer()

    @pyqtSlot(int, DashboardLevel)
    def inOdometer(self, value: int, level: DashboardLevel) -> None:
        logging.debug(
            f"[Dashboard.inOdometer] New value = {value}, level = {level}")
        # Store new state
        self.odometerValue = 0 if value < 0 else (
            9999 if value > 9999 else value)
        self.odometerLevel = level
        # Redraw UI
        self.renderOdometer()
Ejemplo n.º 27
0
class BoardGUI(QWidget):
    """cointain the graphical representation of the Board"""

    # ratio of bordersize compared to the size of one base square
    borderRatio = 0.8
    baseRectRatio = 14 / 15  # 12/13 for normal ratio but looks weird
    stoneScale = 0.46

    # siganl
    stoneClicked = pyqtSignal(tuple)

    def __init__(self, parent, game):
        super().__init__()

        self.initUI(game)

    def initUI(self, game):
        self.board = game.currentBoard
        self.game = game

        self.showCoords = True
        self.scene = QGraphicsScene()

        # grid containing coordinates for the scene
        self.grid = []
        self.drawGrid()

        # initialize and set layout + view
        self.view = QGraphicsView(self.scene)
        self.view.setMouseTracking(True)
        self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        self.setMouseTracking(True)
        box = QHBoxLayout()
        box.addWidget(self.view)
        self.setLayout(box)

        # stones for all positions are created and listed in self.pos dict
        self.createPosition()
        self.makeCoords()  # has to be called after drawGrid!

    def resizeEvent(self, e):
        self.view.fitInView(self.view.scene().sceneRect(), Qt.KeepAspectRatio)

    def boardWidth(self):
        """returns the max width fitting into widget"""
        width = self.contentsRect().width() * 0.95
        height = self.contentsRect().height() * 0.95

        return min(width, height * self.baseRectRatio)

    def boardHeight(self):
        """returns the max width fitting into widget """
        return self.boardWidth() * (1 / self.baseRectRatio)

    def makeGrid(self):
        """
        returns coords [[(x, y)]] for the Grid according
         to current window mesures
        """
        # set scenesize to window size
        self.scene.setSceneRect(0, 0, self.boardWidth(), self.boardHeight())
        denom = self.board.size + 2 * self.borderRatio
        baseWidth = self.boardWidth() / denom
        baseHeight = self.boardHeight() / denom

        leftOffset = 0.5 * baseWidth  # (self.contentsRect().width()-self.boardWidth())/2
        topOffset = 0  # (self.contentsRect().height()-self.boardHeight())/2

        partionWidth = [
            leftOffset + (self.borderRatio + x) * baseWidth
            for x in range(self.board.size)
        ]
        partionHeight = [
            topOffset + (self.borderRatio + x) * baseHeight
            for x in range(self.board.size)
        ]

        grid = [[(x, y) for x in partionWidth] for y in partionHeight]
        self.grid = grid
        self.baseWidth = baseWidth

    def drawGrid(self):
        """draws the background grid"""
        self.makeGrid()
        for line in self.grid:
            self.scene.addLine(*line[0], *line[-1])
        for (pointT, pointB) in zip(self.grid[0], self.grid[-1]):
            self.scene.addLine(*pointT, *pointB)
        self.drawHoshis()

    def makeCoords(self):
        """ draws Coordinates """
        xLabels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
        yLabels = list(range(1, 26))
        botGrid = []
        leftGrid = []
        # generate pixel coordinates grids
        for n in range(self.board.size):
            (xBot, yBot) = self.grid[self.board.size - 1][n]
            yBot += self.baseWidth * 0.4 / self.baseRectRatio
            xBot -= self.baseWidth * 0.1
            botGrid.append((xBot, yBot))
            (xLeft, yLeft) = self.grid[n][0]
            xLeft -= self.baseWidth * 1.2
            yLeft -= self.baseWidth * 0.3 / self.baseRectRatio
            leftGrid.append((xLeft, yLeft))
        # generate Text items and add them to group
        self.coordGroup = QGraphicsItemGroup()
        for n in range(self.board.size):
            leftText = QGraphicsSimpleTextItem(str(yLabels[n]))
            leftText.setPos(*leftGrid[n])
            self.coordGroup.addToGroup(leftText)
            bottomText = QGraphicsSimpleTextItem(xLabels[n])
            bottomText.setPos(*botGrid[n])
            self.coordGroup.addToGroup(bottomText)
        # draw coordinates and update visibility according to self.showCoords
        self.scene.addItem(self.coordGroup)
        self.updateCoords()

    def updateCoords(self):
        """ slot that updates the visibility os the coordiantes. """
        self.coordGroup.setVisible(self.showCoords)

    def setCoordVis(self, visibility):
        """ set the self.showCoords boolean """
        self.showCoords = visibility
        self.updateCoords()

    def drawHoshis(self):
        """ Draws Hoshi dots"""
        hoshis = []
        rad = self.baseWidth * 0.15
        for (x, y) in self.board.getHoshis():
            hoshis.append(self.grid[x][y])
        for point in hoshis:
            (x, y) = point
            self.scene.addEllipse(x - rad, y - rad, rad * 2.0, rad * 2.0,
                                  QPen(), QBrush(Qt.SolidPattern))

    def updatePosition(self):
        """
        sets the colors for all stones in self.pos according
        to the status in self.board
        """
        for (x, y) in self.pos:
            color = self.game.currentBoard.getPosition(x, y)
            self.pos[(x, y)].setMark(None)
            self.pos[(x, y)].setColor(color)
        lastMove = self.game.currentBoard.lastMove
        if lastMove:
            self.pos[lastMove].setMark(GoMarks.circel)
        ko = self.game.currentBoard.ko
        if ko:
            self.pos[ko].setMark(GoMarks.square)

    def createPosition(self):
        """
        Creates the self.pos dictionary containing all possible stones on the
        board initialized as empty stones

        also connects a signal form each stone to ???
        """
        self.pos = {}
        radius = self.stoneScale * self.baseWidth
        for row in range(self.board.size):
            for col in range(self.board.size):
                (x, y) = self.grid[row][col]
                newStone = Stone(x, y, radius)
                self.pos[(row, col)] = newStone
                self.scene.addItem(newStone)
        self.updatePosition()
        self.connecting()

    def connecting(self):
        for key in self.pos:
            self.pos[key].clicked.connect(lambda key=key: self.resend(key))

    def resend(self, pos):
        """
        emits the captured signal again,
        with (int, in) parameter for stone clicked
        """
        self.stoneClicked.emit(pos)
Ejemplo n.º 28
0
class Paint(QGraphicsView):  #clase para crear el plano donde podremos dibujar
    def __init__(self):
        QGraphicsView.__init__(self)

        r = QRectF(self.viewport().rect()
                   )  #área de la ventana en la que se podrá dibujar
        self.setSceneRect(r)
        self.scene = QGraphicsScene(
        )  #escena que debemos añadir al plano de dibujo

        self.isParticles = False  #para dibujar partículas

        self.penColors = [
            Qt.red, QColor.fromRgb(255, 105, 180), Qt.blue, Qt.green
        ]  #lista de colores para el pen (el de rgb es rosa, por si hace falta)

        self.globalList = [
        ]  #lista para llevar ordenados los ids de curvas y partículas que se van dibujando en las imgs (para el UNDO)

        self.N = 10  #número de puntos a partir del cual lo dibujado se corresponde a una curva y no a una partícula

        self.setScene(self.scene)  #para incluir la escena en el plano

        self.previousPoint = None  #para quitar la separación entre puntos cuando se dibuja muy rápido

    def initIMG(self, filename, scale):
        self.scene.clear()  #con clear() se queda el plano en blanco

        self.colorN = 0  #comenzamos pintando curvas en rojo

        self.imgCurves = dict(
        )  #diccionario para guardar cada curva de la imagen como clave, y como valores su lista de puntos
        self.imgParticles = dict(
        )  #diccionario para guardar cada partícula de la imagen como clave, y como valores su lista de puntos

        self.curveCounter = 1  #contador para indicar la curva
        self.particleCounter = 1  # contador de partículas

        self.pointList = []  #lista de puntos para las curvas de la imagen
        self.particleList = []  #lista de partículas

        utilsPac.cropImageBorders(
            filename)  #recortar los bordes negros de la imagen

        img = QImage(filename)  #convertir la imagen a QImage
        imgS = img.scaled(img.width() * scale,
                          img.height() * scale)  #ajustar la img a la pantalla

        self.pixMap = QPixmap().fromImage(imgS)  #convertir la imagen a QPixmap
        scenePix = self.scene.addPixmap(
            self.pixMap)  # añadimos la imagen (escalada) a la escena
        scenePix.setPos(
            -350, -70
        )  #esto es para que la imagen este en la esquina superior izquierda

    def draw(self, e, thickness, width=1):  #función para pintar con el raton
        self.pen = QPen(
            self.penColors[self.colorN]
        )  #creamos un pen y le asociamos un color de la lista de colores
        self.pen.setWidth(width)  #grosor de la línea
        brush = QBrush(
            Qt.SolidPattern)  #para que lo que se dibuje no tenga transparencia
        # incluir el pen a la escena: el pen dibuja círculos (ellipse con altura=thickness y anchura=thickness), el brush los rellena
        self.scene.addItem(
            self.scene.addEllipse(e.x(), e.y(), thickness, thickness, self.pen,
                                  brush))

        self.scene.update()  #para actualizar los puntos dibujados con el ratón

    def mousePressEvent(self, event):  #cuando se pulsa el ratón
        e = QPointF(self.mapToScene(
            event.pos()))  #crear un punto en la posición marcada por el ratón

        self.previousPoint = (
            e.x(), e.y()
        )  #lo guardamos para poder comprobar su distancia con el siguiente punto

        self.colorN = 0  #cuando empezamos a dibujar, siempre pintamos en rojo
        self.pointList.append(
            (e.x(),
             e.y()))  # añadir el punto a la lista de puntos para las curvas

        self.draw(
            e, 1
        )  #dibujar el punto de la curva/partícula con una thickness = 1 (grosor del lápiz)

    def mouseMoveEvent(self,
                       event):  #cuando se mueve el ratón mientras está pulsado
        e = QPointF(self.mapToScene(
            event.pos()))  #crear un punto en la posición marcada por el ratón

        self.completeWithLine(
            self.previousPoint, (e.x(), e.y())
        )  #completar los puntos con una línea recta si están muy separados
        self.previousPoint = (
            e.x(), e.y()
        )  #guardamos el punto para poder calcular la distancia con el siguiente

        self.colorN = 0  #seguimos pintando en rojo
        self.pointList.append(
            (e.x(),
             e.y()))  # añadir el punto a la lista de puntos para las curvas

        self.draw(
            e, 1
        )  #dibujar el punto de la curva/partícula con una thickness = 1 (grosor del lápiz)

    def mouseReleaseEvent(self, event, scale=None):  #cuando se suelta el ratón
        if len(
                self.pointList
        ) > self.N:  #si el numero de puntos del trazo es mayor que N (N determina si es curva o partícula)...
            self.isParticles = False  #el trazo dibujado es una curva

            if not scale == None:  #aplicar escala
                self.pointList = [(x * scale, y * scale)
                                  for (x, y) in self.pointList]

            # terminar la curva con una línea recta
            start = self.pointList[
                0]  #el comienzo de dicha línea sera el primer punto dibujado
            end = self.pointList[
                len(self.pointList) -
                1]  #el final de dicha línea sera el último punto dibujado
            self.completeWithLine(start, end)  #dibujamos la línea

            curveN = "curve" + str(
                self.curveCounter
            )  #esto será la clave del diccionario (curve1, curve2...)
            self.curveCounter += 1  #aumentamos el contador de curva

            # diccionario para asociar una lista de puntos a cada una de las curvas de la imagen
            self.imgCurves.update({curveN: self.pointList})

            #añadir el id de la curva a la lista global
            self.globalList.append(curveN)

            # una vez guardados los puntos de una curva, reiniciamos la lista de puntos para poder pintar una nueva curva
            self.pointList = []
        else:
            self.isParticles = True  #el trazo dibujado es una partícula

            particle = self.pointList.pop(
            )  #si se han dibujado varios puntos, nos quedamos con el último de ellos
            p = particle

            if not scale == None:  # aplicar escala
                p[0] = p[0] * scale
                p[1] = p[1] * scale

            particleN = "particle" + str(
                self.particleCounter
            )  #clave del diccionario (particle1, particle2...)
            self.particleCounter += 1  #aumentamos el contador de partículas

            # diccionario para asociar una lista de puntos a cada una de las partículas de la imagen
            self.imgParticles.update({particleN: particle})

            # añadir el id de la partícula a la lista global
            self.globalList.append(particleN)

            # una vez guardados los puntos de una partícula, reiniciamos la lista de puntos para poder pintar nuevas partículas
            self.pointList = []

            self.colorN = 2  #las partículas las pintamos en azul
            e = QPointF(p[0], p[1])  #creamos un punto en la posición marcada
            #le restamos 3 píxeles para que el punto se dibuje centrado, justo donde se ha marcado con el ratón
            e.setX(e.x() - 3)
            e.setY(e.y() - 3)

            self.draw(
                e, 8, 2
            )  #pintamos la partícula, con un grosor de lápiz=8, y un radio de brush=2 (para que se vea bien hermosote)

    def completeWithLine(
            self, start,
            end):  #función para completar el trazo con líneas rectas
        startPoint = QPointF(
            start[0], start[1]
        )  #creamos un punto con las coordernadas del punto de inicio
        endPoint = QPointF(
            end[0],
            end[1])  #creamos un punto con las coordernadas del punto de fin
        self.line = QGraphicsLineItem(QLineF(
            startPoint, endPoint))  #dibujamos una línea con esos ptos
        # para que la línea se vea bien, la pintamos un poco más gordita
        self.pen.setWidth(2)
        self.line.setPen(self.pen)

        self.scene.addItem(self.line)  #añadimos la línea a la escena

    def loadCurves(
            self,
            inputName,
            scale=None):  #función para cargar las curvas de la img actual
        self.colorN = 0  #las curvas de la img actual van en rojo
        if os.path.isfile(
                inputName
        ):  #si hay algún json con curvas de otra sesión anterior...
            with open(
                    inputName, 'r'
            ) as f:  #lo leemos y escribimos su contenido en el diccionario de curvas de la img
                s = f.read()
                self.imgCurves = json.loads(s)
                if not len(self.imgCurves
                           ) == 0:  #si hay alguna curva en el diccionario...
                    self.drawPastCurves(
                        self.imgCurves, 1, scale
                    )  #la dibujamos en la img, con un grosor de lápiz=1 (más finita para que no moleste)
                else:
                    print("there are no curves for this image")
        else:
            print("there's no json file for this image")

    def loadParticles(
            self,
            inputName,
            scale=None):  #función para cargar las partículas de la img actual
        self.colorN = 2  #las partículas de la img actual van en azul
        if os.path.isfile(
                inputName
        ):  #si hay algún json con partículas de otra sesión anterior...
            with open(
                    inputName, 'r'
            ) as f:  #lo leemos y escribimos su contenido en el diccionario de partículas de la img
                s = f.read()
                self.imgParticles = json.loads(s)
                if not len(
                        self.imgParticles
                ) == 0:  #si hay alguna partícula en el diccionario...
                    self.drawPastParticles(
                        self.imgParticles, 8, scale
                    )  #la dibujamos en la img, con un grosor de lápiz=8 (para que se vean bien)
                else:
                    print("there are no particles for this image")
        else:
            print("there's no json file for this image")

    def drawPastCurves(self, dic, thickness,
                       scale):  #función para pintar las curvas del json
        for curve, points in dic.items():  #recorremos el diccionario de curvas
            self.curveCounter += 1  #aumentamos el contador de curva para que las claves del diccionario sigan un orden lógico

            if not scale == None:  # aplicar escala
                points = [(x / scale, y / scale) for (x, y) in points]

            for i in range(
                    len(points) - 1
            ):  #recorremos la lista de puntos pertenecientes a una curva
                e = QPointF(
                    points[i][0], points[i]
                    [1])  # crear un punto en la posición marcada por el json
                self.draw(e, thickness)  #dibujarlo con el grosor especificado

                # volver a dibujar los puntos de la curva, sin separaciones entre ellos (para la función completeWithLine)
                distance = numpy.sqrt(((points[i][0] - points[i + 1][0])**2) +
                                      ((points[i][1] - points[i + 1][1])**2))
                if distance > 2:  #si la distancia euclídea entre ptos consecutivos es muy grande, debemos rellenar el espacio con una línea recta
                    self.completeWithLine(points[i], points[i + 1])

            # terminar con una línea recta si se deja de dibujar y la curva no estaba completa
            start = points[0]
            end = points[len(points) - 1]
            self.completeWithLine(start, end)

    def drawPastParticles(self, dic, thickness,
                          scale):  #función para pintar las partículas del json
        for keyN, particle in dic.items(
        ):  #recorremos el diccionario de partículas
            self.particleCounter += 1  #aumentamos el contador de partícula para que las claves del diccionario sigan un orden lógico

            if not scale == None:
                particle[0] = particle[0] / scale
                particle[1] = particle[1] / scale

            e = QPointF(
                particle[0],
                particle[1])  #creamos el punto en la posición de la partícula
            self.draw(e, thickness, 2)  #la dibujamos gordita

    def showPrevCurves(
            self, currentImg,
            prevImg):  #función para mostrar curvas de la imagen anterior
        if os.path.isfile(prevImg):  #si hay img anterior...

            with open(
                    prevImg, 'r'
            ) as f:  #leemos su json de curvas y guardamos los ptos en un diccionario
                s = f.read()
                dic = json.loads(s)

                if not len(dic) == 0:  #si hay alguna curva...
                    mask = self.generateMask(
                        prevImg,
                        dic)  #generamos la máscara de la img y sus curvas
                    img = cv2.imread(currentImg)  #leemos la img actual
                    # escalamos esta img con el tamaño de la máscara de la img antetior para que casen bien
                    small = cv2.resize(img, (mask.shape[1], mask.shape[0]))
                    small[
                        mask ==
                        0] //= 2  #mostramos la img actual oscurecida en los ptos de la máscara que estén a 0 (negro)

                    # volvemos a hacer resize (primero con la Y y luego la X) para mostrar la img en la ventana:
                    img = cv2.resize(small, (img.shape[1], img.shape[0]))

                    head, sep, tail = currentImg.rpartition(
                        "/")  #para meterlo en la carpeta data
                    currentImgData = head + "/data/" + tail

                    cv2.imwrite(
                        currentImgData + '_masked.png',
                        img)  #guardamos la mascara en un png para comprobar

                    return currentImgData + '_masked.png'  #la devolvemos

                else:  #si no hay curvas
                    img = cv2.imread(currentImg)  #leemos la img actual
                    img //= 2  #oscurecemos toda la img, puesto que no hay ninguna curva en la img anterior (su máscara sería todo 0's)

                    head, sep, tail = currentImg.rpartition(
                        "/")  # para meterlo en la carpeta data
                    currentImgData = head + "/data/" + tail

                    cv2.imwrite(
                        currentImgData + '_masked.png',
                        img)  #guardamos la máscara en un png para comprobar

                    return currentImgData + '_masked.png'  #la devolvemos
        else:
            return currentImg

    def showPrevParticles(
            self,
            inputName,
            scale=None
    ):  #función para mostrar partículas de la imagen anterior
        self.colorN = 3  #las pintamos en verde

        if os.path.isfile(
                inputName
        ):  #si existe un fichero de partículas de la img anterior, lo leemos y cargamos los ptos en el diccionario

            with open(inputName, 'r') as f:
                s = f.read()
                dic = json.loads(s)

                if not len(
                        dic
                ) == 0:  #si no está vacío, dibujamos los puntos gorditos
                    self.drawPastParticles(dic, 8, scale)

                else:
                    print("there are no particles for this image")
        else:
            print("there's no json file for this image")

    def generateMask(
        self, outputName, dic
    ):  #generar la máscara de una img: 0 negro (fuera de la curva), 255 blanco (area dentro de la curva)

        if 'particles' not in outputName:  #si es curva..
            finalMaskCurves = numpy.zeros(
                (self.pixMap.height(), self.pixMap.width()
                 ))  #creamos un array de 0's (toda la máscara negra al ppio)

            for keyN, points in dic.items():  #recorremos las curvas
                #para cada curva, generamos su máscara correspondiente
                mask = utilsPac.getMask(
                    dic[keyN],
                    (self.pixMap.height(), self.pixMap.width()
                     ))  #obtenemos la máscara (esta función es la más pesada)
                finalMaskCurves[
                    mask] = 255  #los puntos dentro de la curva seran blancos (255)

            cv2.imwrite(outputName + '_maskCurves.png', finalMaskCurves)
            return finalMaskCurves

        else:  #si es partícula...
            finalMaskParticles = numpy.zeros(
                (self.pixMap.height(), self.pixMap.width()
                 ))  #creamos un array de 0's (toda la máscara negra al ppio)

            for keyN, points in dic.items():  #recorremos las partículas
                px = int(
                    points[0]
                ) + 350  #coordenada x de la partícula (hay que sumarle la posición absoluta que le aplicamos a la img al ppio)
                py = int(points[1]) + 70  #coordenada y
                #primero la y y luego la x: 'x' son las columnas e 'y' las filas de la matriz de la imagen
                finalMaskParticles[
                    py,
                    px] = 255  #ponemos a blanco las posiciones de la máscara en las que hay partícula

            #cv2.imwrite(outputName + '_maskParticles.png', self.finalMaskParticles)
            return finalMaskParticles
Ejemplo n.º 29
0
class MapPainter(object):
    def __init__(self, parent, view, displayCities, displayConnections, displayBestUnit):
        super().__init__()
        self.view = view
        self.displayCities = displayCities
        self.displayConnections = displayConnections
        self.displayBestUnit = displayBestUnit
        self.problemMap = None
        self.bestUnit = None

        self.scene = QGraphicsScene(parent)
        self.resizeScene()

        self.view.setScene(self.scene)
        self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)

    def resizeScene(self):
        height = self.view.size().height()
        width = self.view.size().width()
        self.scene.setSceneRect(0.0, 0.0, width, height)

    def setProblemMap(self, problemMap):
        self.problemMap = problemMap

    def setBestUnit(self, unit):
        self.bestUnit = unit

    def setDisplayCities(self, enabled = False):
        self.displayCities = bool(enabled)

    def setDisplayConnections(self, enabled = False):
        self.displayConnections = bool(enabled)

    def setDisplayBestUnit(self, enabled = False):
        self.displayBestUnit = bool(enabled)

    def repaint(self):
        if self.problemMap is None:
            return

        self.scene.clear()
        self.resizeScene()
        height = self.scene.height()
        width = self.scene.width()

        if self.displayCities:
            cityBrush = QBrush(QColor(0, 0, 0), Qt.SolidPattern)
            cityPen = QPen(cityBrush, 5.0)
            for city in self.problemMap.cities:
                x = width * city.positionX
                y = height * city.positionY
                self.scene.addEllipse(x, y, 4, 4, cityPen, cityBrush)

        if self.displayConnections:
            connectionBrush = QBrush(QColor(0, 0, 255), Qt.SolidPattern)
            connectionPen = QPen(connectionBrush, 1.0)
            for city in self.problemMap.cities:
                for neighbour in city.connections:
                    x = width * city.positionX
                    y = height * city.positionY
                    x2 = width * self.problemMap.cities[neighbour].positionX
                    y2 = height * self.problemMap.cities[neighbour].positionY
                    self.scene.addLine(x, y, x2, y2, connectionPen)

        if self.displayBestUnit and self.bestUnit is not None:
            bestUnitBrush = QBrush(QColor(255, 0, 0), Qt.SolidPattern)
            bestUnitPen = QPen(bestUnitBrush, 2.0)
            for i in range(-1, len(self.bestUnit.path)-1):
                currCity = self.problemMap.cities[self.bestUnit.path[i]]
                nextCity = self.problemMap.cities[self.bestUnit.path[i+1]]
                x = width * currCity.positionX
                y = height * currCity.positionY
                x2 = width * nextCity.positionX
                y2 = height * nextCity.positionY
                self.scene.addLine(x, y, x2, y2, bestUnitPen)

        self.view.fitInView(self.scene.sceneRect())
Ejemplo n.º 30
0
class frameArbol(QGraphicsView):
    def __init__(self):
        super(frameArbol, self).__init__()
        # Inicializar el arbol de entornos
        self.arbolEntornos = None
        # Definir la ubicacion inicial en el cuadro de dibujo
        self.y = 50
        # Definir el cuadro de dibujo haciendo uso de librerias externas
        self.panelDibujo = QGraphicsScene()
        # Asignar el panelDibujo como escena principal del frame del arbol
        self.setScene(self.panelDibujo)

    # Indicar en que momento se debe repintar el canvas principal
    def drawA(self):
        self.panelDibujo.clear()
        self.graficar()

    # Proceso para graficar el arbol, incluyendo sus ambientes(nodos) y sus aristas
    def graficar(self):
        raiz = self.arbolEntornos.getRaiz()
        self.y = 50
        self.graficarArbol(raiz, 10, self.y)
        self.graficarAristas(raiz)

    # Sobrescribir el metodo mousePressEvent de la libreria QGraphicsView
    def mousePressEvent(self, event: eventoRaton) -> None:
        # Capturar las coordenadas sobre las que se realizo el evento
        coordenadaX = event.pos().x()
        coordenadaY = event.pos().y()
        # Ubicar el evento en la escena definida
        ubicacion = self.mapToScene(event.pos())
        # Obtener la reiz del arbol
        raiz = self.arbolEntornos.getRaiz()
        if (raiz != None):
            # Se crea para poder operar el ambiente, tener acceso a el
            ambienteN = QRect(int(ubicacion.x()), int(ubicacion.y()),
                              raiz.dimension, raiz.dimension)
            self.verificarNodo(raiz, ambienteN)

    # Verificar relacion panel-ambiente
    def verificarNodo(self, ambienteActual, ambienteBuscar):
        # Verificar si el ambienteActual buscado es el ambienteActual con el evento mouse
        if ambienteActual.dibujarN.intersects(ambienteBuscar):
            # Informacion del ambienteBuscar (ambienteActual)zz
            mensaje = QMessageBox()
            mensaje.setIcon(QMessageBox.Information)
            mensaje.setText("Ambiente: " + str(ambienteActual.contenido))
            mensaje.exec_()
            return True
        else:
            # Realizar la busqueda en todos los ambientes (nodos) restantes
            for i in ambienteActual.hijos:
                self.verificarNodo(i, ambienteBuscar)

    # Graficar el arbol generado
    def graficarArbol(self, ambiente, posX, posY):
        # Crear los esquemas ara utilizar la libreria
        nodo1 = QPen(Qt.black)
        nodo2 = QPen(Qt.green)
        # Asignar coordenada X y Y al nuevo ambiente
        ambiente.x = posX
        ambiente.y = self.y
        # Crear un modelo de ambiente (nodo)
        ambiente.dibujarN = QRect(ambiente.x, ambiente.y, ambiente.dimension,
                                  ambiente.dimension)
        # Definir si el ambiente esta activo para marcarlo con color diferente a los demas
        if ambiente.nActivo:
            self.panelDibujo.addEllipse(ambiente.x, ambiente.y,
                                        ambiente.dimension, ambiente.dimension,
                                        nodo2)
        else:
            self.panelDibujo.addEllipse(ambiente.x, ambiente.y,
                                        ambiente.dimension, ambiente.dimension,
                                        nodo1)

        # Informacion que tendra el ambiente

        cadena = QGraphicsTextItem()
        cadena.setPlainText(str(ambiente.nombre))
        cadena.setPos(QPointF(ambiente.x + 2, ambiente.y - 3))
        posX += 50

        # Graficar los hijos del ambiente actual
        for i in ambiente.hijos:
            self.y += 40
            self.graficarArbol(i, posX, self.y)

    # Graficar las aristas del arbol
    def graficarAristas(self, ambiente):
        linea1 = QPen(Qt.black)
        puntoIni = ambiente.dimension / 2
        for i in ambiente.hijos:
            posXInicial = ambiente.x + ambiente.dimension + 5
            posYInicial = ambiente.y + ambiente.dimension - 5
            posYFinal = i.y + puntoIni
            self.panelDibujo.addLine(ambiente.x + ambiente.dimension,
                                     posYInicial, posXInicial, posYInicial)
            self.panelDibujo.addLine(posXInicial, posYInicial, posXInicial,
                                     posYFinal, linea1)
            self.panelDibujo.addLine(posXInicial, posYFinal, i.x, posYFinal,
                                     linea1)
            self.graficarAristas(i)
Ejemplo n.º 31
0
class MyWin(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.ui = my.Ui_MainWindow()
        self.ui.setupUi(self)
        #self.ui.MainWindow.setFixedWidth(self.ui.geometry.width)
        self.setWindowIcon(QIcon('./pict/icone.png'))
        self.setWindowFlags(Qt.Window | Qt.MSWindowsFixedSizeDialogHint)

        self.ui.graph.setDisabled(True)

        self.ui.pushButton.clicked.connect(self.createP)
        self.ui.pushButton_2.clicked.connect(self.createI)

        self.ui.pushButtonDel.clicked.connect(self.delP)
        self.ui.pushButtonDel_2.clicked.connect(self.delI)

        self.ui.pushButton_9.clicked.connect(self.angle)
        self.ui.pushButton_10.clicked.connect(self.lenght)

        self.scene = QGraphicsScene()
        self.ui.graph.setScene(self.scene)
        self.scene.setSceneRect(0, 0, self.ui.graph.width(),
                                self.ui.graph.height())

        self.ui.graph.installEventFilter(self)
        self.grid(13)
        self.PointFlag = 0
        self.points = list()
        self.lines = list()
        self.InteFlag = 0
        self.delIflag = 0
        self.delPflag = 0
        self.Linepenpen = QPen(QColor('#000000'), 2)
        self.pointpen = QPen(QColor('#ff0000'), 2)
        self.Linepenpen.style = "DashLine"
        self.Linepenpen.cap = "RoundCap"

    def angle(self):
        self.createmodal('Угол')

    def lenght(self):
        self.createmodal('Длина')

    def createmodal(self, t):
        modalWindow = QWidget(window, Qt.Window)
        modalWindow.setWindowTitle(t)
        modalWindow.resize(250, 40)
        modalWindow.setWindowModality(Qt.WindowModal)
        modalWindow.setAttribute(Qt.WA_DeleteOnClose, True)
        modalWindow.move(window.geometry().center() -
                         modalWindow.rect().center() - QPoint(4, 30))
        modLab = QLabel(t)
        modBut = QPushButton('Применить')
        lineEdit = QLineEdit()
        hBox = QHBoxLayout()
        hBox.addWidget(modLab)
        hBox.addWidget(lineEdit)
        hBox.addWidget(modBut)
        modalWindow.setLayout(hBox)
        modBut.clicked.connect(modalWindow.close)
        modalWindow.show()

    def eventFilter(self, source, event):

        if (event.type() == QEvent.MouseButtonPress
                and source is self.ui.graph):
            if self.PointFlag == 1:

                pos = event.pos()
                print('add point: (%d, %d)' % (pos.x(), pos.y()))
                self.points.append(Point(pos.x(), pos.y()))
                self.PointFlag = 0
                self.painter()

            if self.delPflag == 1:
                pos = event.pos()
                poi = self.getpoint(event.pos())
                if poi != None:
                    allline = list()
                    for line in self.lines:
                        if line.P1 == poi or line.P2 == poi:
                            allline.append(line)
                    for line in allline:
                        self.lines.remove(line)
                    self.points.remove(poi)
                    self.delPflag = 0
                    self.painter()

            if self.delIflag == 1:
                pos = event.pos()
                lin = self.getline(event.pos())
                if lin != None:
                    self.lines.remove(lin)

                    self.delIflag = 0
                    self.painter()
            if self.InteFlag > 0:
                if self.InteFlag == 2:

                    lin = Line()
                    if self.getpoint(event.pos()) != None:

                        lin.setP1(self.getpoint(event.pos()))
                        self.lines.append(lin)
                    else:
                        self.InteFlag += 1
                else:
                    if self.getpoint(event.pos()) != None:
                        self.lines[-1].setP2(self.getpoint(event.pos()))
                        print('add line()', self.lines[-1].x1(),
                              self.lines[-1].y1(), self.lines[-1].x2(),
                              self.lines[-1].y2())
                        self.painter()
                    else:
                        self.InteFlag += 1
                self.InteFlag -= 1

        return QWidget.eventFilter(self, source, event)

    def painter(self):
        self.scene.clear()
        self.grid(13)
        for point in self.points:
            self.scene.addEllipse(point.X - 2.5, point.Y - 2.5, 5, 5,
                                  self.pointpen)
        for line in self.lines:
            self.scene.addLine(line.x1(), line.y1(), line.x2(), line.y2(),
                               self.Linepenpen)
        self.scene.update()

    def getpoint(self, a):
        x = a.x()
        y = a.y()
        tolerance = 10
        for point in self.points:
            if abs(point.getX() - x) < tolerance and abs(point.getY() -
                                                         y) < tolerance:
                return point
        return None

    def getline(self, a):
        x = a.x()
        y = a.y()
        tolerance = 5
        for line in self.lines:
            t = abs(y - (line.y1() +
                         ((line.y2() - line.y1()) * (x - line.x1()) /
                          (line.x2() - line.x1()))))
            print(t)
            if t < tolerance:
                return line
        return None

    def grid(self, dxy):
        pen = QPen()
        pen.setColor(QColor('#C0C0C0'))
        for i in range(0, int(self.ui.graph.height() / dxy) + 1):
            self.scene.addLine(0, dxy * i, self.ui.graph.width(), dxy * i, pen)
        for i in range(0, int(self.ui.graph.width() / dxy) + 1):
            self.scene.addLine(dxy * i, 0, dxy * i, self.ui.graph.height(),
                               pen)

    def delP(self):
        self.delPflag = 1

        self.delIflag = 0
        self.PointFlag = 0
        self.InteFlag = 0

    def delI(self):
        self.delIflag = 1

        self.delPflag = 0
        self.PointFlag = 0
        self.InteFlag = 0

    def createP(self):
        self.PointFlag = 1

        self.delPflag = 0
        self.delIflag = 0
        self.InteFlag = 0

    def createI(self):
        self.InteFlag = 2

        self.delPflag = 0
        self.delIflag = 0
        self.PointFlag = 0
Ejemplo n.º 32
0
class Screenshot(QGraphicsView):
    """ Main Class """

    screen_shot_grabed = pyqtSignal(QImage)
    widget_closed = pyqtSignal()

    def __init__(self, flags=constant.DEFAULT, parent=None):
        """
        flags: binary flags. see the flags in the constant.py
        """
        super().__init__(parent)

        # Init
        self.penColorNow = QColor(PENCOLOR)
        self.penSizeNow = PENSIZE
        self.fontNow = QFont('Sans')
        self.clipboard = QApplication.clipboard()

        self.drawListResult = [
        ]  # draw list that sure to be drew, [action, coord]
        self.drawListProcess = None  # the process to the result
        self.selectedArea = QRect(
        )  # a QRect instance which stands for the selected area
        self.selectedAreaRaw = QRect()
        self.mousePosition = MousePosition.OUTSIDE_AREA  # mouse position
        self.screenPixel = None
        self.textRect = None

        self.mousePressed = False
        self.action = ACTION_SELECT
        self.mousePoint = self.cursor().pos()

        self.startX, self.startY = 0, 0  # the point where you start
        self.endX, self.endY = 0, 0  # the point where you end
        self.pointPath = QPainterPath(
        )  # the point mouse passes, used by draw free line
        self.itemsToRemove = [
        ]  # the items that should not draw on screenshot picture
        self.textPosition = None

        # result
        self.target_img = None

        # Init window
        self.getscreenshot()
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)

        self.setMouseTracking(True)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setContentsMargins(0, 0, 0, 0)
        self.setStyleSheet("QGraphicsView { border-style: none; }")

        self.tooBar = MyToolBar(flags, self)
        self.tooBar.trigger.connect(self.changeAction)

        self.penSetBar = None
        if flags & constant.RECT or flags & constant.ELLIPSE or flags & constant.LINE or flags & constant.FREEPEN \
                or flags & constant.ARROW or flags & constant.TEXT:
            self.penSetBar = PenSetWidget(self)
            self.penSetBar.penSizeTrigger.connect(self.changePenSize)
            self.penSetBar.penColorTrigger.connect(self.changePenColor)
            self.penSetBar.fontChangeTrigger.connect(self.changeFont)

        self.textInput = TextInput(self)
        self.textInput.inputChanged.connect(self.textChange)
        self.textInput.cancelPressed.connect(self.cancelInput)
        self.textInput.okPressed.connect(self.okInput)

        self.graphicsScene = QGraphicsScene(0, 0, self.screenPixel.width(),
                                            self.screenPixel.height())

        self.show()
        self.setScene(self.graphicsScene)
        self.windowHandle().setScreen(QGuiApplication.screenAt(QCursor.pos()))
        self.scale = self.get_scale()
        # self.setFixedSize(self.screenPixel.width(), self.screenPixel.height())
        self.setGeometry(QGuiApplication.screenAt(QCursor.pos()).geometry())
        self.showFullScreen()
        self.redraw()

        QShortcut(QKeySequence('ctrl+s'),
                  self).activated.connect(self.saveScreenshot)
        QShortcut(QKeySequence('esc'), self).activated.connect(self.close)

    @staticmethod
    def take_screenshot(flags):
        loop = QEventLoop()
        screen_shot = Screenshot(flags)
        screen_shot.show()
        screen_shot.widget_closed.connect(loop.quit)

        loop.exec()
        img = screen_shot.target_img
        return img

    def getscreenshot(self):
        screen = QGuiApplication.screenAt(QCursor.pos())
        self.screenPixel = screen.grabWindow(0)

    def mousePressEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if event.button() != Qt.LeftButton:
            return

        if self.action is None:
            self.action = ACTION_SELECT

        self.startX, self.startY = event.x(), event.y()

        if self.action == ACTION_SELECT:
            if self.mousePosition == MousePosition.OUTSIDE_AREA:
                self.mousePressed = True
                self.selectedArea = QRect()
                self.selectedArea.setTopLeft(QPoint(event.x(), event.y()))
                self.selectedArea.setBottomRight(QPoint(event.x(), event.y()))
                self.redraw()
            elif self.mousePosition == MousePosition.INSIDE_AREA:
                self.mousePressed = True
            else:
                pass
        elif self.action == ACTION_MOVE_SELECTED:
            if self.mousePosition == MousePosition.OUTSIDE_AREA:
                self.action = ACTION_SELECT
                self.selectedArea = QRect()
                self.selectedArea.setTopLeft(QPoint(event.x(), event.y()))
                self.selectedArea.setBottomRight(QPoint(event.x(), event.y()))
                self.redraw()
            self.mousePressed = True
        elif self.action in DRAW_ACTION:
            self.mousePressed = True
            if self.action == ACTION_FREEPEN:
                self.pointPath = QPainterPath()
                self.pointPath.moveTo(QPoint(event.x(), event.y()))
            elif self.action == ACTION_TEXT:
                if self.textPosition is None:
                    self.textPosition = QPoint(event.x(), event.y())
                    self.textRect = None
                    self.redraw()

    def mouseMoveEvent(self, event: QMouseEvent):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.mousePoint = QPoint(event.globalPos().x(), event.globalPos().y())

        if self.action is None:
            self.action = ACTION_SELECT

        if not self.mousePressed:
            point = QPoint(event.x(), event.y())
            self.detectMousePosition(point)
            self.setCursorStyle()
            self.redraw()
        else:
            self.endX, self.endY = event.x(), event.y()

            # if self.mousePosition != OUTSIDE_AREA:
            #    self.action = ACTION_MOVE_SELECTED

            if self.action == ACTION_SELECT:
                self.selectedArea.setBottomRight(QPoint(event.x(), event.y()))
                self.redraw()
            elif self.action == ACTION_MOVE_SELECTED:
                self.selectedArea = QRect(self.selectedAreaRaw)

                if self.mousePosition == MousePosition.INSIDE_AREA:
                    moveToX = event.x() - self.startX + self.selectedArea.left(
                    )
                    moveToY = event.y() - self.startY + self.selectedArea.top()
                    if 0 <= moveToX <= self.screenPixel.width(
                    ) - 1 - self.selectedArea.width():
                        self.selectedArea.moveLeft(moveToX)
                    if 0 <= moveToY <= self.screenPixel.height(
                    ) - 1 - self.selectedArea.height():
                        self.selectedArea.moveTop(moveToY)
                    self.selectedArea = self.selectedArea.normalized()
                    self.selectedAreaRaw = QRect(self.selectedArea)
                    self.startX, self.startY = event.x(), event.y()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_LEFT_SIDE:
                    moveToX = event.x() - self.startX + self.selectedArea.left(
                    )
                    if moveToX <= self.selectedArea.right():
                        self.selectedArea.setLeft(moveToX)
                        self.selectedArea = self.selectedArea.normalized()
                        self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_RIGHT_SIDE:
                    moveToX = event.x(
                    ) - self.startX + self.selectedArea.right()
                    self.selectedArea.setRight(moveToX)
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_UP_SIDE:
                    moveToY = event.y() - self.startY + self.selectedArea.top()
                    self.selectedArea.setTop(moveToY)
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_DOWN_SIDE:
                    moveToY = event.y(
                    ) - self.startY + self.selectedArea.bottom()
                    self.selectedArea.setBottom(moveToY)
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_TOP_LEFT_CORNER:
                    moveToX = event.x() - self.startX + self.selectedArea.left(
                    )
                    moveToY = event.y() - self.startY + self.selectedArea.top()
                    self.selectedArea.setTopLeft(QPoint(moveToX, moveToY))
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_BOTTOM_RIGHT_CORNER:
                    moveToX = event.x(
                    ) - self.startX + self.selectedArea.right()
                    moveToY = event.y(
                    ) - self.startY + self.selectedArea.bottom()
                    self.selectedArea.setBottomRight(QPoint(moveToX, moveToY))
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_TOP_RIGHT_CORNER:
                    moveToX = event.x(
                    ) - self.startX + self.selectedArea.right()
                    moveToY = event.y() - self.startY + self.selectedArea.top()
                    self.selectedArea.setTopRight(QPoint(moveToX, moveToY))
                    self.selectedArea = self.selectedArea.normalized()
                    self.redraw()
                elif self.mousePosition == MousePosition.ON_THE_BOTTOM_LEFT_CORNER:
                    moveToX = event.x() - self.startX + self.selectedArea.left(
                    )
                    moveToY = event.y(
                    ) - self.startY + self.selectedArea.bottom()
                    self.selectedArea.setBottomLeft(QPoint(moveToX, moveToY))
                    self.redraw()
                else:
                    pass
            elif self.action == ACTION_RECT:
                self.drawRect(self.startX, self.startY, event.x(), event.y(),
                              False)
                self.redraw()
                pass
            elif self.action == ACTION_ELLIPSE:
                self.drawEllipse(self.startX, self.startY, event.x(),
                                 event.y(), False)
                self.redraw()
            elif self.action == ACTION_ARROW:
                self.drawArrow(self.startX, self.startY, event.x(), event.y(),
                               False)
                self.redraw()
            elif self.action == ACTION_LINE:
                self.drawLine(self.startX, self.startY, event.x(), event.y(),
                              False)
                self.redraw()
            elif self.action == ACTION_FREEPEN:
                y1, y2 = event.x(), event.y()
                rect = self.selectedArea.normalized()
                if y1 <= rect.left():
                    y1 = rect.left()
                elif y1 >= rect.right():
                    y1 = rect.right()

                if y2 <= rect.top():
                    y2 = rect.top()
                elif y2 >= rect.bottom():
                    y2 = rect.bottom()

                self.pointPath.lineTo(y1, y2)
                self.drawFreeLine(self.pointPath, False)
                self.redraw()

    def mouseReleaseEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if event.button() != Qt.LeftButton:
            return

        if self.mousePressed:
            self.mousePressed = False
            self.endX, self.endY = event.x(), event.y()

            if self.action == ACTION_SELECT:
                self.selectedArea.setBottomRight(QPoint(event.x(), event.y()))
                self.selectedAreaRaw = QRect(self.selectedArea)
                self.action = ACTION_MOVE_SELECTED
                self.redraw()
            elif self.action == ACTION_MOVE_SELECTED:
                self.selectedAreaRaw = QRect(self.selectedArea)
                self.redraw()
                # self.action = None
            elif self.action == ACTION_RECT:
                self.drawRect(self.startX, self.startY, event.x(), event.y(),
                              True)
                self.redraw()
            elif self.action == ACTION_ELLIPSE:
                self.drawEllipse(self.startX, self.startY, event.x(),
                                 event.y(), True)
                self.redraw()
            elif self.action == ACTION_ARROW:
                self.drawArrow(self.startX, self.startY, event.x(), event.y(),
                               True)
                self.redraw()
            elif self.action == ACTION_LINE:
                self.drawLine(self.startX, self.startY, event.x(), event.y(),
                              True)
                self.redraw()
            elif self.action == ACTION_FREEPEN:
                self.drawFreeLine(self.pointPath, True)
                self.redraw()

    def detectMousePosition(self, point):
        """
        :type point: QPoint
        :param point: the mouse position you want to check
        :return:
        """
        if self.selectedArea == QRect():
            self.mousePosition = MousePosition.OUTSIDE_AREA
            return

        if self.selectedArea.left() - ERRORRANGE <= point.x(
        ) <= self.selectedArea.left() and (self.selectedArea.top() - ERRORRANGE
                                           <= point.y() <=
                                           self.selectedArea.top()):
            self.mousePosition = MousePosition.ON_THE_TOP_LEFT_CORNER
        elif self.selectedArea.right() <= point.x() <= self.selectedArea.right(
        ) + ERRORRANGE and (self.selectedArea.top() - ERRORRANGE <= point.y()
                            <= self.selectedArea.top()):
            self.mousePosition = MousePosition.ON_THE_TOP_RIGHT_CORNER
        elif self.selectedArea.left() - ERRORRANGE <= point.x(
        ) <= self.selectedArea.left() and (
                self.selectedArea.bottom() <= point.y() <=
                self.selectedArea.bottom() + ERRORRANGE):
            self.mousePosition = MousePosition.ON_THE_BOTTOM_LEFT_CORNER
        elif self.selectedArea.right() <= point.x() <= self.selectedArea.right(
        ) + ERRORRANGE and (self.selectedArea.bottom() <= point.y() <=
                            self.selectedArea.bottom() + ERRORRANGE):
            self.mousePosition = MousePosition.ON_THE_BOTTOM_RIGHT_CORNER
        elif -ERRORRANGE <= point.x() - self.selectedArea.left() <= 0 and (
                self.selectedArea.topLeft().y() < point.y() <
                self.selectedArea.bottomLeft().y()):
            self.mousePosition = MousePosition.ON_THE_LEFT_SIDE
        elif 0 <= point.x() - self.selectedArea.right() <= ERRORRANGE and (
                self.selectedArea.topRight().y() < point.y() <
                self.selectedArea.bottomRight().y()):
            self.mousePosition = MousePosition.ON_THE_RIGHT_SIDE
        elif -ERRORRANGE <= point.y() - self.selectedArea.top() <= 0 and (
                self.selectedArea.topLeft().x() < point.x() <
                self.selectedArea.topRight().x()):
            self.mousePosition = MousePosition.ON_THE_UP_SIDE
        elif 0 <= point.y() - self.selectedArea.bottom() <= ERRORRANGE and (
                self.selectedArea.bottomLeft().x() < point.x() <
                self.selectedArea.bottomRight().x()):
            self.mousePosition = MousePosition.ON_THE_DOWN_SIDE
        elif not self.selectedArea.contains(point):
            self.mousePosition = MousePosition.OUTSIDE_AREA
        else:
            self.mousePosition = MousePosition.INSIDE_AREA

    def setCursorStyle(self):
        if self.action in DRAW_ACTION:
            self.setCursor(Qt.CrossCursor)
            return

        if self.mousePosition == MousePosition.ON_THE_LEFT_SIDE or \
                        self.mousePosition == MousePosition.ON_THE_RIGHT_SIDE:

            self.setCursor(Qt.SizeHorCursor)
        elif self.mousePosition == MousePosition.ON_THE_UP_SIDE or \
                        self.mousePosition == MousePosition.ON_THE_DOWN_SIDE:

            self.setCursor(Qt.SizeVerCursor)
        elif self.mousePosition == MousePosition.ON_THE_TOP_LEFT_CORNER or \
                        self.mousePosition == MousePosition.ON_THE_BOTTOM_RIGHT_CORNER:

            self.setCursor(Qt.SizeFDiagCursor)
        elif self.mousePosition == MousePosition.ON_THE_TOP_RIGHT_CORNER or \
                        self.mousePosition == MousePosition.ON_THE_BOTTOM_LEFT_CORNER:

            self.setCursor(Qt.SizeBDiagCursor)
        elif self.mousePosition == MousePosition.OUTSIDE_AREA:
            self.setCursor(Qt.ArrowCursor)
        elif self.mousePosition == MousePosition.INSIDE_AREA:
            self.setCursor(Qt.OpenHandCursor)
        else:
            self.setCursor(Qt.ArrowCursor)
            pass

    def drawMagnifier(self):
        # First, calculate the magnifier position due to the mouse position
        watchAreaWidth = 16
        watchAreaHeight = 16
        watchAreaPixmap = QPixmap()

        cursor_pos = self.mousePoint

        watchArea = QRect(
            QPoint(cursor_pos.x() - watchAreaWidth / 2,
                   cursor_pos.y() - watchAreaHeight / 2),
            QPoint(cursor_pos.x() + watchAreaWidth / 2,
                   cursor_pos.y() + watchAreaHeight / 2))
        if watchArea.left() < 0:
            watchArea.moveLeft(0)
            watchArea.moveRight(watchAreaWidth)
        if self.mousePoint.x() + watchAreaWidth / 2 >= self.screenPixel.width(
        ):
            watchArea.moveRight(self.screenPixel.width() - 1)
            watchArea.moveLeft(watchArea.right() - watchAreaWidth)
        if self.mousePoint.y() - watchAreaHeight / 2 < 0:
            watchArea.moveTop(0)
            watchArea.moveBottom(watchAreaHeight)
        if self.mousePoint.y(
        ) + watchAreaHeight / 2 >= self.screenPixel.height():
            watchArea.moveBottom(self.screenPixel.height() - 1)
            watchArea.moveTop(watchArea.bottom() - watchAreaHeight)

        # tricks to solve the hidpi impact on QCursor.pos()
        watchArea.setTopLeft(
            QPoint(watchArea.topLeft().x() * self.scale,
                   watchArea.topLeft().y() * self.scale))
        watchArea.setBottomRight(
            QPoint(watchArea.bottomRight().x() * self.scale,
                   watchArea.bottomRight().y() * self.scale))
        watchAreaPixmap = self.screenPixel.copy(watchArea)

        # second, calculate the magnifier area
        magnifierAreaWidth = watchAreaWidth * 10
        magnifierAreaHeight = watchAreaHeight * 10
        fontAreaHeight = 40

        cursorSize = 24
        magnifierArea = QRectF(
            QPoint(QCursor.pos().x() + cursorSize,
                   QCursor.pos().y() + cursorSize),
            QPoint(QCursor.pos().x() + cursorSize + magnifierAreaWidth,
                   QCursor.pos().y() + cursorSize + magnifierAreaHeight))
        if magnifierArea.right() >= self.screenPixel.width():
            magnifierArea.moveLeft(QCursor.pos().x() - magnifierAreaWidth -
                                   cursorSize / 2)
        if magnifierArea.bottom() + fontAreaHeight >= self.screenPixel.height(
        ):
            magnifierArea.moveTop(QCursor.pos().y() - magnifierAreaHeight -
                                  cursorSize / 2 - fontAreaHeight)

        # third, draw the watch area to magnifier area
        watchAreaScaled = watchAreaPixmap.scaled(
            QSize(magnifierAreaWidth * self.scale,
                  magnifierAreaHeight * self.scale))
        magnifierPixmap = self.graphicsScene.addPixmap(watchAreaScaled)
        magnifierPixmap.setOffset(magnifierArea.topLeft())

        # then draw lines and text
        self.graphicsScene.addRect(QRectF(magnifierArea),
                                   QPen(QColor(255, 255, 255), 2))
        self.graphicsScene.addLine(
            QLineF(QPointF(magnifierArea.center().x(), magnifierArea.top()),
                   QPointF(magnifierArea.center().x(),
                           magnifierArea.bottom())),
            QPen(QColor(0, 255, 255), 2))
        self.graphicsScene.addLine(
            QLineF(QPointF(magnifierArea.left(),
                           magnifierArea.center().y()),
                   QPointF(magnifierArea.right(),
                           magnifierArea.center().y())),
            QPen(QColor(0, 255, 255), 2))

        # get the rgb of mouse point
        pointRgb = QColor(self.screenPixel.toImage().pixel(self.mousePoint))

        # draw information
        self.graphicsScene.addRect(
            QRectF(
                magnifierArea.bottomLeft(),
                magnifierArea.bottomRight() + QPoint(0, fontAreaHeight + 30)),
            Qt.black, QBrush(Qt.black))
        rgbInfo = self.graphicsScene.addSimpleText(
            ' Rgb: ({0}, {1}, {2})'.format(pointRgb.red(), pointRgb.green(),
                                           pointRgb.blue()))
        rgbInfo.setPos(magnifierArea.bottomLeft() + QPoint(0, 5))
        rgbInfo.setPen(QPen(QColor(255, 255, 255), 2))

        rect = self.selectedArea.normalized()
        sizeInfo = self.graphicsScene.addSimpleText(' Size: {0} x {1}'.format(
            rect.width() * self.scale,
            rect.height() * self.scale))
        sizeInfo.setPos(magnifierArea.bottomLeft() + QPoint(0, 15) +
                        QPoint(0, fontAreaHeight / 2))
        sizeInfo.setPen(QPen(QColor(255, 255, 255), 2))

    def get_scale(self):
        return self.devicePixelRatio()

    def saveScreenshot(self,
                       clipboard=False,
                       fileName='screenshot.png',
                       picType='png'):
        fullWindow = QRect(0, 0, self.width() - 1, self.height() - 1)
        selected = QRect(self.selectedArea)
        if selected.left() < 0:
            selected.setLeft(0)
        if selected.right() >= self.width():
            selected.setRight(self.width() - 1)
        if selected.top() < 0:
            selected.setTop(0)
        if selected.bottom() >= self.height():
            selected.setBottom(self.height() - 1)

        source = (fullWindow & selected)
        source.setTopLeft(
            QPoint(source.topLeft().x() * self.scale,
                   source.topLeft().y() * self.scale))
        source.setBottomRight(
            QPoint(source.bottomRight().x() * self.scale,
                   source.bottomRight().y() * self.scale))
        image = self.screenPixel.copy(source)
        image.setDevicePixelRatio(1)

        if clipboard:
            QGuiApplication.clipboard().setImage(QImage(image),
                                                 QClipboard.Clipboard)
        else:
            image.save(fileName, picType, 10)
        self.target_img = image
        self.screen_shot_grabed.emit(QImage(image))

    def redraw(self):
        self.graphicsScene.clear()

        # draw screenshot
        self.graphicsScene.addPixmap(self.screenPixel)

        # prepare for drawing selected area
        rect = QRectF(self.selectedArea)
        rect = rect.normalized()

        topLeftPoint = rect.topLeft()
        topRightPoint = rect.topRight()
        bottomLeftPoint = rect.bottomLeft()
        bottomRightPoint = rect.bottomRight()
        topMiddlePoint = (topLeftPoint + topRightPoint) / 2
        leftMiddlePoint = (topLeftPoint + bottomLeftPoint) / 2
        bottomMiddlePoint = (bottomLeftPoint + bottomRightPoint) / 2
        rightMiddlePoint = (topRightPoint + bottomRightPoint) / 2

        # draw the picture mask
        mask = QColor(0, 0, 0, 155)

        if self.selectedArea == QRect():
            self.graphicsScene.addRect(0, 0, self.screenPixel.width(),
                                       self.screenPixel.height(),
                                       QPen(Qt.NoPen), mask)
        else:
            self.graphicsScene.addRect(0, 0, self.screenPixel.width(),
                                       topRightPoint.y(), QPen(Qt.NoPen), mask)
            self.graphicsScene.addRect(0, topLeftPoint.y(), topLeftPoint.x(),
                                       rect.height(), QPen(Qt.NoPen), mask)
            self.graphicsScene.addRect(
                topRightPoint.x(), topRightPoint.y(),
                self.screenPixel.width() - topRightPoint.x(), rect.height(),
                QPen(Qt.NoPen), mask)
            self.graphicsScene.addRect(
                0, bottomLeftPoint.y(), self.screenPixel.width(),
                self.screenPixel.height() - bottomLeftPoint.y(),
                QPen(Qt.NoPen), mask)

        # draw the toolBar
        if self.action != ACTION_SELECT:
            spacing = 5
            # show the toolbar first, then move it to the correct position
            # because the width of it may be wrong if this is the first time it shows
            self.tooBar.show()

            dest = QPointF(rect.bottomRight() -
                           QPointF(self.tooBar.width(), 0) -
                           QPointF(spacing, -spacing))
            if dest.x() < spacing:
                dest.setX(spacing)
            pen_set_bar_height = self.penSetBar.height(
            ) if self.penSetBar is not None else 0
            if dest.y() + self.tooBar.height(
            ) + pen_set_bar_height >= self.height():
                if rect.top() - self.tooBar.height(
                ) - pen_set_bar_height < spacing:
                    dest.setY(rect.top() + spacing)
                else:
                    dest.setY(rect.top() - self.tooBar.height() -
                              pen_set_bar_height - spacing)

            self.tooBar.move(dest.toPoint())

            if self.penSetBar is not None:
                self.penSetBar.show()
                self.penSetBar.move(dest.toPoint() +
                                    QPoint(0,
                                           self.tooBar.height() + spacing))

                if self.action == ACTION_TEXT:
                    self.penSetBar.showFontWidget()
                else:
                    self.penSetBar.showPenWidget()
        else:
            self.tooBar.hide()

            if self.penSetBar is not None:
                self.penSetBar.hide()

        # draw the list
        for step in self.drawListResult:
            self.drawOneStep(step)

        if self.drawListProcess is not None:
            self.drawOneStep(self.drawListProcess)
            if self.action != ACTION_TEXT:
                self.drawListProcess = None

        if self.selectedArea != QRect():
            self.itemsToRemove = []

            # draw the selected rectangle
            pen = QPen(QColor(0, 255, 255), 2)
            self.itemsToRemove.append(self.graphicsScene.addRect(rect, pen))

            # draw the drag point
            radius = QPoint(3, 3)
            brush = QBrush(QColor(0, 255, 255))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(topLeftPoint - radius, topLeftPoint + radius), pen,
                    brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(topMiddlePoint - radius, topMiddlePoint + radius),
                    pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(topRightPoint - radius, topRightPoint + radius),
                    pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(leftMiddlePoint - radius, leftMiddlePoint + radius),
                    pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(rightMiddlePoint - radius,
                           rightMiddlePoint + radius), pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(bottomLeftPoint - radius, bottomLeftPoint + radius),
                    pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(bottomMiddlePoint - radius,
                           bottomMiddlePoint + radius), pen, brush))
            self.itemsToRemove.append(
                self.graphicsScene.addEllipse(
                    QRectF(bottomRightPoint - radius,
                           bottomRightPoint + radius), pen, brush))

        # draw the textedit
        if self.textPosition is not None:
            textSpacing = 50
            position = QPoint()
            if self.textPosition.x() + self.textInput.width(
            ) >= self.screenPixel.width():
                position.setX(self.textPosition.x() - self.textInput.width())
            else:
                position.setX(self.textPosition.x())

            if self.textRect is not None:
                if self.textPosition.y() + self.textInput.height(
                ) + self.textRect.height() >= self.screenPixel.height():
                    position.setY(self.textPosition.y() -
                                  self.textInput.height() -
                                  self.textRect.height())
                else:
                    position.setY(self.textPosition.y() +
                                  self.textRect.height())
            else:
                if self.textPosition.y() + self.textInput.height(
                ) >= self.screenPixel.height():
                    position.setY(self.textPosition.y() -
                                  self.textInput.height())
                else:
                    position.setY(self.textPosition.y())

            self.textInput.move(position)
            self.textInput.show()
            # self.textInput.getFocus()

        # draw the magnifier
        if self.action == ACTION_SELECT:
            self.drawMagnifier()
            if self.mousePressed:
                self.drawSizeInfo()

        if self.action == ACTION_MOVE_SELECTED:
            self.drawSizeInfo()

    # deal with every step in drawList
    def drawOneStep(self, step):
        """
        :type step: tuple
        """
        if step[0] == ACTION_RECT:
            self.graphicsScene.addRect(
                QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])),
                step[5])
        elif step[0] == ACTION_ELLIPSE:
            self.graphicsScene.addEllipse(
                QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])),
                step[5])
        elif step[0] == ACTION_ARROW:
            arrow = QPolygonF()

            linex = float(step[1] - step[3])
            liney = float(step[2] - step[4])
            line = sqrt(pow(linex, 2) + pow(liney, 2))

            # in case to divided by 0
            if line == 0:
                return

            sinAngel = liney / line
            cosAngel = linex / line

            # sideLength is the length of bottom side of the body of an arrow
            # arrowSize is the size of the head of an arrow, left and right
            # sides' size is arrowSize, and the bottom side's size is arrowSize / 2
            sideLength = step[5].width()
            arrowSize = 8
            bottomSize = arrowSize / 2

            tmpPoint = QPointF(step[3] + arrowSize * sideLength * cosAngel,
                               step[4] + arrowSize * sideLength * sinAngel)

            point1 = QPointF(step[1] + sideLength * sinAngel,
                             step[2] - sideLength * cosAngel)
            point2 = QPointF(step[1] - sideLength * sinAngel,
                             step[2] + sideLength * cosAngel)
            point3 = QPointF(tmpPoint.x() - sideLength * sinAngel,
                             tmpPoint.y() + sideLength * cosAngel)
            point4 = QPointF(tmpPoint.x() - bottomSize * sideLength * sinAngel,
                             tmpPoint.y() + bottomSize * sideLength * cosAngel)
            point5 = QPointF(step[3], step[4])
            point6 = QPointF(tmpPoint.x() + bottomSize * sideLength * sinAngel,
                             tmpPoint.y() - bottomSize * sideLength * cosAngel)
            point7 = QPointF(tmpPoint.x() + sideLength * sinAngel,
                             tmpPoint.y() - sideLength * cosAngel)

            arrow.append(point1)
            arrow.append(point2)
            arrow.append(point3)
            arrow.append(point4)
            arrow.append(point5)
            arrow.append(point6)
            arrow.append(point7)
            arrow.append(point1)

            self.graphicsScene.addPolygon(arrow, step[5], step[6])
        elif step[0] == ACTION_LINE:
            self.graphicsScene.addLine(
                QLineF(QPointF(step[1], step[2]), QPointF(step[3], step[4])),
                step[5])
        elif step[0] == ACTION_FREEPEN:
            self.graphicsScene.addPath(step[1], step[2])
        elif step[0] == ACTION_TEXT:
            textAdd = self.graphicsScene.addSimpleText(step[1], step[2])
            textAdd.setPos(step[3])
            textAdd.setBrush(QBrush(step[4]))
            self.textRect = textAdd.boundingRect()

    # draw the size information on the top left corner
    def drawSizeInfo(self):
        sizeInfoAreaWidth = 200
        sizeInfoAreaHeight = 30
        spacing = 5
        rect = self.selectedArea.normalized()
        sizeInfoArea = QRect(rect.left(),
                             rect.top() - spacing - sizeInfoAreaHeight,
                             sizeInfoAreaWidth, sizeInfoAreaHeight)

        if sizeInfoArea.top() < 0:
            sizeInfoArea.moveTopLeft(rect.topLeft() + QPoint(spacing, spacing))
        if sizeInfoArea.right() >= self.screenPixel.width():
            sizeInfoArea.moveTopLeft(rect.topLeft() -
                                     QPoint(spacing, spacing) -
                                     QPoint(sizeInfoAreaWidth, 0))
        if sizeInfoArea.left() < spacing:
            sizeInfoArea.moveLeft(spacing)
        if sizeInfoArea.top() < spacing:
            sizeInfoArea.moveTop(spacing)

        self.itemsToRemove.append(
            self.graphicsScene.addRect(QRectF(sizeInfoArea), Qt.white,
                                       QBrush(Qt.black)))

        sizeInfo = self.graphicsScene.addSimpleText('  {0} x {1}'.format(
            rect.width() * self.scale,
            rect.height() * self.scale))
        sizeInfo.setPos(sizeInfoArea.topLeft() + QPoint(0, 2))
        sizeInfo.setPen(QPen(QColor(255, 255, 255), 2))
        self.itemsToRemove.append(sizeInfo)

    def drawRect(self, x1, x2, y1, y2, result):
        rect = self.selectedArea.normalized()
        tmpRect = QRect(QPoint(x1, x2), QPoint(y1, y2)).normalized()
        resultRect = rect & tmpRect
        tmp = [
            ACTION_RECT,
            resultRect.topLeft().x(),
            resultRect.topLeft().y(),
            resultRect.bottomRight().x(),
            resultRect.bottomRight().y(),
            QPen(QColor(self.penColorNow), int(self.penSizeNow))
        ]
        if result:
            self.drawListResult.append(tmp)
        else:
            self.drawListProcess = tmp

    def drawEllipse(self, x1, x2, y1, y2, result):
        rect = self.selectedArea.normalized()
        tmpRect = QRect(QPoint(x1, x2), QPoint(y1, y2)).normalized()
        resultRect = rect & tmpRect
        tmp = [
            ACTION_ELLIPSE,
            resultRect.topLeft().x(),
            resultRect.topLeft().y(),
            resultRect.bottomRight().x(),
            resultRect.bottomRight().y(),
            QPen(QColor(self.penColorNow), int(self.penSizeNow))
        ]
        if result:
            self.drawListResult.append(tmp)
        else:
            self.drawListProcess = tmp

    def drawArrow(self, x1, x2, y1, y2, result):
        rect = self.selectedArea.normalized()
        if y1 <= rect.left():
            y1 = rect.left()
        elif y1 >= rect.right():
            y1 = rect.right()

        if y2 <= rect.top():
            y2 = rect.top()
        elif y2 >= rect.bottom():
            y2 = rect.bottom()

        tmp = [
            ACTION_ARROW, x1, x2, y1, y2,
            QPen(QColor(self.penColorNow), int(self.penSizeNow)),
            QBrush(QColor(self.penColorNow))
        ]
        if result:
            self.drawListResult.append(tmp)
        else:
            self.drawListProcess = tmp

    def drawLine(self, x1, x2, y1, y2, result):
        rect = self.selectedArea.normalized()
        if y1 <= rect.left():
            y1 = rect.left()
        elif y1 >= rect.right():
            y1 = rect.right()

        if y2 <= rect.top():
            y2 = rect.top()
        elif y2 >= rect.bottom():
            y2 = rect.bottom()

        tmp = [
            ACTION_LINE, x1, x2, y1, y2,
            QPen(QColor(self.penColorNow), int(self.penSizeNow))
        ]
        if result:
            self.drawListResult.append(tmp)
        else:
            self.drawListProcess = tmp

    def drawFreeLine(self, pointPath, result):
        tmp = [
            ACTION_FREEPEN,
            QPainterPath(pointPath),
            QPen(QColor(self.penColorNow), int(self.penSizeNow))
        ]
        if result:
            self.drawListResult.append(tmp)
        else:
            self.drawListProcess = tmp

    def textChange(self):
        if self.textPosition is None:
            return
        self.text = self.textInput.getText()
        self.drawListProcess = [
            ACTION_TEXT,
            str(self.text),
            QFont(self.fontNow),
            QPoint(self.textPosition),
            QColor(self.penColorNow)
        ]
        self.redraw()

    def undoOperation(self):
        if len(self.drawListResult) == 0:
            self.action = ACTION_SELECT
            self.selectedArea = QRect()
            self.selectedAreaRaw = QRect()
            self.tooBar.hide()
            if self.penSetBar is not None:
                self.penSetBar.hide()
        else:
            self.drawListResult.pop()
        self.redraw()

    def saveOperation(self):
        filename = QFileDialog.getSaveFileName(self, 'Save file',
                                               './screenshot.png',
                                               '*.png;;*.jpg')
        if len(filename[0]) == 0:
            return
        else:
            self.saveScreenshot(False, filename[0], filename[1][2:])
            self.close()

    def close(self):
        self.widget_closed.emit()
        super().close()
        self.tooBar.close()
        if self.penSetBar is not None:
            self.penSetBar.close()

    def saveToClipboard(self):
        QApplication.clipboard().setText('Test in save function')

        self.saveScreenshot(True)
        self.close()

    # slots
    def changeAction(self, nextAction):
        QApplication.clipboard().setText('Test in changeAction function')

        if nextAction == ACTION_UNDO:
            self.undoOperation()
        elif nextAction == ACTION_SAVE:
            self.saveOperation()
        elif nextAction == ACTION_CANCEL:
            self.close()
        elif nextAction == ACTION_SURE:
            self.saveToClipboard()

        else:
            self.action = nextAction

        self.setFocus()

    def changePenSize(self, nextPenSize):
        self.penSizeNow = nextPenSize

    def changePenColor(self, nextPenColor):
        self.penColorNow = nextPenColor

    def cancelInput(self):
        self.drawListProcess = None
        self.textPosition = None
        self.textRect = None
        self.textInput.hide()
        self.textInput.clearText()
        self.redraw()

    def okInput(self):
        self.text = self.textInput.getText()
        self.drawListResult.append([
            ACTION_TEXT,
            str(self.text),
            QFont(self.fontNow),
            QPoint(self.textPosition),
            QColor(self.penColorNow)
        ])
        self.textPosition = None
        self.textRect = None
        self.textInput.hide()
        self.textInput.clearText()
        self.redraw()

    def changeFont(self, font):
        self.fontNow = font
Ejemplo n.º 33
0
class InitialPoseDialog(QDialog, Ui_PoseDialog):
    data_manager = None
    image = None
    y_line = 0
    y_top_line = 0
    y_lower_line = 0
    landmark_size = 2
    lines = None
    middle_idx = 0
    pose_model = None

    def __init__(self, data_manager):
        super(InitialPoseDialog, self).__init__()
        self.setupUi(self)
        self.setAttribute(Qt.WA_DeleteOnClose)

        assert isinstance(data_manager, DataManager)
        self.data_manager = data_manager
        self.pose_model = InitialPoseModel(data_manager)

        self.scene = QGraphicsScene()
        self.graphicsView.setScene(self.scene)

        self.image = Filter.crop_image(self.data_manager.radiographs[0].image)

        self.findButton.clicked.connect(self.find_jaw_divider)
        self.openButton.clicked.connect(self._open_radiograph)

        self._redraw()

    def find_jaw_divider(self):
        self.y_top_line, self.y_lower_line = self.pose_model._find_jaw_separation_line(self.pose_model._crop_image_sides(self.image))

        upper_jaw_image = self.pose_model.crop_upper_jaw(self.image, self.y_top_line)
        lower_jaw_image = self.pose_model.crop_lower_jaw(self.image, self.y_lower_line)

        # Filter the image
        upper_jaw_image = Filter.process_image(upper_jaw_image, median_kernel=5, bilateral_kernel=17, bilateral_color=6)
        lower_jaw_image = Filter.process_image(lower_jaw_image, median_kernel=5, bilateral_kernel=17, bilateral_color=6)

        upper_jaw_image = self.pose_model._convert_to_binary_image(upper_jaw_image)
        lower_jaw_image = self.pose_model._convert_to_binary_image(lower_jaw_image)

        upper_lines = self.pose_model._find_hough_lines(upper_jaw_image, threshold=15)
        lower_lines = self.pose_model._find_hough_lines(lower_jaw_image, threshold=15)

        # Filter out lines
        upper_lines = self.pose_model._filter_lines(upper_lines, upper_jaw_image.shape, line_offset=6, max_line_gap=90)
        lower_lines = self.pose_model._filter_lines(lower_lines, lower_jaw_image.shape, line_offset=2, max_line_gap=60)

        self.image = lower_jaw_image
        self.lines = lower_lines
        self._redraw()

    def _open_radiograph(self):
        file_dialog = QFileDialog(self)
        file_dialog.setDirectory("./data/Radiographs")
        file_dialog.setFileMode(QFileDialog.ExistingFile)
        file_dialog.setNameFilter("Radiograph (*.tif)")
        if file_dialog.exec_() and len(file_dialog.selectedFiles()) == 1:
            radiograph = Radiograph()
            radiograph.path_to_img = file_dialog.selectedFiles()[0]
            #self.image = radiograph.image
            #crop_translation = -Filter.get_cropping_region(radiograph.image).left_top
            self.image = Filter.crop_image(radiograph.image)
            self.lines = None
            self._redraw()

    def _redraw(self, normalize=False):
        self.scene.clear()

        img = self.image.copy()

        if normalize:
            img = (img / img.max()) * 255

        # Draw image
        qimg = toQImage(img.astype(np.uint8))
        self.scene.addPixmap(QPixmap.fromImage(qimg))

        # Add jaws divider
        self.scene.addLine(QLineF(0, self.y_line, self.image.shape[1], self.y_line), pen=QPen(QColor.fromRgb(255, 0, 0)))
        self.scene.addLine(QLineF(0, self.y_top_line, self.image.shape[1], self.y_top_line), pen=QPen(QColor.fromRgb(255, 0, 0)))
        self.scene.addLine(QLineF(0, self.y_lower_line, self.image.shape[1], self.y_lower_line), pen=QPen(QColor.fromRgb(255, 0, 0)))


        # Add image center
        self.scene.addEllipse(self.image.shape[0]/2 - self.landmark_size, self.image.shape[1]/2 - self.landmark_size,
                             self.landmark_size * 2, self.landmark_size * 2,
                             pen=QPen(QColor.fromRgb(255, 0, 0)), brush=QBrush(QColor.fromRgb(255, 0, 0)))

        # Draw Hough lines
        if self.lines is not None:
            #for x1,y1,x2,y2 in self.lines[0]:
            for i, line_param in enumerate(self.lines):
                    rho,theta = line_param
                    a = np.cos(theta)
                    b = np.sin(theta)
                    x0 = a*rho
                    y0 = b*rho
                    x1 = int(x0 + 200*(-b))
                    y1 = int(y0 + 200*(a))
                    x2 = int(x0 - 200*(-b))
                    y2 = int(y0 - 200*(a))
                    self.scene.addLine(QLineF(x1, y1, x2, y2), pen=QPen(QColor.fromRgb(0, 255, 0)))