def main(argv): app = QApplication(argv) scene = QGraphicsScene(0, 0, 500, 500) scene.setItemIndexMethod(QGraphicsScene.NoIndex) brush = QBrush(Qt.red) brush_brics = QBrush(QPixmap('brick_texture.jpg')) brush_brics.setStyle(Qt.TexturePattern) pen = QPen() pen.setWidth(5) pen.setStyle(Qt.DashLine) rectItem = RectItem('r1', 20, 10, 200, 100) rectItem.setBrush(brush) rectItem2 = RectItem('r2', 20, 10, 150, 250) rectItem2.setPen(pen) rectItem2.setBrush(brush_brics) rectItem2.setOpacity(70) arrowItem = ArrowItem(QLine(50, 200, 300, 400)) scene.addItem(arrowItem) scene.addItem(rectItem) scene.addItem(rectItem2) view = QGraphicsView(scene) view.show() return app.exec_()
def __init__(self, main_window, parent_script, config=None): super(Flow, self).__init__() # SHORTCUTS place_new_node_shortcut = QShortcut(QKeySequence('Shift+P'), self) place_new_node_shortcut.activated.connect( self.place_new_node_by_shortcut) move_selected_nodes_left_shortcut = QShortcut( QKeySequence('Shift+Left'), self) move_selected_nodes_left_shortcut.activated.connect( self.move_selected_nodes_left) move_selected_nodes_up_shortcut = QShortcut(QKeySequence('Shift+Up'), self) move_selected_nodes_up_shortcut.activated.connect( self.move_selected_nodes_up) move_selected_nodes_right_shortcut = QShortcut( QKeySequence('Shift+Right'), self) move_selected_nodes_right_shortcut.activated.connect( self.move_selected_nodes_right) move_selected_nodes_down_shortcut = QShortcut( QKeySequence('Shift+Down'), self) move_selected_nodes_down_shortcut.activated.connect( self.move_selected_nodes_down) select_all_shortcut = QShortcut(QKeySequence('Ctrl+A'), self) select_all_shortcut.activated.connect(self.select_all) copy_shortcut = QShortcut(QKeySequence.Copy, self) copy_shortcut.activated.connect(self.copy) cut_shortcut = QShortcut(QKeySequence.Cut, self) cut_shortcut.activated.connect(self.cut) paste_shortcut = QShortcut(QKeySequence.Paste, self) paste_shortcut.activated.connect(self.paste) # UNDO/REDO self.undo_stack = QUndoStack(self) self.undo_action = self.undo_stack.createUndoAction(self, 'undo') self.undo_action.setShortcuts(QKeySequence.Undo) self.redo_action = self.undo_stack.createRedoAction(self, 'redo') self.redo_action.setShortcuts(QKeySequence.Redo) undo_shortcut = QShortcut(QKeySequence.Undo, self) undo_shortcut.activated.connect(self.undo_activated) redo_shortcut = QShortcut(QKeySequence.Redo, self) redo_shortcut.activated.connect(self.redo_activated) # GENERAL ATTRIBUTES self.parent_script = parent_script self.all_node_instances: [NodeInstance] = [] self.all_node_instance_classes = main_window.all_node_instance_classes # ref self.all_nodes = main_window.all_nodes # ref self.gate_selected: PortInstanceGate = None self.dragging_connection = False self.ignore_mouse_event = False # for stylus - see tablet event self.last_mouse_move_pos: QPointF = None self.node_place_pos = QPointF() self.left_mouse_pressed_in_flow = False self.mouse_press_pos: QPointF = None self.tablet_press_pos: QPointF = None self.auto_connection_gate = None # stores the gate that we may try to auto connect to a newly placed NI self.panning = False self.pan_last_x = None self.pan_last_y = None self.current_scale = 1 self.total_scale_div = 1 # SETTINGS self.algorithm_mode = Flow_AlgorithmMode() self.viewport_update_mode = Flow_ViewportUpdateMode() # CREATE UI scene = QGraphicsScene(self) scene.setItemIndexMethod(QGraphicsScene.NoIndex) scene.setSceneRect(0, 0, 10 * self.width(), 10 * self.height()) self.setScene(scene) self.setCacheMode(QGraphicsView.CacheBackground) self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate) self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setDragMode(QGraphicsView.RubberBandDrag) scene.selectionChanged.connect(self.selection_changed) self.setAcceptDrops(True) self.centerOn( QPointF(self.viewport().width() / 2, self.viewport().height() / 2)) # NODE CHOICE WIDGET self.node_choice_proxy = FlowProxyWidget(self) self.node_choice_proxy.setZValue(1000) self.node_choice_widget = NodeChoiceWidget( self, main_window.all_nodes) # , main_window.node_images) self.node_choice_proxy.setWidget(self.node_choice_widget) self.scene().addItem(self.node_choice_proxy) self.hide_node_choice_widget() # ZOOM WIDGET self.zoom_proxy = FlowProxyWidget(self) self.zoom_proxy.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self.zoom_proxy.setZValue(1001) self.zoom_widget = FlowZoomWidget(self) self.zoom_proxy.setWidget(self.zoom_widget) self.scene().addItem(self.zoom_proxy) self.set_zoom_proxy_pos() # STYLUS self.stylus_mode = '' self.current_drawing = None self.drawing = False self.drawings = [] self.stylus_modes_proxy = FlowProxyWidget(self) self.stylus_modes_proxy.setFlag( QGraphicsItem.ItemIgnoresTransformations, True) self.stylus_modes_proxy.setZValue(1001) self.stylus_modes_widget = FlowStylusModesWidget(self) self.stylus_modes_proxy.setWidget(self.stylus_modes_widget) self.scene().addItem(self.stylus_modes_proxy) self.set_stylus_proxy_pos() self.setAttribute(Qt.WA_TabletTracking) # DESIGN THEME Design.flow_theme_changed.connect(self.theme_changed) if config: config: dict # algorithm mode if config.keys().__contains__('algorithm mode'): if config['algorithm mode'] == 'data flow': self.parent_script.widget.ui.algorithm_data_flow_radioButton.setChecked( True) self.algorithm_mode.mode_data_flow = True else: # 'exec flow' self.parent_script.widget.ui.algorithm_exec_flow_radioButton.setChecked( True) self.algorithm_mode.mode_data_flow = False # viewport update mode if config.keys().__contains__('viewport update mode'): if config['viewport update mode'] == 'sync': self.parent_script.widget.ui.viewport_update_mode_sync_radioButton.setChecked( True) self.viewport_update_mode.sync = True else: # 'async' self.parent_script.widget.ui.viewport_update_mode_async_radioButton.setChecked( True) self.viewport_update_mode.sync = False node_instances = self.place_nodes_from_config(config['nodes']) self.connect_nodes_from_config(node_instances, config['connections']) if list(config.keys()).__contains__( 'drawings' ): # not all (old) project files have drawings arr self.place_drawings_from_config(config['drawings']) self.undo_stack.clear()
class AbstractGraphicViewer(QGraphicsView, TcWidget): def __init__(self, parent=None): super(AbstractGraphicViewer, self).__init__(parent) self.m_scaleX = 0 self.m_scaleY = 0 self._pan = False self._panStartX = 0 self._panStartY = 0 self.scene = QGraphicsScene() self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(-2000, -2000, 4000, 4000) self.setScene(self.scene) self.setCacheMode(QGraphicsView.CacheBackground) self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate) self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setMinimumSize(400, 400) self.adjustSize() self.setMouseTracking(True) self.viewport().setMouseTracking(True) def wheelEvent(self, event): if event.angleDelta().y() > 0: factor = 1.1 else: factor = 0.9 view_pos = event.pos() scene_pos = self.mapToScene(view_pos) self.centerOn(scene_pos) self.scale(factor, factor) delta = self.mapToScene(view_pos) - self.mapToScene(self.viewport().rect().center()) self.centerOn(scene_pos - delta) def resizeEvent(self, event): super(AbstractGraphicViewer, self).resizeEvent(event) def mouseMoveEvent(self, event): if self._pan: self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - (event.x() - self._panStartX)) self.verticalScrollBar().setValue(self.verticalScrollBar().value() - (event.y() - self._panStartY)) self._panStartX = event.x() self._panStartY = event.y() event.accept() super(AbstractGraphicViewer, self).mouseMoveEvent(event) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self._pan = True self._panStartX = event.x() self._panStartY = event.y() self.setCursor(QCursor.ClosedHandCursor) event.accept() return super(AbstractGraphicViewer, self).mousePressEvent(event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self._pan = False self.setCursor(QCursor.ArrowCursor) event.accept() super(AbstractGraphicViewer, self).mouseReleaseEvent(event) def showEvent(self, event): super(AbstractGraphicViewer, self).showEvent(event) adjusted = self.scene.itemsBoundingRect().adjusted(-100, -100, 100, 100) self.scene.setSceneRect(adjusted) # FitInView is called two times because of this bug: https://bugreports.qt.io/browse/QTBUG-1047 update_state = self.updatesEnabled() self.setUpdatesEnabled(False) self.fitInView(adjusted, Qt.KeepAspectRatio) QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) self.fitInView(adjusted, Qt.KeepAspectRatio) self.setUpdatesEnabled(update_state)