コード例 #1
0
class MainScreen(QMainWindow):
    def __init__(self):

        super().__init__()
        #self.setupUi(self)

        # Graphic Screen set
        self.img = QGraphicsPixmapItem(QPixmap('KarlaOnMyShoulder.jpg'))
        self.scene = QGraphicsScene()
        self.graphicsView = QGraphicsView()
        self.scene.addItem(self.img)
        self.graphicsView.setScene(self.scene)

        # Full Screen set size
        _WIDTH_ADD = 25
        _HEIGHT_ADD = 25
        self.setGeometry(0, 0, 640 + _WIDTH_ADD, 500 + _HEIGHT_ADD)

        self.graphicsView.viewport().installEventFilter(self)

        self.current_item = None
        self.start_pos = QPointF()
        self.end_pos = QPointF()
        self.show()

    def eventFilter(self, o, e):
        if self.graphicsView.viewport() is o:
            if e.type() == QEvent.MouseButtonPress:
                if e.buttons() & Qt.LeftButton:
                    print("press")
                    self.start_pos = self.end_pos = self.graphicsView.mapToScene(
                        e.pos())
                    pen = QPen(QColor(240, 240, 240))
                    pen.setWidth(3)
                    brush = QBrush(QColor(100, 255, 100, 100))
                    self.current_item = self.scene.addRect(
                        QRectF(), pen, brush)
                    self._update_item()
            elif e.type() == QEvent.MouseMove:
                if e.buttons(
                ) & Qt.LeftButton and self.current_item is not None:
                    print("move")
                    self.end_pos = self.graphicsView.mapToScene(e.pos())
                    self._update_item()
            elif e.type() == QEvent.MouseButtonRelease:
                print("release")
                self.end_pos = self.graphicsView.mapToScene(e.pos())
                self._update_item()
                self.current_item = None

        return super().eventFilter(o, e)

    def _update_item(self):
        if self.current_item is not None:
            self.current_item.setRect(
                QRectF(self.start_pos, self.end_pos).normalized())
コード例 #2
0
class SlideViewer(QWidget):
    eventSignal = pyqtSignal(PyQt5.QtCore.QEvent)

    def __init__(self, parent: QWidget = None, viewer_top_else_left=True):
        super().__init__(parent)
        self.init_view()
        self.init_labels(word_wrap=viewer_top_else_left)
        self.init_layout(viewer_top_else_left)

    def init_view(self):
        self.scene = MyGraphicsScene()
        self.view = QGraphicsView()
        self.view.setScene(self.scene)
        self.view.setTransformationAnchor(QGraphicsView.NoAnchor)
        self.view.viewport().installEventFilter(self)

        self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
        self.mouse_press_view = QPoint()

        self.view.horizontalScrollBar().sliderMoved.connect(
            self.on_view_changed)
        self.view.verticalScrollBar().sliderMoved.connect(self.on_view_changed)
        self.scale_initializer_deffered_function = None
        self.slide_view_params = None
        self.slide_helper = None

    def init_labels(self, word_wrap):
        # word_wrap = True
        self.level_downsample_label = QLabel()
        self.level_downsample_label.setWordWrap(word_wrap)
        self.level_size_label = QLabel()
        self.level_size_label.setWordWrap(word_wrap)
        self.selected_rect_label = QLabel()
        self.selected_rect_label.setWordWrap(word_wrap)
        self.mouse_pos_scene_label = QLabel()
        self.mouse_pos_scene_label.setWordWrap(word_wrap)
        self.view_rect_scene_label = QLabel()
        self.view_rect_scene_label.setWordWrap(word_wrap)
        self.labels_layout = QVBoxLayout()
        self.labels_layout.setAlignment(Qt.AlignTop)
        self.labels_layout.addWidget(self.level_downsample_label)
        self.labels_layout.addWidget(self.level_size_label)
        self.labels_layout.addWidget(self.mouse_pos_scene_label)
        # self.labels_layout.addWidget(self.selected_rect_label)
        self.labels_layout.addWidget(self.view_rect_scene_label)

    def init_layout(self, viewer_top_else_left=True):
        main_layout = QVBoxLayout(
            self) if viewer_top_else_left else QHBoxLayout(self)
        main_layout.addWidget(self.view, )
        main_layout.addLayout(self.labels_layout)
        # main_layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(main_layout)

    """
    If you want to start view frome some point at some level, specify <level> and <level_rect> params. 
    level_rect : rect in dimensions of slide at level=level. If None - fits the whole size of slide
    """

    def load(self,
             slide_view_params: SlideViewParams,
             preffered_rects_count=2000,
             zoom_step=1.15):
        self.zoom_step = zoom_step
        self.slide_view_params = slide_view_params
        self.slide_helper = SlideHelper(slide_view_params.slide_path)

        self.slide_graphics = SlideGraphicsGroup(slide_view_params,
                                                 preffered_rects_count)
        self.scene.clear()
        self.scene.addItem(self.slide_graphics)

        if self.slide_view_params.level == -1 or self.slide_view_params.level is None:
            self.slide_view_params.level = self.slide_helper.get_max_level()

        self.slide_graphics.update_visible_level(self.slide_view_params.level)
        self.scene.setSceneRect(
            self.slide_helper.get_rect_for_level(self.slide_view_params.level))

        def scale_initializer_deffered_function():
            self.view.resetTransform()
            # print("size when loading: ", self.view.viewport().size())
            if self.slide_view_params.level_rect:
                # self.view.fitInView(QRectF(*self.slide_view_params.level_rect), Qt.KeepAspectRatioByExpanding)
                self.view.fitInView(QRectF(*self.slide_view_params.level_rect),
                                    Qt.KeepAspectRatio)
                # print("after fit: ", self.get_current_view_scene_rect())
            else:
                start_margins = QMarginsF(200, 200, 200, 200)
                start_image_rect_ = self.slide_helper.get_rect_for_level(
                    self.slide_view_params.level)
                self.view.fitInView(start_image_rect_ + start_margins,
                                    Qt.KeepAspectRatio)

        self.scale_initializer_deffered_function = scale_initializer_deffered_function

    def eventFilter(self, qobj: 'QObject', event: QEvent):
        self.eventSignal.emit(event)
        event_processed = False
        # print("size when event: ", event, event.type(), self.view.viewport().size())
        if isinstance(event, QShowEvent):
            """
            we need it deffered because fitInView logic depends on current viewport size. Expecting at this point widget is finally resized before being shown at first
            """
            if self.scale_initializer_deffered_function:
                # TODO labels start to occupy some space after view was already fitted, and labels will reduce size of viewport
                # self.update_labels()
                self.scale_initializer_deffered_function()
                self.on_view_changed()
                self.scale_initializer_deffered_function = None
        elif isinstance(event, QWheelEvent):
            event_processed = self.process_viewport_wheel_event(event)
            # we handle wheel event to prevent GraphicsView interpret it as scrolling
        elif isinstance(event, QMouseEvent):
            event_processed = self.process_mouse_event(event)

        return event_processed

    def process_viewport_wheel_event(self, event: QWheelEvent):
        # print("size when wheeling: ", self.view.viewport().size())
        zoom_in = self.zoom_step
        zoom_out = 1 / zoom_in
        zoom_ = zoom_in if event.angleDelta().y() > 0 else zoom_out
        self.update_scale(event.pos(), zoom_)
        event.accept()
        self.on_view_changed()
        return True

    def process_mouse_event(self, event: QMouseEvent):
        if self.slide_helper is None:
            return False

        if event.button() == Qt.MiddleButton:
            if event.type() == QEvent.MouseButtonPress:
                self.slide_graphics.update_grid_visibility(
                    not self.slide_graphics.slide_view_params.grid_visible)
                # items=self.scene.items()
                # QMessageBox.information(None, "Items", str(items))
                return True
            # self.update_scale(QPoint(), 1.15)
        elif event.button() == Qt.LeftButton:
            if event.type() == QEvent.MouseButtonPress:
                self.mouse_press_view = QPoint(event.pos())
                self.rubber_band.setGeometry(
                    QRect(self.mouse_press_view, QSize()))
                self.rubber_band.show()
                return True
            elif event.type() == QEvent.MouseButtonRelease:
                self.rubber_band.hide()
                self.remember_selected_rect_params()
                self.slide_graphics.update_selected_rect_0_level(
                    self.slide_view_params.selected_rect_0_level)
                self.update_labels()
                self.scene.invalidate()
                return True
        elif event.type() == QEvent.MouseMove:
            self.mouse_pos_scene_label.setText(
                "mouse_scene: " +
                point_to_str(self.view.mapToScene(event.pos())))
            if not self.mouse_press_view.isNull():
                self.rubber_band.setGeometry(
                    QRect(self.mouse_press_view, event.pos()).normalized())
            return True

        return False

    def remember_selected_rect_params(self):
        pos_scene = self.view.mapToScene(self.rubber_band.pos())
        rect_scene = self.view.mapToScene(
            self.rubber_band.rect()).boundingRect()
        downsample = self.slide_helper.get_downsample_for_level(
            self.slide_view_params.level)
        selected_qrectf_0_level = QRectF(pos_scene * downsample,
                                         rect_scene.size() * downsample)
        self.slide_view_params.selected_rect_0_level = selected_qrectf_0_level.getRect(
        )

    def update_scale(self, mouse_pos: QPoint, zoom):
        old_mouse_pos_scene = self.view.mapToScene(mouse_pos)
        old_view_scene_rect = self.view.mapToScene(
            self.view.viewport().rect()).boundingRect()

        old_level = self.get_best_level_for_scale(
            self.get_current_view_scale())
        old_level_downsample = self.slide_helper.get_downsample_for_level(
            old_level)
        new_level = self.get_best_level_for_scale(
            self.get_current_view_scale() * zoom)
        new_level_downsample = self.slide_helper.get_downsample_for_level(
            new_level)

        level_scale_delta = 1 / (new_level_downsample / old_level_downsample)

        r = old_view_scene_rect.topLeft()
        m = old_mouse_pos_scene
        new_view_scene_rect_top_left = (m - (m - r) / zoom) * level_scale_delta
        new_view_scene_rect = QRectF(
            new_view_scene_rect_top_left,
            old_view_scene_rect.size() * level_scale_delta / zoom)

        new_scale = self.get_current_view_scale(
        ) * zoom * new_level_downsample / old_level_downsample
        transform = QTransform().scale(new_scale, new_scale).translate(
            -new_view_scene_rect.x(), -new_view_scene_rect.y())

        new_rect = self.slide_helper.get_rect_for_level(new_level)
        self.scene.setSceneRect(new_rect)
        self.slide_view_params.level = new_level
        self.reset_view_transform()
        self.view.setTransform(transform, False)
        self.slide_graphics.update_visible_level(new_level)
        self.update_labels()

    def get_best_level_for_scale(self, scale):
        scene_width = self.scene.sceneRect().size().width()
        candidates = [0]
        for level in self.slide_helper.get_levels():
            w, h = self.slide_helper.get_level_size(level)
            if scene_width * scale <= w:
                candidates.append(level)
        best_level = max(candidates)
        return best_level

    def update_labels(self):
        level_downsample = self.slide_helper.get_downsample_for_level(
            self.slide_view_params.level)
        level_size = self.slide_helper.get_level_size(
            self.slide_view_params.level)
        self.level_downsample_label.setText(
            "level, downsample: {}, {:.0f}".format(
                self.slide_view_params.level, level_downsample))
        self.level_size_label.setText(
            "level_size: ({}, {})".format(*level_size))
        self.view_rect_scene_label.setText(
            "view_scene: ({:.0f},{:.0f},{:.0f},{:.0f})".format(
                *self.get_current_view_scene_rect().getRect()))
        if self.slide_view_params.selected_rect_0_level:
            self.selected_rect_label.setText(
                "selected rect (0-level): ({:.0f},{:.0f},{:.0f},{:.0f})".
                format(*self.slide_view_params.selected_rect_0_level))

    def on_view_changed(self):
        if self.scale_initializer_deffered_function is None and self.slide_view_params:
            self.slide_view_params.level_rect = self.get_current_view_scene_rect(
            ).getRect()
        self.update_labels()

    def reset_view_transform(self):
        self.view.resetTransform()
        self.view.horizontalScrollBar().setValue(0)
        self.view.verticalScrollBar().setValue(0)

    def get_current_view_scene_rect(self):
        return self.view.mapToScene(self.view.viewport().rect()).boundingRect()

    def get_current_view_scale(self):
        scale = self.view.transform().m11()
        return scale
コード例 #3
0
ファイル: graph_editor.py プロジェクト: UmbrellaBurns/RTA
class GraphEditor(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setMinimumSize(600, 400)

        random.seed(version=2)

        self.nodes = []

        self.connections = []

        # Widget layout and child widgets:
        self.horizontalLayout = QHBoxLayout(self)

        self.diagramScene = DiagramScene(self)
        self.diagramView = QGraphicsView(self.diagramScene, self)
        self.horizontalLayout.addWidget(self.diagramView)

        self.diagramView.setRenderHint(QtGui.QPainter.Antialiasing, on=True)

        self.started_connection = None

    def remove_connection(self, connection):
        self.diagramScene.removeItem(connection.arrow)
        self.diagramScene.removeItem(connection.arrow.text_label)

        self.connections.remove(connection)

    def start_connection(self, port):
        self.started_connection = Connection(port, None, self)

    def get_node_by_name(self, name):
        for node in self.nodes:
            if node.name == name:
                return node
        return None

    def is_connection_exists(self, first_node, last_node):
        for connection in self.connections:
            if connection.get_first_node() == first_node and connection.get_last_node() == last_node:
                return True
        return False

    def load_diagram_from_graph(self, graph):
        # Read diagram from graph edges

        self.nodes = []
        self.connections = []

        self.diagramScene.clear()

        size = math.sqrt(len(graph.edges))

        x_shift = 100
        y_shift = 100
        i = 0

        for edge in graph.edges:
            first_node = edge.from_node.text
            last_node = edge.to_node.text
            link_type = edge.text

            # First Node
            i += 1
            x = x_shift * i
            y = y_shift
            f = self.add_node(x, y, first_node)

            if i > size:
                y_shift += 100
                i = 0

            # Last Node
            i += 1
            x = x_shift * i
            y = y_shift
            l = self.add_node(x, y, last_node)

            if i > size:
                y_shift += 100
                i = 0

            connection = Connection(f.get_random_port(), None, self)
            connection.set_link_type(link_type)
            connection.setToPort(l.get_random_port())

            self.connections.append(connection)

        # self.dump()

        # svg = QSvgGenerator()
        # svg.setFileName('graph.svg')
        # svg.setSize(QSize(self.diagramScene.width(), self.diagramScene.height()))
        # svg.setViewBox(QRect(0, 0, self.diagramScene.width(), self.diagramScene.height()))
        # svg.setTitle('Semantic Graph')
        # svg.setDescription('File created by RTA')

        # painter = QPainter()
        # painter.begin(svg)
        # self.diagramScene.render(painter)
        # painter.end()

        print('Triples loading is finished')

    def scene_mouse_move_event(self, event):
        if self.started_connection:
            pos = event.scenePos()
            self.started_connection.setEndPos(pos)

    def scene_mouse_release_event(self, event):
        if self.started_connection:
            pos = event.scenePos()
            items = self.diagramScene.items(pos)
            for item in items:
                if type(item) is PortItem:
                    if (not self.is_connection_exists(self.started_connection.fromPort.parent_block,
                                                      item.parent_block)) and (
                                self.started_connection.fromPort.parent_block is not item.parent_block):
                        self.started_connection.setToPort(item)

                        self.connections.append(self.started_connection)

            if self.started_connection.toPort is None:
                self.started_connection.delete()
            self.started_connection = None

    def add_node(self, x, y, text):
        node = Block(text, parent=self)
        node.setPos(x, y)
        self.diagramScene.addItem(node)
        self.nodes.append(node)
        return node

    def remove_node(self, node):

        delete_later = []

        for connection in self.connections:
            if connection.get_last_node() == node or connection.get_first_node() == node:
                delete_later.append(connection)

        for item in delete_later:
            self.remove_connection(item)

        self.diagramScene.removeItem(node)
        self.nodes.remove(node)

    def remove_selected_items(self):
        for item in self.diagramScene.selectedItems():
            if type(item) == Block:
                self.remove_node(item)

    def mousePressEvent(self, event):
        if event.buttons() == QtCore.Qt.RightButton:
            self.add_block_item(self.diagramView.mapToScene(event.pos()))
            # self.dump()

    def add_block_item(self, pos):
        text, ok = QInputDialog.getText(None, 'Добавить элемент', 'Введите название:')
        if ok:
            self.add_node(pos.x(), pos.y(), str(text))

    def dump(self):

        print('||------- DUMP -------||')
        print('Nodes: ')

        for node in self.nodes:
            print(node.get_text())

        print('\nEdges: ')

        for connection in self.connections:
            first_node = connection.get_first_node().get_text()
            last_node = connection.get_last_node().get_text()
            link_type = connection.get_link_type()

            print('{0} {1} {2}'.format(first_node, link_type, last_node))

        print('||------- END --------||')

    def get_all_connections(self):
        return self.connections

    def get_all_nodes(self):
        return self.nodes

    def get_diagram_scene(self):
        return self.diagramScene

    def context_menu_event(self, event):
        menu = QMenu()
        add = menu.addAction('Добавить узел')
        add.triggered.connect(self.add_block_item)

        dump = menu.addAction('Dump')
        dump.triggered.connect(self.dump)

        menu.exec_(event.screenPos())
コード例 #4
0
ファイル: QCliWidget.py プロジェクト: nano13/tambi
class QCliWidget(QWidget):

    interpreter = Interpreter()
    display_widget = None
    vkbd = None
    beamer = None

    result_from_queue = False

    set_tab_text = pyqtSignal(str)

    def __init__(self):
        super().__init__()

        self.unicode_fonts = UnicodeFonts()

        self.grid = QGridLayout()
        self.grid.setContentsMargins(0, 0, 0, 6)
        self.setLayout(self.grid)

        self.display_widget = QTextEditEnhanced()
        self.display_widget.setText(
            "type in the command 'man' down in the command line for getting started ..."
        )
        self.display_widget.setReadOnly(True)

        self.addDisplayWidget()

        line = QInputLine()
        line.setPlaceholderText(
            "This is the command line. See 'man commandline' for details.")
        line.return_pressed.connect(self.commandEntered)
        self.grid.addWidget(line, 1, 0)

        vkbdButton = QPushButton(self)
        vkbdButton.clicked.connect(partial(self.vkbdButtonClicked, line))
        vkbdButton.setIcon(QIcon.fromTheme('input-keyboard'))
        self.grid.addWidget(vkbdButton, 1, 1)

        zoomOutButton = QPushButton(self)
        zoomOutButton.setIcon(QIcon.fromTheme('zoom-out'))
        zoomOutButton.clicked.connect(self.onZoomOutClicked)
        self.grid.addWidget(zoomOutButton, 1, 2)

        zoomResetButton = QPushButton(self)
        zoomResetButton.setIcon(QIcon.fromTheme('zoom-original'))
        zoomResetButton.clicked.connect(self.onZoomResetClicked)
        self.grid.addWidget(zoomResetButton, 1, 3)

        zoomInButton = QPushButton(self)
        zoomInButton.setIcon(QIcon.fromTheme('zoom-in'))
        zoomInButton.clicked.connect(self.onZoomInClicked)
        self.grid.addWidget(zoomInButton, 1, 4)

        self.applyStylesheet()

    def applyStylesheet(self):
        config = ConfigFile(None, None)
        path = config.readVar('global', 'stylesheet')
        stylesheet = ''
        try:
            with open(path) as css:
                for line in css:
                    stylesheet += line

            self.display_widget.setStyleSheet(stylesheet)
        except FileNotFoundError:
            pass

    def addDisplayWidget(self):
        self.view = QGraphicsView()
        self.scene = QGraphicsScene()

        self.scene.addWidget(self.display_widget)
        self.view.setScene(self.scene)
        self.view.setStyleSheet("QGraphicsView { border-style: none; }")

        self.grid.addWidget(self.view, 0, 0, 1, 0)

        self.resizeDisplayWidget()

        self.applyStylesheet()

    def resizeDisplayWidget(self):
        # the magick numbers are for keeping the size of the view allways small enough not to spawn an outer set of scrollbars:
        x = self.view.width() - 2.1
        y = self.view.height() - 2.1
        self.x, self.y = x, y

        mapped_rect = self.view.mapToScene(QRect(0, 0, x, y)).boundingRect()

        self.display_widget.setFixedSize(mapped_rect.width(),
                                         mapped_rect.height())
        self.scene.setSceneRect(0, 0, mapped_rect.width(),
                                mapped_rect.height())

    def resizeEvent(self, event):
        self.resizeDisplayWidget()

    def vkbdButtonClicked(self, lineEdit):
        self.vkbd = QVirtualKeyboardWindow()
        self.vkbd.setLineEdit(lineEdit)

    def commandEntered(self, command):
        # to keep the display_widget in the correct size
        self.resize(self.x, self.y)

        print("command:", command)
        if '|' in command:
            command, pipe = command.split('|')
            self.handleCommand(command)

            pipe = pipe.strip()
            if pipe == 'beamer':
                if self.beamer:
                    self.beamer.destroy()
                    print('destroyed!!!')

                self.beamer = QBeamerWindow()

                from PyQt5.QtWidgets import QLabel, QPushButton
                widget = QLabel('blaaaa')

                self.beamer.setWidget(self.display_widget)
                #self.beamer.setText('test')
                self.beamer.routeToScreen()
                self.beamer.showFullScreen()
        else:
            #self.handleCommand(command)
            self.set_tab_text.emit(command)

            #self.activityIndicator()

            q = queue.Queue()

            self.interpreter_thread = HandleCommandThread(command, q)
            self.interpreter_thread.processResult.connect(self.processResult)
            self.interpreter_thread.clearDisplayWidget.connect(
                self.clearDisplayWidget)
            self.interpreter_thread.makeSnapshot.connect(self.makeSnapshot)
            self.interpreter_thread.stopQueueListener.connect(
                self.stopQueueListener)
            self.interpreter_thread.start()

            self.queue_thread = GetQueueItemsThread(q)
            self.queue_thread.processQueueItem.connect(self.processQueueItem)
            self.queue_thread.start()

    def stopQueueListener(self):
        self.queue_thread.stop()

    def processQueueItem(self, item):
        self.result_from_queue = True

        item = item.getItem()

        json_dict = json.loads(item)
        if json_dict['category'] == 'progressbar':
            last_type = type(self.display_widget)
            if not last_type == QProgressBar:
                self.display_widget.deleteLater()
                self.display_widget = QProgressBar()

            self.display_widget.setMinimum(json_dict['minimum'])
            self.display_widget.setMaximum(json_dict['maximum'])
            self.display_widget.setValue(json_dict['value'])

            if not last_type == QProgressBar:
                self.addDisplayWidget()

        else:
            result_object = Result()
            result_object.payload = item.getItem()
            self.resultInTextEdit(result_object)

    def processResult(self, result):
        if self.result_from_queue:
            self.result_from_queue = False

        else:
            #if result is None:
            #self.showErrorMessage('no result found')

            if hasattr(result, 'payload') and result.payload:
                if hasattr(result, 'category') and result.category == "table":
                    try:
                        result.payload[0]
                    except IndexError:
                        pass  # datastructure does not fit to display type 'table'
                    else:
                        self.resultInTable(result)

                elif hasattr(
                        result,
                        'category') and result.category == "multimedia_table":
                    self.resultInMultimediaTable(result)

                elif hasattr(result, 'category') and result.category == "list":
                    self.resultInTextEdit(result)

                elif hasattr(result, 'category') and result.category == "text":
                    self.resultInTextEdit(result)

                elif hasattr(result,
                             'category') and result.category == "string":
                    self.resultInTextEdit(result)

                elif hasattr(result,
                             'category') and result.category == "itemized":
                    self.resultInItemizedWidget(result)

                elif hasattr(result,
                             'category') and result.category == "image":
                    self.resultInImageWidget(result)

                elif hasattr(result, 'category') and result.category == "html":
                    #self.resultInHTMLWidget(result)
                    self.resultInTextEdit(result)

                elif hasattr(result,
                             'category') and result.category == 'diagram':
                    self.resultInDiagram(result)

                elif hasattr(result,
                             'category') and result.category == 'bloodline':
                    self.resultInBloodlineDiagram(result)

                elif hasattr(result,
                             'category') and result.category == 'command':
                    self.showMapWidget()

            elif hasattr(result, 'error') and result.error:
                self.showErrorMessage(result.error)

            else:
                result = Result()
                result.payload = 'empty result set'
                self.resultInTextEdit(result)

    def activityIndicator(self):
        self.display_widget.deleteLater()

        label = QLabel()
        movie = QMovie('./assets/images/activity_indicator.gif')
        movie.start()
        label.setMovie(movie)

        self.display_widget = QWidget()
        layout = QVBoxLayout()
        self.display_widget.setLayout(layout)
        layout.addWidget(label, Qt.AlignCenter)

        self.addDisplayWidget()

    def clearDisplayWidget(self):
        self.display_widget.deleteLater()
        self.display_widget = QTextEditEnhanced()
        self.display_widget.setReadOnly(True)
        self.addDisplayWidget()

    def makeSnapshot(self):
        image = QImage(self.display_widget.size(), QImage.Format_ARGB32)
        painter = QPainter(image)

        if painter.isActive():
            self.render(painter)

        painter.end()

        default_dir = path.join(path.expanduser('~'))
        filename = QFileDialog.getSaveFileName(self, 'Save Snapshot',
                                               default_dir)

        image.save(filename[0])

    def resultInTable(self, result):
        self.display_widget.deleteLater()
        self.display_widget = QTableWidget()
        self.display_widget.setRowCount(len(result.payload))
        self.display_widget.setColumnCount(len(result.payload[0]))

        try:
            self.display_widget.setHorizontalHeaderLabels(result.header)
        except TypeError:
            pass
        try:
            self.display_widget.setVerticalHeaderLabels(result.header_left)
        except TypeError:
            pass

        for row, line in enumerate(result.payload):
            for column, item in enumerate(line):
                table_item = QTableWidgetItem(str(item))
                table_item.setFlags(Qt.ItemIsEnabled)
                self.unicode_fonts.applyFontToQWidget(str(item), table_item)
                self.display_widget.setItem(row, column, table_item)

        self.display_widget.resizeColumnsToContents()
        self.addDisplayWidget()

    def resultInMultimediaTable(self, result):
        self.display_widget.deleteLater()

        max_length = 0
        for line in result.payload:
            if len(line) > max_length:
                max_length = len(line)

        self.display_widget = QTableWidget()
        self.display_widget.setRowCount(len(result.payload))
        self.display_widget.setColumnCount(max_length)

        audio_count = 0
        config = ConfigFile(None, None)
        deckpath = config.readPath("vocable", "deckpath")
        for row, line in enumerate(result.payload):
            deckname = line[0]
            for column, item in enumerate(line):
                if self.isImage(str(item)):
                    pixmap = QPixmap()
                    pixmap.load(path.join(deckpath, deckname, str(item)))
                    pixmap = pixmap.scaled(QSize(60, 30), Qt.KeepAspectRatio)
                    image_widget = QLabel()
                    image_widget.setPixmap(pixmap)
                    self.display_widget.setCellWidget(row, column,
                                                      image_widget)
                elif self.isAudio(str(item)):
                    splitted = item.split(',')
                    if audio_count < len(splitted):
                        audio_count = len(splitted)
                    audio_widget = QAudioItems(path.join(deckpath, deckname),
                                               self.display_widget, 7,
                                               max_length)
                    audio_widget.appendPlayButtonsList(splitted, row)
                else:
                    table_item = QTableWidgetItem(str(item))
                    table_item.setFlags(Qt.ItemIsEnabled)
                    #self.unicode_fonts.applyFontToQWidget(str(item), table_item)
                    self.display_widget.setItem(row, column, table_item)

        self.display_widget.setColumnCount(max_length + audio_count)
        self.display_widget.resizeColumnsToContents()
        self.addDisplayWidget()

    def resultInTextEdit(self, result):
        self.display_widget.deleteLater()
        self.display_widget = QTextEditEnhanced()

        self.unicode_fonts.applyFontAndSizeToQWidget(result.toString(),
                                                     self.display_widget)

        self.display_widget.setAcceptRichText(True)

        self.display_widget.setText(result.toString())
        self.display_widget.setReadOnly(True)
        self.display_widget.setTextInteractionFlags(
            self.display_widget.textInteractionFlags()
            | Qt.TextSelectableByKeyboard)
        self.addDisplayWidget()

    def resultInHTMLWidget(self, result):
        self.display_widget.deleteLater()
        self.display_widget = QWebView()

        self.display_widget.setHtml(result.payload)
        self.addDisplayWidget()

    def resultInItemizedWidget(self, result):
        self.display_widget.deleteLater()
        self.display_widget = QItemizedWidget(result.payload)
        self.addDisplayWidget()

    def resultInImageWidget(self, result):
        self.display_widget.deleteLater()

        self.display_widget = QCustomizedGraphicsView()

        import PIL
        if type(result.payload) == PIL.Image.Image:
            from PIL.ImageQt import ImageQt
            qimage = ImageQt(result.payload)
            pixmap = QPixmap.fromImage(qimage)

        #pixmap = QPixmap("/tmp/tmprp3q0gi9.PNG")
        #pixmap.fromImage(image)

        item = self.display_widget.scene().addPixmap(pixmap)
        item.setPos(0, 0)
        self.addDisplayWidget()

    def resultInDiagram(self, result):
        self.display_widget.deleteLater()

        curve = QLineSeries()
        pen = curve.pen()
        pen.setColor(Qt.red)
        pen.setWidthF(2)
        curve.setPen(pen)

        for data in result.payload:
            if type(data['y']) == str:
                data['y'] = 0
            curve.append(data['x'], data['y'], 10)

        chart = QChart()
        chart.setTitle(result.name)
        chart.legend().hide()
        chart.addSeries(curve)
        chart.createDefaultAxes()

        view = QChartViewEnhanced(chart)
        view.setRenderHint(QPainter.Antialiasing)
        self.display_widget = view
        self.addDisplayWidget()

    def resultInBloodlineDiagram(self, result):
        self.display_widget.deleteLater()
        self.display_widget = QBloodlineWidget(result.payload)
        self.addDisplayWidget()

    def showMapWidget(self):
        self.display_widget.deleteLater()

        self.display_widget = QMapWidget()
        self.display_widget.showPosition()

        self.addDisplayWidget()

    def showErrorMessage(self, message):
        self.display_widget.deleteLater()
        self.display_widget = QTextEditEnhanced()
        self.display_widget.setText(message)
        self.display_widget.setReadOnly(True)
        self.addDisplayWidget()

    def onZoomInClicked(self):
        if type(self.display_widget) == QTextEditEnhanced:
            self.display_widget.zoomIn()
        elif type(self.display_widget) == QChartViewEnhanced:
            self.display_widget.chart().zoomIn()
        else:
            self.view.scale(SCALE_FACTOR, SCALE_FACTOR)
            self.resizeDisplayWidget()

    def onZoomOutClicked(self):
        if type(self.display_widget) == QTextEditEnhanced:
            self.display_widget.zoomOut()
        elif type(self.display_widget) == QChartViewEnhanced:
            self.display_widget.chart().zoomOut()
        else:
            self.view.scale(1 / SCALE_FACTOR, 1 / SCALE_FACTOR)
            self.resizeDisplayWidget()

    def onZoomResetClicked(self):
        if type(self.display_widget) == QTextEditEnhanced:
            self.display_widget.zoomReset()
        elif type(self.display_widget) == QChartViewEnhanced:
            self.display_widget.chart().zoomReset()
        else:
            self.view.resetTransform()
            self.resizeDisplayWidget()

    def keyPressEvent(self, event):
        if (event.modifiers() & Qt.ControlModifier):
            if event.key() == Qt.Key_Plus:
                self.onZoomInClicked()

            elif event.key() == Qt.Key_Minus:
                self.onZoomOutClicked()

    def isImage(self, data):
        suffixes = ['.png', '.jpg', '.jpe', '.jpeg', '.svg', '.bmp']
        for suffix in suffixes:
            if data.lower().endswith(suffix):
                return True
        return False

    def isAudio(self, data):
        suffixes = ['.ogg', '.wav', '.mp3', '.aiff', '.wma']
        for suffix in suffixes:
            if data.lower().endswith(suffix):
                return True
        return False
コード例 #5
0
class ViewWindow(QMainWindow):  # QWidget):
    def __init__(self):
        super().__init__()
        self.pilorig = None
        self.savedImg = None
        self.controlPanel = None
        self.dirName, self.fileName = '', ''
        self.dirFileNames = []
        self.fileIdx = -1
        self.ctrl = None  # transformation control widget
        self.locator = None  # locator rectangle widget
        self.locator1 = None  # locator 1st point
        self.locator2 = None  # locator 2nd point
        self.scale = (1, 1)
        self.show_histogram = False
        # usage of QGraphicsScene and QGraphicsView is taken from
        # https://stackoverflow.com/questions/50851587/undo-functionality-for-qpainter-drawellipse-function
        self.gv = None
        self.scene = None
        self.scaledPixmap = None
        self.histogram = []
        self.initUI()

    def initUI(self):
        self.setWindowTitle("PyQT Tuts!")
        transforms.editWindow = self

        bar = self.menuBar()
        makeMenu(bar, FILE_MENU, self)
        menu = bar.actions()[2].menu()
        menu.addSeparator()
        addAction(menu, self, 'Show &Histogram', self.toggleHistogram,
                  'Ctrl+H', 'Show/hide histogram')

        menu = bar.actions()[1].menu()
        menu.addSeparator()
        for item in transforms.getTransforms():
            addAction(menu, self, item[0], item[2], item[3],
                      item[4])  # item[1] (Icon is ignored, todo: add support)

        menu = bar.actions()[0].menu()
        menu.addSeparator()
        addAction(menu, self, '&Next', self.onNextBtn, 'Ctrl+N', 'Next image')
        addAction(menu, self, '&Prev', self.onPrevBtn, 'Ctrl+P', 'Prev image')
        addAction(menu, self, '&Save', self.onSaveImg, 'Ctrl+S', 'Save image')

        layout1 = QVBoxLayout()

        self.gv = QGraphicsView()
        self.scene = QGraphicsScene()
        self.gv.setScene(self.scene)
        self.gv.installEventFilter(self)
        layout1.addWidget(self.gv)

        panel = QWidget(self)
        self.controlPanel = QHBoxLayout()
        panel.setLayout(self.controlPanel)
        layout1.addWidget(panel)

        center = QWidget()
        center.setLayout(layout1)
        self.setCentralWidget(center)

    def toggleHistogram(self):
        self.show_histogram = not self.show_histogram
        self.make_histogram()

    def eventFilter(self, obj, event):
        if obj == self.gv and event.type() == QEvent.MouseButtonPress:
            p = self.gv.mapToScene(event.pos())
            self.setLocation(p)
        return QWidget.eventFilter(self, obj, event)

    def setLocation(self, pos):
        if self.locator2 is not None:
            self.locator1 = None
            self.locator2 = None
        if self.locator1:
            self.locator2 = (pos.x(), pos.y())
            self.drawLocator()
        else:
            self.locator1 = (pos.x(), pos.y())

    def drawLocator(self):
        if self.locator:
            self.scene.removeItem(self.locator)
            self.locator = None
        pen = QPen(Qt.red, 3)
        self.locator = self.scene.addRect(self.locator1[0], self.locator1[1],
                                          self.locator2[0] - self.locator1[0],
                                          self.locator2[1] - self.locator1[1],
                                          pen)
        print('locator', self.locator1, self.locator2)
        self.gv.update()  # self.label.update() #QApplication.processEvents()

    def resizeEvent(self, event):
        QWidget.resizeEvent(self, event)
        self.sizeImage()

    def openImage(self, fileName):
        self.setWindowTitle(fileName)
        self.dirName = os.path.dirname(fileName)
        self.fileName = os.path.basename(fileName)
        self.dirFileNames = list(imgFiles(self.dirName))
        self.fileIdx = self.dirFileNames.index(self.fileName)
        if fileName:
            self.pilorig = PIL.Image.open(fileName)
            self.sizeImage()

    def fullFileName(self):
        if self.fileName:
            return os.path.join(self.dirName, self.fileName)
        else:
            return None

    def showImage(self, fileName):
        self.openImage(fileName)
        self.show()

    def updateImage(self, pilImage):
        self.pilorig = pilImage
        self.sizeImage()

    def sizeImage(self):
        orig = pil2pixmap(self.pilorig)
        if self.pilorig:
            if self.scaledPixmap:
                self.scene.removeItem(self.scaledPixmap)
                self.scaledPixmap = None
            if self.locator:
                self.scene.removeItem(self.locator)
                self.locator = None

            pixmap = orig.scaled(self.gv.width(),
                                 self.gv.height(),
                                 Qt.KeepAspectRatio,
                                 transformMode=Qt.SmoothTransformation)
            self.scaledPixmap = self.scene.addPixmap(pixmap)

            self.scale = (orig.size().width() / pixmap.size().width(),
                          orig.size().height() / pixmap.size().height())
            self.make_histogram()

    def absLocatorRect(self):
        return [
            self.locator1[0] * self.scale[0], self.locator1[1] * self.scale[1],
            self.locator2[0] * self.scale[0], self.locator2[1] * self.scale[1]
        ]

    def nextFileName(self):
        if self.fileIdx < len(self.dirFileNames) - 1:
            return os.path.join(self.dirName,
                                self.dirFileNames[self.fileIdx + 1])
        else:
            return None

    def prevFileName(self):
        if self.fileIdx > 0:
            return os.path.join(self.dirName,
                                self.dirFileNames[self.fileIdx - 1])
        else:
            return None

    def onNextBtn(self):
        fn = self.nextFileName()
        if fn:
            self.openImage(os.path.join(self.dirName, fn))

    #@staticmethod
    def onPrevBtn(self):
        fn = self.prevFileName()
        if fn:
            self.openImage(os.path.join(self.dirName, fn))

    def onSaveImg(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "Save as ...",
            os.path.join(self.dirName, self.fileName),
            "All Files (*);;Jpeg Files(*.jpg)",
            options=options)
        if fileName:
            print(fileName)
            self.pilorig.save(fileName)

    def make_histogram(self):  # should it be a ShowWin class method?
        #self.canvas.delete('histogram')
        for it in self.histogram:
            self.scene.removeItem(it)
        del self.histogram[:]
        if not self.show_histogram:
            return

        img = self.pilorig
        if not img:
            return
        h = img.convert("L").histogram()
        maxVal = 1
        for i in range(0, len(h)):
            if h[i] > maxVal:
                maxVal = h[i]
        _X = float(img.size[1])
        x = 100 if _X > 100 else _X

        penGray = QPen(Qt.gray, 3)
        penRed = QPen(Qt.red, 3)

        for i in range(0, len(h)):
            if h[i] == maxVal:
                pen = penRed
            else:
                pen = penGray
            self.histogram.append(
                self.scene.addLine(i, x, i, x - x * h[i] / maxVal, pen))

        self.histogram.append(self.scene.addRect(0, 0, len(h), x, penGray))
        self.gv.update()

    # support transformation plugins
    def controlImg(self, checkCtrl=True):
        if checkCtrl and not self.ctrl:
            return None
        else:
            return self.savedImg

    def setCtrl(self, ctrl):
        if ctrl and self.ctrl:
            return  # do not allow two control panels
        if self.ctrl and not ctrl:
            self.ctrl.setParent(None)
        self.ctrl = ctrl
        if ctrl:
            self.controlPanel.addWidget(ctrl)
            self.savedImg = self.pilorig

    def unsetCtrl(self):
        if self.ctrl:
            self.ctrl.setParent(None)
            self.ctrl = None
コード例 #6
0
ファイル: filter.py プロジェクト: johan--/OurManInAntibes
class Filter(QWidget):
    label_map = {
        'K': 'Keep',
        'T': 'Take',
        'S': 'Stitch',
        'M': 'Compare',
        'C': 'Crop',
        'D': 'Delete',
        None: ''
    }

    def __init__(self, parent, config, new_files):
        QWidget.__init__(self, parent)
        self.zoomLevel = 1.0
        self.rotation = 0

        self.all_images = ImageList()
        self.compare_set = ImageList()
        # start with all images
        self.images = self.all_images
        self.comparing = False

        self.src = config['Directories']['mid']
        self.dst = os.getcwd()
        self.scan(self.src)
        self.new_files = new_files

        self.image = None

        self.image_actions = defaultdict(lambda: None)
        self.image_positions = {}
        self.original_position = None

        self.buildUI(parent)

        self.dir_dialog = QFileDialog(self)
        self.dir_dialog.setFileMode(QFileDialog.Directory)

    def buildUI(self, parent):
        # left labels
        self.splitter = QSplitter(self)
        self.splitter.setContentsMargins(QMargins(0, 0, 0, 0))
        self.splitter.setOrientation(Qt.Horizontal)
        self.widget = QWidget(self.splitter)
        self.label_layout = QVBoxLayout(self.widget)

        for count, name in enumerate([
                'exposure_time',
                'fnumber',
                'iso_speed',
                'focal_length',
                'date',
        ]):
            key_label = QLabel(name.replace('_', ' ').title(), self.widget)
            # setattr(self, "key_label_%02d" % count, key_label)
            self.label_layout.addWidget(key_label)

            value_label = QLabel(self.widget)
            value_label.setAlignment(Qt.AlignRight)
            setattr(self, name, value_label)
            self.label_layout.addWidget(value_label)

        # TODO
        s = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.label_layout.addItem(s)

        # main view
        self.scene = QGraphicsScene()

        self.item = QGraphicsPixmapItem()
        self.scene.addItem(self.item)

        self.view = QGraphicsView(self.scene, parent)
        self.view.setFrameShadow(QFrame.Plain)
        self.view.setFrameStyle(QFrame.NoFrame)
        self.view.setDragMode(QGraphicsView.ScrollHandDrag)
        self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        brush = QBrush(QColor(20, 20, 20))
        brush.setStyle(Qt.SolidPattern)
        self.view.setBackgroundBrush(brush)

        self.view.show()

        # "status bar"
        self.fname = QLabel(self)
        self.fname.setTextInteractionFlags(Qt.TextSelectableByMouse)
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.tag_view = QLabel(self)

        status_bar = QHBoxLayout()
        status_bar.addWidget(self.fname)
        status_bar.addItem(spacer)
        status_bar.addWidget(self.tag_view)

        w = QWidget(self.splitter)

        v = QVBoxLayout(w)
        v.setContentsMargins(QMargins(0, 0, 0, 0))
        v.addWidget(self.view)
        v.addLayout(status_bar)

        # TODO
        self.splitter.setSizes([10, 90])

        h = QHBoxLayout(self)
        h.setContentsMargins(QMargins(0, 0, 0, 0))
        h.addWidget(self.splitter)

        # now... ACTION!(s)
        for key, slot in (
            (Qt.Key_Home, self.first_image),
            (Qt.Key_PageUp, self.prev_ten),
            (Qt.Key_Backspace, self.prev_image),
            (Qt.Key_Space, self.next_image),
            (Qt.Key_PageDown, self.next_ten),
            (Qt.Key_End, self.last_image),
            (Qt.Key_F, self.toggle_fullsize),
            (Qt.Key_K, self.keep),
            (Qt.Key_T, self.tag),
            (Qt.Key_S, self.stitch),
            (Qt.Key_M, self.select_for_compare),
            (Qt.Key_C, self.crop),
            (Qt.Key_D, self.delete),
            (Qt.Key_U, self.untag),
            (Qt.Key_X, self.expunge),
            (Qt.Key_Return, self.apply),
            (Qt.CTRL + Qt.Key_M, self.compare),
            (Qt.CTRL + Qt.Key_O, self.new_src),
            (Qt.CTRL + Qt.Key_S, self.save),
        ):
            action = QAction(parent)
            action.setShortcut(QKeySequence(key))
            action.triggered.connect(slot)
            self.view.addAction(action)

    def scan(self, src):
        index = 0

        logger.debug('scanning %r', src)
        for r, dirs, files in os.walk(os.path.abspath(src)):
            for name in sorted(files):
                if name[-4:].lower() in ('.jpg', '.png'):
                    # logger.info ('found %s' % name)
                    self.images.append(Image(index, os.path.join(r, name)))
                    index += 1

    def rotate_view(self):
        # we have to 'undo' the rotations, so the numbers are negative
        rotate = -self.image.rotation

        # undo the last rotation and apply the new one
        self.view.rotate(-self.rotation + rotate)
        self.rotation = rotate
        logger.debug(rotate, self.rotation)

    def zoom_to_fit(self):
        winSize = self.view.size()
        logger.debug(self.image.size, winSize)

        hZoom = winSize.width() / self.image.size.width()
        vZoom = winSize.height() / self.image.size.height()
        zoomLevel = min(hZoom, vZoom)

        self.zoom(zoomLevel)

    def zoom(self, zoomLevel):
        # logger.info (zoomLevel)
        scale = zoomLevel / self.zoomLevel
        # logger.info ("scaling", scale)
        self.view.scale(scale, scale)

        self.zoomLevel = zoomLevel

    def move_index(self, to=None, how_much=0):
        if self.image is not None:
            self.save_position()

        self.images.move_index(to, how_much)

        self.image = self.images.current_image
        self.show_image()

    def view_position(self):
        view_size = self.view.size()
        center = QPoint(view_size.width() / 2, view_size.height() / 2)
        position = self.view.mapToScene(center)
        return position

    def show_image(self):
        logger.info(self.image.path)
        self.image.read()

        self.rotate_view()
        self.item.setPixmap(self.image.pixmap)
        if self.zoomLevel != 1.0:
            self.zoom_to_fit()

        # we might have rotated the view, but the scene still has the image
        # in its original size, so we use that as bounding rect
        boundingRect = QRectF(self.item.pixmap().rect())
        logger.debug(boundingRect)
        self.scene.setSceneRect(boundingRect)

        if self.image.index in self.image_positions:
            self.original_position = None
            position = self.image_positions[self.image.index]
            logger.debug("previously moved, back to that point: %f x %f",
                         position.x(), position.y())
            self.view.centerOn(position)
        else:
            # TODO: 'undo' the move
            position = self.view_position()
            logger.debug("original position: %f x %f", position.x(),
                         position.y())
            self.original_position = position
            self.view.centerOn(self.item)

        self.update_view()

    def update_view(self):
        self.fname.setText(self.image.path)
        label = self.label_map[self.image_actions[self.image]]
        self.tag_view.setText(label)

        meta = self.image.metadata
        date = read_image_date(self.image.path, meta)
        if date is None:
            self.date.setText('unknown')
        else:
            self.date.setText(date.isoformat())

        self.fnumber.setText(str(meta.get_fnumber()))
        self.focal_length.setText(str(meta.get_focal_length()))
        self.iso_speed.setText(str(meta.get_iso_speed()))

        f = meta.get_exposure_time()
        if f is None:
            s = 'unknown'
        elif f.denominator == 1:
            s = '%ds' % f.numerator
        else:
            s = '%d/%ds' % (f.numerator, f.denominator)
        self.exposure_time.setText(s)

    def save_position(self):
        position = self.view_position()
        if (self.original_position is None
                or position.x() != self.original_position.x()
                or position.y() != self.original_position.y()):

            logger.debug("saving position: %f x %f", position.x(),
                         position.y())
            # this way (I hope) I only remember those positions which changed
            self.image_positions[self.image.index] = position

    # movements
    def first_image(self, *args):
        self.move_index(to=0)

    def prev_ten(self, *args):
        self.move_index(how_much=-10)

    def prev_image(self, *args):
        self.move_index(how_much=-1)

    def next_image(self, *args):
        self.move_index(how_much=+1)

    def next_ten(self, *args):
        self.move_index(how_much=+10)

    def last_image(self, *args):
        self.move_index(to=len(self.images) - 1)

    def toggle_fullsize(self, *args):
        # noooooooooooooooothing compares...
        if abs(self.zoomLevel - 1.0) < 0.000001:
            # logger.info ('fit')
            self.zoom_to_fit()
        else:
            # logger.info ('orig')
            self.zoom(1.0)

    # image actions
    # Keep -> /gallery/foo, resized
    def keep(self, *args):
        self.image_actions[self.image] = 'K'
        self.next_image()

    # Tag -> /gallery/foo, as-is
    def tag(self, *args):
        self.image_actions[self.image] = 'T'
        self.next_image()

    # Stitch -> 02-new/stitch
    def stitch(self, *args):
        self.image_actions[self.image] = 'S'
        self.next_image()

    # coMpare
    def select_for_compare(self, *args):
        if self.image_actions[self.image] == 'M':
            # TODO?: undo/toggle
            # NOTE: this can already be achieved by Untag
            pass
        else:
            self.image_actions[self.image] = 'M'
            # ugh
            insort(self.compare_set, self.image)
            logger.debug(self.compare_set.images)

        self.next_image()

    def compare(self):
        logger.info('comparing')
        self.comparing = True
        self.images = self.compare_set
        self.move_index()

    # Crop -> launch gwenview
    def crop(self, *args):
        self.image_actions[self.image] = 'C'
        self.next_image()

    # Delete -> /dev/null
    def delete(self, *args):
        self.image_actions[self.image] = 'D'

        if self.comparing:
            # remove the image from the list and refresh the view
            self.images.remove()
            self.image = self.images.current_image
            self.show_image()
        else:
            self.next_image()

    def untag(self, *args):
        try:
            del self.image_actions[self.image]
            # don't move, most probably I'm reconsidering what to do
            # but change the label
            self.tag_view.setText('')
        except KeyError:
            # tried to untag a non-tagged image
            pass

    def resize(self, src, dst):
        src_meta = GExiv2.Metadata(src)
        src_p = QPixmap(src)
        dst_p = src_p.scaled(4500, 3000, Qt.KeepAspectRatio,
                             Qt.SmoothTransformation)

        dst_p.save(src)
        shutil.move(src, dst)

        # copy all the metadata
        dst_meta = GExiv2.Metadata(dst)
        for tag in src_meta.get_tags():
            dst_meta[tag] = src_meta[tag]
        dst_meta.save_file()

    def apply(self, *args):
        if not self.comparing:
            hugin = False

            if len([
                    action for action in self.image_actions.values()
                    if action in ('K', 'T')
            ]) > 0:
                self.new_dst()

            for img, action in sorted(
                    self.image_actions.items(),
                    key=lambda s: s[0].path):  # sort by fname
                src = img.path
                dst = os.path.join(self.dst, os.path.basename(src))

                try:
                    if src in self.new_files and action not in ('C', 'D'):
                        # rename
                        src = rename_file(src)

                    if action == 'K':
                        # Keep -> /gallery/foo, as-is
                        logger.info("%s -> %s" % (src, dst))
                        shutil.move(src, dst)

                    elif action == 'T':
                        # Tag -> /gallery/foo, resized
                        self.resize(src, dst)

                    elif action == 'S':
                        # Stitch -> 02-new/stitch
                        dst = os.path.join(
                            '/home/mdione/Pictures/incoming/02-new/stitch',
                            os.path.basename(src))
                        logger.info("%s -> %s" % (src, dst))
                        shutil.move(src, dst)
                        hugin = True

                    elif action == 'M':
                        # coMpare -> 03-cur
                        dst = os.path.join(
                            '/home/mdione/Pictures/incoming/03-cur',
                            os.path.basename(src))
                        logger.info("%s -> %s" % (src, dst))
                        shutil.move(src, dst)

                        new_root = '/home/mdione/Pictures/incoming/03-cur'
                        old_root = self.src

                    elif action == 'C':
                        # Crop -> launch gwenview
                        os.system('gwenview %s' % src)

                        # asume the file was saved under a new name
                        # logger.info ("%s -> %s" % (src, dst))
                        # shutil.move (src, dst)

                    elif action == 'D':
                        # Delete -> /dev/null
                        os.unlink(src)
                        logger.info("%s deleted" % (src, ))
                except FileNotFoundError as e:
                    logger.info(e)

            if hugin:
                os.system('hugin')

            self.reset()
        else:
            logger.info('back to all')
            self.comparing = False

            # untag all images marked for compare
            for image in self.compare_set:
                # but only those still marked 'M'
                if self.image_actions[image] == 'M':
                    del self.image_actions[image]

            self.compare_set.clear()
            self.images = self.all_images
            self.move_index()

    def expunge(self, *args):
        for img, action in self.image_actions.items():
            src = img.path
            try:
                if action == 'D':
                    # Delete -> /dev/null
                    os.unlink(src)
                    logger.info("%s deleted" % (src, ))
            except FileNotFoundError as e:
                logger.info(e)

        self.reset()

    def reset(self, new_root=None):
        if new_root is not None:
            self.src = new_root

        self.image_actions.clear()
        self.all_images.clear()
        self.compare_set.clear()
        self.comparing = False
        self.scan(self.src)

    def new_dst(self, *args):
        self.dir_dialog.setDirectory(self.dst)
        if self.dir_dialog.exec():
            self.dst = self.dir_dialog.selectedFiles()[0]

    def new_src(self, *args):
        self.dir_dialog.setDirectory(self.src)
        if self.dir_dialog.exec():
            self.src = self.dir_dialog.selectedFiles()[0]
            self.reset()

    def save(self, *args):
        src = self.image.path
        self.dir_dialog.setDirectory(self.dst)
        if self.dir_dialog.exec():
            dst_dir = self.dir_dialog.selectedFiles()[0]
            if src in self.new_files:
                src = rename_file(src)

            dst = os.path.join(dst_dir, os.path.basename(src))

            logger.info("%s -> %s" % (src, dst))
            self.resize(src, dst)

            self.next_image()
コード例 #7
0
class WindowTime(QMainWindow):
    '''This class handles the main window.'''
    def __init__(self):
        super().__init__()

        self.menubar = self.menuBar()

        self.status = self.statusBar()

        exitAction = QAction('Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.close)

        fileMenu = self.menubar.addMenu('&File')
        fileMenu.addAction(exitAction)

        self.zoomlevel = 2
        # self.pixmaps = {2: QPixmap('yeg-2.png'), 3: QPixmap('yeg-3.png'),
        # 				4: QPixmap('yeg-4.png'), 5: QPixmap('yeg-5.png'), 6: QPixmap('yeg-6.png')}
        #
        # self.sizes = {1: 512, 2: 1024, 3: 2048, 4: 4096, 5: 8192, 6: 16384}
        self.pixmaps = {
            2: QPixmap(os.path.join(__location__, 'yeg-2.png')),
            3: QPixmap(os.path.join(__location__, 'yeg-3.png')),
            4: QPixmap(os.path.join(__location__, 'yeg-4.png')),
            5: QPixmap(os.path.join(__location__, 'yeg-5.png'))
        }

        self.sizes = {1: 512, 2: 1024, 3: 2048, 4: 4096, 5: 8192}
        self.pressed = False
        self.start = 0
        self.dest = 0
        self.center = (0, 0)
        self.howmanycars = 0
        self.customer_id = 0
        self.initUI()

        self.show()

    def initUI(self):
        #The QToolTip class provides tool tips (balloon help) for any widget.
        QToolTip.setFont(QFont('SansSerif', 10))

        w = QWidget()
        #The QGridLayout class lays out widgets in a grid.
        grid = QGridLayout()
        #setLayout(self, Qlayout) Sets the layout manager for this widget to layout.
        #The QLayout argument has it's ownership transferred to Qt.
        w.setLayout(grid)
        #The QLabel widget provides a text or image display.
        labelZoom = QLabel('Zoom here pls')
        labelPassengers = QLabel('How many Passengers')

        #The QPushButton widget provides a command button. Takes in arguments
        #For text label
        btnZoomIn = QPushButton('+')
        btnZoomIn.setToolTip('Zoom In')
        btnZoomIn.clicked.connect(self.zoomIn)
        btnZoomOut = QPushButton('-')
        btnZoomOut.setToolTip('Zoom Out')
        btnZoomOut.clicked.connect(self.zoomOut)

        spinBox = QSpinBox()
        spinBox.setMaximum(5)
        spinBox.setMinimum(1)

        self.mapScene = GraphicsScene()
        self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel],
                                   self.sizes[self.zoomlevel])
        self.mapScene.addPixmap(self.pixmaps[self.zoomlevel])
        #ellipse = mapScene.addEllipse(50,100,50,50)
        self.mapView = QGraphicsView()
        self.mapView.setScene(self.mapScene)
        #Set it so user can drag map via cursor
        self.mapView.setDragMode(QGraphicsView.ScrollHandDrag)
        #Hide the scroll bar
        self.mapView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.mapView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        grid.addWidget(labelZoom, 0, 4)
        grid.addWidget(self.mapView, 0, 0, 4, 4)
        grid.addWidget(btnZoomIn, 1, 4)
        grid.addWidget(btnZoomOut, 2, 4)
        grid.addWidget(labelPassengers, 3, 4)
        grid.addWidget(spinBox, 4, 4)

        #How everything will look on the screen
        self.setGeometry(300, 300, 800, 600)
        self.setWindowTitle('Uber Pool')
        self.setCentralWidget(w)

        #CHANGED: This
    def setCenter(self):
        center = self.mapView.mapToScene(self.mapView.width() // 2,
                                         self.mapView.height() // 2)
        self.center = (ConversionFunctions.x_to_longitude(
            self.zoomlevel, center.x()),
                       ConversionFunctions.y_to_latitude(
                           self.zoomlevel, center.y()))

    def zoomIn(self):
        if self.zoomlevel < 5:
            self.pressed = False
            self.setCenter()
            self.zoomlevel += 1
            self.updateSceneZoom()

    def zoomOut(self):
        if self.zoomlevel > 2:
            self.pressed = False
            self.setCenter()
            self.zoomlevel -= 1
            self.updateSceneZoom()

    #updates the scence once the zoom button has been pressed. The scene is
    #updated on the center of the last scene
    def updateSceneZoom(self):
        self.mapScene.clear()
        self.mapScene.addPixmap(self.pixmaps[self.zoomlevel])
        self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel],
                                   self.sizes[self.zoomlevel])
        (x, y) = (ConversionFunctions.longitude_to_x(self.zoomlevel,
                                                     self.center[0]),
                  ConversionFunctions.latitude_to_y(self.zoomlevel,
                                                    self.center[1]))
        self.mapView.centerOn(x, y)

    #returns the x,y position of the cursor on the map
    def handleClick(self, pos):
        return (pos.x(), pos.y())
        # #Grab the x,y coords
        # (x, y) = (pos.x(), pos.y())
        # #Convert them into lat,lon
        # lon = x_to_longitude(self.zoomlevel, x)
        # lat = y_to_latitude(self.zoomlevel, y)
        #
        # #Determine whether start location has already been decided
        # if self.pressed == False:
        # 	self.start = Vertex(lat, lon)
        # 	self.pressed = True
        # 	self.drawBubble(self.start)
        # else:
        # 	#Once dest has been decided, find shortest path and draw it
        # 	self.dest = Vertex(lat, lon)
        # 	self.pressed = False
        # 	self.drawBubble(self.dest)
        # 	self.controller.passRequest(self.start, self.dest, 1)

    def drawCar(self):
        #Draws the map in place
        self.setCenter()
        self.mapScene.clear()
        self.mapScene.addPixmap(self.pixmaps[self.zoomlevel])
        self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel],
                                   self.sizes[self.zoomlevel])
        (lat, lon) = self.center
        x = ConversionFunctions.longitude_to_x(self.zoomlevel, lon)
        y = ConversionFunctions.latitude_to_y(self.zoomlevel, lat)
        self.mapView.centerOn(x, y)
        #advance_taxi
        UberTaxi.advance_taxi(taxi_directory, cust_directory, g)
        for taxi in taxi_directory.values():
            #gets coords from vertex
            lon = server.coordinates[taxi.loc][1]
            lat = server.coordinates[taxi.loc][0]
            #stored in lat, lon, and then converted
            newx = ConversionFunctions.longitude_to_x(self.zoomlevel, lon)
            newy = ConversionFunctions.latitude_to_y(self.zoomlevel, lat)
            #draws path and car
            self.mapScene.addRect(newx, newy, 15, 10)
            self.mapScene.addEllipse(newx - 2, newy + 10, 6, 6)
            self.mapScene.addEllipse(newx + 11, newy + 10, 6, 6)
            self.drawPath(taxi.path)

    def drawPath(self, path):
        linePen = QPen()
        linePen.setWidth(3)  #Set the width of the line to be noticeable
        for i in range(len(path) - 1):
            lon1 = server.coordinates[path[i]][1]
            lat1 = server.coordinates[path[i]][0]
            lon2 = server.coordinates[path[i + 1]][1]
            lat2 = server.coordinates[path[i + 1]][0]

            self.mapScene.addLine(
                ConversionFunctions.longitude_to_x(self.zoomlevel, lon1),
                ConversionFunctions.latitude_to_y(self.zoomlevel, lat1),
                ConversionFunctions.longitude_to_x(self.zoomlevel, lon2),
                ConversionFunctions.latitude_to_y(self.zoomlevel, lat2),
                linePen)
コード例 #8
0
ファイル: player2.py プロジェクト: zaswed76/sling
class VideoPlayer(QWidget):
    def __init__(self, cfg, playlist, main, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.main = main
        self.playlist = playlist
        self.cfg = cfg
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        self.videoItem = VideoItem()
        self.videoItem.setAspectRatioMode(Qt.KeepAspectRatio)

        width = self.cfg["ui"]["viewCardWidth"]
        height = self.cfg["ui"]["viewCardHeight"]

        scene = QGraphicsScene(self)
        # scene.setSceneRect(0, 0, 838, 610)
        self.graphicsView = QGraphicsView(scene)
        # self.setFixedSize(960, 598)
        # self.graphicsView.mapToScene(28, 28)
        print(self.graphicsView.mapToScene(width, height))
        self.videoItem.setSize(QSizeF(width, height))

        scene.addItem(self.videoItem)

        openButton = QPushButton("Open...")
        openButton.clicked.connect(self.openFile)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.graphicsView)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.mediaPlayer.setVideoOutput(self.videoItem)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

    # def sizeHint(self):
    #     return QSize(800, 600)

    def setFile(self, fileName):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                                                  str(paths.DICTIONARIES))
        if fileName != '':
            self.setFile(fileName)
            self.playButton.setEnabled(True)

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)
コード例 #9
0
ファイル: ZigBee-GUI.py プロジェクト: zzeitt/ZigBee-GUI
class MyWinMap(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.initWidget()  # 初始化组件
        self.initLayout()  # 初始化布局
        self.initWindow(800, 700)  # 初始化窗口
        self.initMap()  # 初始化地图
        self.initSerial(STR_COM)  # 初始化串口
        self.show()

    '''----------------------------------------------'''

    def initWidget(self):
        '''地图显示控件'''
        self.gscene_map = QGraphicsScene()
        self.gview_map = QGraphicsView(self.gscene_map)
        '''设定节点及阈值区'''
        self.chb_mark = QCheckBox('进入标记模式')
        self.chb_mark.toggle()
        self.sp_thre = QSpinBox()
        self.sp_thre.setRange(0, 10)  # 设置上界和下界
        '''数据显示区'''

    def initLayout(self):
        '''箱组声明'''
        self.gpbx_map = QGroupBox('地图', self)
        self.gpbx_mark_and_thre = QGroupBox('设定节点及阈值', self)
        self.gpbx_data = QGroupBox('数据', self)
        '''箱组布局类型'''
        self.lot_v_map = QVBoxLayout()
        self.lot_g_mark_and_thre = QGridLayout()
        self.lot_g_data = QGridLayout()
        self.lot_v_all = QVBoxLayout()
        '''箱组map布局设置'''
        self.lot_v_map.addWidget(self.gview_map, alignment=Qt.AlignHCenter)
        self.gpbx_map.setLayout(self.lot_v_map)
        '''箱组mark and thre布局设置'''
        #  _ __ __ _ _
        # |_|__|__|_|_|
        self.lot_g_mark_and_thre.addWidget(self.chb_mark, 0, 1, 1, 1,
                                           Qt.AlignCenter)
        self.lot_g_mark_and_thre.addWidget(self.sp_thre, 0, 3, 1, 1,
                                           Qt.AlignCenter)
        self.lot_g_mark_and_thre.setColumnStretch(0, 1)
        self.lot_g_mark_and_thre.setColumnStretch(1, 2)
        self.lot_g_mark_and_thre.setColumnStretch(2, 2)
        self.lot_g_mark_and_thre.setColumnStretch(3, 1)
        self.lot_g_mark_and_thre.setColumnStretch(4, 1)
        self.gpbx_mark_and_thre.setLayout(self.lot_g_mark_and_thre)
        '''箱组data布局设置'''
        for i in range(NODE_NUM):
            # 数据框
            le_temp = QLineEdit('*')
            le_temp.setReadOnly(True)
            le_temp.setAlignment(Qt.AlignHCenter)
            self.lot_g_data.addWidget(le_temp, 0, i)
        for i in range(NODE_NUM):
            # 节点号框
            lb_temp = QLabel('<div style="color:#d648ac;"><b>' + str(i + 1) +
                             '</b></div>')
            lb_temp.setAlignment(Qt.AlignCenter)
            self.lot_g_data.addWidget(lb_temp, 1, i)
        self.gpbx_data.setLayout(self.lot_g_data)
        '''总布局设置'''
        self.lot_v_all.addWidget(self.gpbx_map)
        self.lot_v_all.addWidget(self.gpbx_mark_and_thre)
        self.lot_v_all.addWidget(self.gpbx_data)
        self.setLayout(self.lot_v_all)

    def initWindow(self, w, h):
        '''获取屏幕居中点信息'''
        center_point = QDesktopWidget().availableGeometry().center()
        self.center_point_x = center_point.x()
        self.center_point_y = center_point.y()
        '''窗口初始化'''
        self.setGeometry(0, 0, w, h)
        self.max_w = (self.center_point_x - 10) * 2  # 窗口允许的最大宽
        self.max_h = (self.center_point_y - 20) * 2  # 窗口允许的最大高
        self.setMaximumSize(self.max_w, self.max_h)  # 防止窗口尺寸过大
        self.moveToCenter(w, h)
        self.win_name = GUI_NAME  # 窗口标题
        self.setWindowTitle(self.win_name)

    def moveToCenter(self, w, h):
        '''窗口过大则先进行调整'''
        if (w > self.max_w) or (h > self.max_h):
            self.adjustSize()
        '''窗口居中'''
        topleft_point_x = (int)(self.center_point_x - w / 2)
        topleft_point_y = (int)(self.center_point_y - h / 2)
        self.move(topleft_point_x, topleft_point_y)

    def initMap(self):
        try:
            # 地图加载部分
            self.pixmap_map = QPixmap('平面图_走廊_房间.png')
            if self.pixmap_map.isNull():  # 空图处理
                self.initMapErrorHandle()
                return
            self.pixmap_map = self.pixmap_map.scaled(700, 600,
                                                     Qt.KeepAspectRatio,
                                                     Qt.SmoothTransformation)
            self.gscene_map.addPixmap(self.pixmap_map)
            # 固定边界以禁用滑动条
            self.f_pixmap_map_x = float(self.pixmap_map.rect().x())
            self.f_pixmap_map_y = float(self.pixmap_map.rect().y())
            self.f_pixmap_map_w = float(self.pixmap_map.rect().width())
            self.f_pixmap_map_h = float(self.pixmap_map.rect().height())
            self.gview_map.setSceneRect(self.f_pixmap_map_x,
                                        self.f_pixmap_map_y,
                                        self.f_pixmap_map_w,
                                        self.f_pixmap_map_h)
            # 地图加载成功的标志位
            self.b_map_loaded = True
            # 复选框信号连接
            self.chb_mark.stateChanged.connect(self.updateMap)
            # view视图鼠标响应
            self.gview_map.mousePressEvent = self.markMap
            w = self.width()
            h = self.height()
            self.moveToCenter(w, h)
            # 节点相关部分
            self.node_list = []  # 存储节点的坐标及邻域信息
        except Exception as e:
            print(e)
            self.initMapErrorHandle()

    def initMapErrorHandle(self):
        self.b_map_loaded = False
        self.text_warning = '<div style="font:20px;\
                            color:red;\
                            text-align:center;">\
                            <b>⚠ WARNING ⚠</b><br /><br />\
                            地图加载出错啦<br /><br />\
                            ::>﹏<::\
                            </div>'

        self.gtext_warning = QGraphicsTextItem()
        self.gtext_warning.setHtml(self.text_warning)
        self.gscene_map.addItem(self.gtext_warning)

    def markMap(self, event):
        if self.b_map_loaded:
            if self.chb_mark.isChecked():
                self.node_pos = self.gview_map.mapToScene(event.pos())
                # 左键创建标记
                if event.button() == Qt.LeftButton:
                    if len(self.node_list) < NODE_NUM:
                        _is_near_init = False  # 标记模式下,初始化无近邻rssi
                        _append_iter = [self.node_pos,
                                        _is_near_init]  # 用list存储复合信息
                        self.node_list.append(_append_iter)
                        # 绘图部分
                        self.drawNode(len(self.node_list), _append_iter[0],
                                      _append_iter[1])
                # 右键回退标记
                if event.button() == Qt.RightButton:
                    if len(self.node_list) > 0:
                        self.node_list.pop()
                        self.gscene_map.clear()  # 清空scene
                        self.gscene_map.addPixmap(self.pixmap_map)  # 重新加载地图
                        for i in range(len(self.node_list)):
                            self.drawNode(i + 1, self.node_list[i][0],
                                          self.node_list[i][1])

    def updateMap(self):
        if self.b_map_loaded:
            if not self.chb_mark.isChecked():
                self.timer_map_refresh = QTimer(self)  # 设定地图刷新定时器
                self.timer_map_refresh.timeout.connect(self.redrawMap)
                self.timer_map_refresh.start(REFRESH_TIME_MS)  # 设置刷新时间为100毫秒

    def redrawMap(self):
        self.gscene_map.clear()  # 清空scene
        self.gscene_map.addPixmap(self.pixmap_map)  # 重新加载地图
        for i in range(len(self.node_list)):
            self.drawNode(i + 1, self.node_list[i][0], self.node_list[i][1])

    '''----------------------------------------------'''

    def drawNode(self, index, node_pos, is_near):
        # 样式设置
        node_draw_r = 15
        node_draw_x = node_pos.x() - node_draw_r
        node_draw_y = node_pos.y() - node_draw_r
        # node_draw_pos = QPointF(node_draw_x, node_draw_y)
        node_draw_pen = QPen(QColor(204, 47, 105), 3, Qt.SolidLine)
        node_draw_brush = QBrush(QColor(255, 110, 151), Qt.SolidPattern)
        # 正式画圆
        self.gellipse_node = self.gscene_map.addEllipse(
            node_draw_x, node_draw_y, 2 * node_draw_r, 2 * node_draw_r,
            node_draw_pen, node_draw_brush)
        # 索引号
        self.text_index = '<div style=\"font:26px;color:black;font-weight:900;\">' + \
            str(index) + '</div>'
        self.gtext_index = QGraphicsTextItem()
        self.gtext_index.setHtml(self.text_index)
        self.gtext_index.setParentItem(self.gellipse_node)
        self.gtext_index.setPos(node_draw_x + 4, node_draw_y - 2)
        if is_near:  # 若附近rssi判断有效
            node_draw_r = 20
            node_draw_x = node_pos.x() - node_draw_r
            node_draw_y = node_pos.y() - node_draw_r
            node_draw_pen = QPen(QColor(245, 229, 143), 10, Qt.DashLine)
            self.gscene_map.addEllipse(node_draw_x, node_draw_y,
                                       2 * node_draw_r, 2 * node_draw_r,
                                       node_draw_pen)

    '''----------------------------------------------'''

    def initSerial(self, str_com):
        self.data_zigbee_list = []
        # 初始化串口
        self.ser_data = QSerialPort(STR_COM,
                                    baudRate=QSerialPort.Baud115200,
                                    readyRead=self.receive)
        self.ser_data.open(QIODevice.ReadWrite)
        if self.ser_data.isOpen():
            print('串口开启成功!')
        else:
            print('串口打开失败……')

    @pyqtSlot()
    def receive(self):
        _data = self.ser_data.readLine().data()  # 读取数据
        if _data != b'':
            self.data_zigbee_list = []  # 清空数据
            self.data = _data[0:2 * NODE_NUM].decode("gbk")
            # 存储数据
            for i in range(len(self.data) // 2):
                # 每两位存储,用tuple存储,只读
                data_iter = (self.data[2 * i:2 * i + 1],
                             self.data[2 * i + 1:2 * i + 2])
                self.data_zigbee_list.append(data_iter)
            # print('data_zigbee_list:', self.data_zigbee_list)
            self.updateSerial()
        else:
            print('串口接收内容为空!')

    def updateSerial(self):
        if not self.chb_mark.isChecked():
            for i in range(NODE_NUM):
                if i < len(self.node_list):
                    value_update = self.data_zigbee_list[i][1]
                    # 更新节点列表
                    self.node_list[i][1] = (True
                                            if value_update == '1' else False)
                else:
                    value_update = '*'
                self.lot_g_data.itemAt(i).widget().setText(value_update)