def __init__(self, tileSource, parent=None): """Constructor. Args: tileSource(MapTileSource): Source for loading the tiles. parent(QObject): Parent object, default `None` """ QGraphicsScene.__init__(self, parent=parent) self._zoom = 15 self._tileSource = tileSource self._tileSource.setParent(self) self._tileSource.tileReceived.connect(self.setTilePixmap) tdim = self._tileSource.tileSize() self._emptyTile = QPixmap(tdim, tdim) self._emptyTile.fill(Qt.lightGray) self._tilesRect = QRect() self._tilePixmaps = {} self._tileInDownload = list() self.setSceneRect(0.0, 0.0, 400, 300) self.sceneRectChanged.connect(self.onSceneRectChanged)
class BlockDiagramEditorView(QWidget): _size = 1_000 def __init__(self): super().__init__() self.labeledSlider = VLabeledSlider() self._qscene = QGraphicsScene() self._qscene.setSceneRect(-self._size / 2, -self._size / 2, self._size, self._size) self._qview = BlockDiagramView(scene=self._qscene, parent=self) layout = QHBoxLayout() layout.addWidget(self.labeledSlider, 0) layout.addWidget(self._qview, 1) layout.setAlignment(Qt.AlignCenter) self.widgetLayout = layout groupBox = QGroupBox() groupBox.setTitle("Block diagram") groupBox.setLayout(layout) parentLayout = QVBoxLayout() parentLayout.addWidget(groupBox) self.setLayout(parentLayout)
def __init__(self, registry=None, style=None, parent=None, allow_node_creation=True, allow_node_deletion=True): ''' Create a new flow scene Parameters ---------- registry : DataModelRegistry, optional style : StyleCollection, optional parent : QObject, optional ''' # Note: PySide2 does not support a cooperative __init__, meaning we # cannot use super().__init__ here. # super().__init__(registry=registry, parent=parent) QGraphicsScene.__init__(self, parent=parent) _FlowSceneModel.__init__(self, registry=registry) if style is None: style = style_module.default_style self._style = style self.allow_node_deletion = allow_node_creation self.allow_node_creation = allow_node_deletion self.setItemIndexMethod(QGraphicsScene.NoIndex)
def __init__(self, appdata: CnaData, name: str): self.scene = QGraphicsScene() QGraphicsView.__init__(self, self.scene) palette = self.palette() palette.setColor(QPalette.Base, Qt.white) self.setPalette(palette) self.appdata = appdata self.name = name self.setAcceptDrops(True) self.drag = False self.reaction_boxes: Dict[str, ReactionBox] = {} self._zoom = 0 self.drag = False self.drag_start = None # initial scale self._zoom = self.appdata.project.maps[self.name]["zoom"] if self._zoom > 0: for _ in range(1, self._zoom): self.scale(INCREASE_FACTOR, INCREASE_FACTOR) if self._zoom < 0: for _ in range(self._zoom, -1): self.scale(DECREASE_FACTOR, DECREASE_FACTOR) # connect events to methods self.horizontalScrollBar().valueChanged.connect(self.on_hbar_change) self.verticalScrollBar().valueChanged.connect(self.on_vbar_change)
def __init__(self, camera, **settings): super(CroppableCameraView, self).__init__() self.setRenderHint(QPainter.Antialiasing) self.cam = camera self.is_live = False self._cmin = 0 self._cmax = None self.settings = settings self._selecting = False self.needs_resize = False self.latest_array = None self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() #self.setFrameStyle(QFrame.NoFrame) self.setScene(self.scene) self.pixmapitem = self.scene.addPixmap(QPixmap()) self._uncropped_pixmap = None self.setMouseTracking(True) self.start = None c1 = QColor(0, 100, 220, 150) self.c2 = QColor(0, 100, 220, 50) self.c3 = QColor(0, 100, 220, 0) pen = QPen(c1, 2) self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3) self.selrect.setZValue(100) self.selrect.hide()
def showImage(self, posterPath: str): self.removeImage() imgData = requests.get(self.__poster_url__ + posterPath) pix = QPixmap() pix.loadFromData(imgData.content) item = QGraphicsPixmapItem(pix) self.__scene__ = QGraphicsScene(self) self.__scene__.addItem(item) self.ui.graphicsView.setScene(self.__scene__) self.resizeImage()
def __init__(self, **kwargs): super(GraphicsView, self).__init__(**kwargs) self._scene = QGraphicsScene(parent=self) self.current_image = QGraphicsPixmapItem() self._scene.addItem(self.current_image) self.setScene(self._scene) self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setMouseTracking(True) self.setRenderHint(QPainter.Antialiasing)
def mousePressEvent(self, evt): '''Catch right-click events for rectangle drawing''' if self.rubberband_enabled and evt.button() == 2: evt.accept() pos = evt.scenePos() self.rect_start = pos if self.rubberband != None: self.removeItem(self.rubberband) self.rubberband = None else: evt.ignore() QGraphicsScene.mousePressEvent(self, evt)
def __init__(self, parent=None): super(GraphicsView, self).__init__(parent) self.scene = QGraphicsScene() self.pixmapItem = QGraphicsPixmapItem() self.scene.setSceneRect(0, 0, 500, 500) self.setScene(self.scene) self.scene.addItem(self.pixmapItem) #would eventually make this fit to size of screen, waiting cause it's annoying. self.buildingParams = [] self.scalef = [1, 1] self.Buildings()
def mouseReleaseEvent(self, evt): '''Catch right-click events for rectangle drawing''' if self.rubberband_enabled and evt.button() == 2: evt.accept() pos = evt.scenePos() lon0, lat0 = self.lonLatFromPos(self.rect_start.x(), self.rect_start.y()) lon1, lat1 = self.lonLatFromPos(pos.x(), pos.y()) self.removeItem(self.rubberband) self.rect_start = None self.rect_end = None self.rubberband = None self.sigSelectionDrawn.emit(lon0, lat0, lon1, lat1) else: evt.ignore() QGraphicsScene.mouseReleaseEvent(self, evt)
def __init__(self, parent=None): super(DataGraphWidget, self).__init__(parent=parent) # Set up scene self.scene = QGraphicsScene(self) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(0, 0, 800, 300) self.setScene(self.scene) self.setWindowTitle("Glue data graph") self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) self.selection_level = 0
def setup_gfx_ui(): # design overview self.motor_display_view = QGraphicsView() self.motor_display_scene = QGraphicsScene() self.motor_display_view.setScene(self.motor_display_scene) self.motor_display_view.show() # sliced cross section self.grain_slice_view = QGraphicsView() self.grain_slice_scene = QGraphicsScene() self.grain_slice_view.setScene(self.grain_slice_scene) self.grain_slice_view.show() # splitter self.splt_gfx = QSplitter(Qt.Horizontal) self.splt_gfx.addWidget(self.motor_display_view) self.splt_gfx.addWidget(self.grain_slice_view) self.splt_gfx.setStretchFactor(0, 10) self.splt_gfx.setStretchFactor(1, 3) self.splt_gfx.setMinimumHeight(50)
def __init__(self, item) -> None: QGraphicsView.__init__(self) scene = QGraphicsScene(self) self.setScene(scene) item.setMinimumSize(QSize(150, 150)) item.setMaximum(36000) item.setSingleStep(100) item.setPageStep(100) item.setInvertedAppearance(True) item.setWrapping(True) item.setNotchTarget(.1) item.setNotchesVisible(True) graphics_item = scene.addWidget(item) graphics_item.setRotation(-90) # make the QGraphicsView invisible. self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFixedHeight(item.height()) self.setFixedWidth(item.width()) self.setStyleSheet("border: 0px;")
class GraphicsView(QGraphicsView): def __init__(self, **kwargs): super(GraphicsView, self).__init__(**kwargs) self._scene = QGraphicsScene(parent=self) self.current_image = QGraphicsPixmapItem() self._scene.addItem(self.current_image) self.setScene(self._scene) self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setMouseTracking(True) self.setRenderHint(QPainter.Antialiasing) def update_image(self, img: np.ndarray): rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w qimg = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qimg) self.current_image.setPixmap(pixmap) self._scene.setSceneRect(0, 0, w, h) self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio) def resizeEvent(self, e): self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio) def wheelEvent(self, e): if e.angleDelta().y() > 0: self.scale(1.25, 1.25) elif e.angleDelta().y() < 0: self.scale(0.85, 0.85) def mousePressEvent(self, e): # シーン上のマウス位置を取得する pos = self.mapToScene(e.pos()) if e.button() == Qt.LeftButton: if e.modifiers() == Qt.NoModifier: pass elif e.modifiers() == Qt.AltModifier: self.setDragMode(QGraphicsView.ScrollHandDrag) QGraphicsView.mousePressEvent(self, e) def mouseReleaseEvent(self, e): QGraphicsView.mouseReleaseEvent(self, e) if e.button() == Qt.LeftButton: self.setDragMode(QGraphicsView.NoDrag) def calc_offset(self, p: QPoint): offset_x = p.x() - int(self.viewport().width() / 2) offset_y = p.y() - int(self.viewport().height() / 2) return QPoint(offset_x, offset_y)
def __init__(self, parent: QWidget): super(QRotatableView, self).__init__(parent) scene = QGraphicsScene(self) self.setScene(scene) self.dial = QDial() self.dial.setMinimumSize(QSize(150, 150)) self.dial.setSingleStep(100) self.dial.setPageStep(100) self.dial.setInvertedAppearance(True) self.dial.setWrapping(True) self.dial.setNotchTarget(0.1) self.dial.setNotchesVisible(True) self.dial.valueChanged.connect(self.__value_changed) self.set_maximum(360) graphics_item = scene.addWidget(self.dial) graphics_item.setRotation(-90) # make the QGraphicsView invisible. self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFixedHeight(self.dial.height()) self.setFixedWidth(self.dial.width()) self.setStyleSheet("border: 0px;")
def __init__(self, parent=None): super(SvgView, self).__init__(parent) self.signal = NodeSignal() self.renderer = SvgView.Native self.__svg_items = [] self.__wrapper_item = None self.__svg_renderer = QSvgRenderer() self.setScene(QGraphicsScene(self)) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) self.setViewport(QWidget()) self.setBackgroundBrush( QBrush(QColor(QPalette().color(QPalette.Active, QPalette.Window))))
def __init__(self, width, height, pixel_ratio, path): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # overwrite dimesions specified in slideShow3.py, as they are specific to MacBookPro display, and QTDesigner # has its own idea on what they should be. This code should work on any size display self.resize(width, height) self.ui.graphicsView.setGeometry(QtCore.QRect(0, 0, width, height)) self.ui.menubar.setGeometry(QtCore.QRect(0, 0, width, 0)) self.width = width self.height = height self.pixel_ratio = pixel_ratio self.path = path self.imageFiles = [] self.slideIndex = -1 self.random_index_number = 0 self.random = "" self.imageFiles, self.random_index, self.path, self.max_index = self.getImageNames2( ) self.helpFile = os.path.join( os.path.dirname(os.path.realpath(sys.argv[0])), "instructions.png") #print(self.helpFile) self.scene = QGraphicsScene(self) #self.scene.setAlignment(QtCore.Qt.AlignCenter) self.ui.actionDir.triggered.connect(self.openFileNameDialog) self.ui.actionStart_Slide_Show.triggered.connect(self.slide_show) self.ui.actionRandom_Slide_Show.triggered.connect( self.random_slide_show) eventFilter = MouseEventFilter(self.scene) self.scene.installEventFilter(eventFilter) self.ui.actionHelp.triggered.connect(self.helpWindow) #self.show() self.showFullScreen()
def __init__(self, parent=None): super(TestWidgetItem, self).__init__(parent) scene = QGraphicsScene() self.setScene(scene) self.line_item = LineItem() self.line_item.setLine(0, 0, 10, 10) self.line_item2 = LineItem() self.line_item2.setLine(30, 30, 40, 40) self.circle_item = CenterManipulatorItem() self.circle_item.setRect(10, 10, 50, 50) self.text_item = TextItem() self.scene().addItem(self.text_item) self.scene().addItem(self.circle_item) self.scene().addItem(self.line_item) self.scene().addItem(self.line_item2) self.scene().setSceneRect(0,0,100,100) self.setMouseTracking(True)
def __init__(self, item): super().__init__() self._shown = False self.modified_callback = None scene = QGraphicsScene() self.scene = scene self.scene_item = item scene.addItem(item) layout = QBoxLayout(QBoxLayout.TopToBottom, self) scene_view = View(self) self.scene_view = scene_view scene_view.setScene(scene) scene_view.setMinimumSize(350, 350) scene_view.setRenderHint(QPainter.Antialiasing) layout.addWidget(scene_view) self.double_click_callback = None self.mouse_press_callback = None if hasattr(self.scene_item, "mouse_pressed_in"): self.mouse_press_callback = self.scene_item.mouse_pressed_in if hasattr(self.scene_item, "double_clicked_in_background"): self.double_click_callback = \ self.scene_item.double_clicked_in_background if hasattr(self.scene_item, "mouse_moved_in_scene"): self.scene_view.mouse_move_callback = \ self.scene_item.mouse_moved_in_scene self.menus = [] view_menu = QMenu("&View") self.view_menu = view_menu self.menus.append(view_menu) export_menu = QMenu("&Export") self.menus.append(export_menu) self.tools = [] fit_action = QAction("&Fit", self) fit_action.setShortcut("0") fit_action.setIcon(QIcon.fromTheme("zoom-fit-best")) fit_action.setStatusTip("Fit the entire scene to the viewport") fit_action.triggered.connect(self.scene_view.fit_all_in_view) view_menu.addAction(fit_action) self.tools.append(fit_action) reset_action = QAction("&Reset (1:1)", self) reset_action.setShortcut("9") reset_action.setIcon(QIcon.fromTheme("zoom-original")) reset_action.setStatusTip("Reset the view to 100% scale") reset_action.triggered.connect(self.scene_view.reset_scale) view_menu.addAction(reset_action) self.tools.append(reset_action) zoom_in_action = QAction("Zoom &In", self) zoom_in_action.setShortcuts(["+", "="]) zoom_in_action.setStatusTip("Zoom in") zoom_in_action.triggered.connect(lambda: self.scene_view.zoom_in()) view_menu.addAction(zoom_in_action) zoom_out_action = QAction("Zoom &Out", self) zoom_out_action.setShortcuts(["-", "_"]) zoom_out_action.setStatusTip("Zoom out") zoom_out_action.triggered.connect(lambda: self.scene_view.zoom_out()) view_menu.addAction(zoom_out_action) export_svg_action = QAction("As &SVG...", self) export_svg_action.setStatusTip("Export the current tab as an SVG file") export_svg_action.triggered.connect(lambda: export_as_svg(self.scene)) export_menu.addAction(export_svg_action) export_png_action = QAction("As PN&G...", self) export_png_action.setStatusTip("Export the current tab as an PNG file") export_png_action.triggered.connect(lambda: export_as_png(self.scene)) export_menu.addAction(export_png_action) export_pdf_action = QAction("As &PDF...", self) export_pdf_action.setStatusTip("Export the current tab as an PDF file") export_pdf_action.triggered.connect(lambda: export_as_pdf(self.scene)) export_menu.addAction(export_pdf_action) export_svg_clip_action = QAction("To Clipboard as SVG", self) export_svg_clip_action.setStatusTip( "Export the current tab to the clipoard in SVG format") export_svg_clip_action.triggered.connect( lambda: export_to_clipboard_as_svg(self.scene)) export_menu.addAction(export_svg_clip_action) export_image_clip_action = QAction("To &Clipboard as Image", self) export_image_clip_action.setStatusTip( "Export the current tab to the clipoard as an image") export_image_clip_action.triggered.connect( lambda: export_to_clipboard_as_image(self.scene)) export_menu.addAction(export_image_clip_action) self.resize(800, 600)
class MyForm(QMainWindow): def __init__(self, width, height, pixel_ratio, path): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # overwrite dimesions specified in slideShow3.py, as they are specific to MacBookPro display, and QTDesigner # has its own idea on what they should be. This code should work on any size display self.resize(width, height) self.ui.graphicsView.setGeometry(QtCore.QRect(0, 0, width, height)) self.ui.menubar.setGeometry(QtCore.QRect(0, 0, width, 0)) self.width = width self.height = height self.pixel_ratio = pixel_ratio self.path = path self.imageFiles = [] self.slideIndex = -1 self.random_index_number = 0 self.random = "" self.imageFiles, self.random_index, self.path, self.max_index = self.getImageNames2( ) self.helpFile = os.path.join( os.path.dirname(os.path.realpath(sys.argv[0])), "instructions.png") #print(self.helpFile) self.scene = QGraphicsScene(self) #self.scene.setAlignment(QtCore.Qt.AlignCenter) self.ui.actionDir.triggered.connect(self.openFileNameDialog) self.ui.actionStart_Slide_Show.triggered.connect(self.slide_show) self.ui.actionRandom_Slide_Show.triggered.connect( self.random_slide_show) eventFilter = MouseEventFilter(self.scene) self.scene.installEventFilter(eventFilter) self.ui.actionHelp.triggered.connect(self.helpWindow) #self.show() self.showFullScreen() extension = staticmethod(lambda f: f.split('.').pop().lower()) filename = staticmethod(lambda f: f.split('/').pop()) def openFileNameDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog self.fileName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", "All Files (*);;Python Files (*.py)", options=options) if self.fileName: self.path = os.path.dirname(self.fileName) self.imageFiles = [] self.random_index = [] self.max_index = [] self.imageFiles, self.random_index, self.path, self.max_index = self.getImageNames2( ) self.slideIndex = self.imageFiles.index(self.fileName) - 1 def getImageNames2(self): "get the names of all images on disc or from the web (which are cached locally)" if not self.path: self.path = os.getcwd() if self.path[-1] != '/': self.path += '/' try: os.listdir(self.path) except: error_dialog = QtWidgets.QErrorMessage() error_dialog.showMessage( 'Error in path' + self.path ) # https://stackoverflow.com/questions/40227047/python-pyqt5-how-to-show-an-error-message-with-pyqt5 return [], self.path for i in GlobDirectoryWalker(self.path, "*.*"): if os.path.isfile(i): if self.checkImageType(i): self.imageFiles.append(i) max_index = len(self.imageFiles) - 1 self.imageFiles.sort() random_index = list(range(max_index + 1)) random.shuffle(random_index) return self.imageFiles, random_index, self.path, max_index def slide(self, i): self.pixmap = QtGui.QPixmap() #self.pixmap.setAlignment(QtCore.Qt.AlignCenter) self.pixmap.load(self.imageFiles[i]) self.pixmap.setDevicePixelRatio( self.pixel_ratio ) # https://stackoverflow.com/questions/50127246/pyqt-5-10-enabling-high-dpi-support-for-macos-poor-pixmap-quality #self.pixmap4 = self.pixmap.scaled(self.width * self.pixel_ratio, (self.height * self.pixel_ratio)-45, Qt.KeepAspectRatio) self.pixmap4 = self.pixmap.scaled(self.width * self.pixel_ratio, (self.height * self.pixel_ratio), Qt.KeepAspectRatio) try: self.scene.removeItem(self.item) except: print("failed to remove item") self.item = QGraphicsPixmapItem(self.pixmap4) self.scene.addItem(self.item) #myapp.setWindowTitle(os.path.basename(self.imageFiles[i])) self.setWindowTitle(os.path.basename(self.imageFiles[i])) self.ui.graphicsView.setScene(self.scene) def slide_show(self): self.random = 0 self.next_slide() def random_slide_show(self): self.random = 1 self.next_slide() def next_slide(self): if self.random == 0: self.increment_slide() else: self.random_next() def prev_slide(self): if self.random == 0: self.decrement_slide() else: self.random_prev() def random_next(self): "display the next random slide" self.random_index_number += 1 try: self.slideIndex = self.random_index[self.random_index_number] self.slide(self.slideIndex) except IndexError: self.random_index_number = 0 self.slideIndex = self.random_index[self.random_index_number] self.slide(self.slideIndex) return False def random_prev(self): "display the previous random slide" self.random_index_number -= 1 #self.ImageWindow.clear() try: self.slideIndex = self.random_index[self.random_index_number] self.slide(self.slideIndex) except IndexError: self.random_index_number = self.max_index self.slideIndex = self.random_index[self.random_index_number] self.slide(self.slideIndex) return False def increment_slide(self): "display a higher slide" print("in increment_slide") self.slideIndex += 1 if self.slideIndex > self.max_index: self.slideIndex = 0 print('Max index hit') self.slide(self.slideIndex) return False def decrement_slide(self): "display a lower slide" self.slideIndex -= 1 if self.slideIndex < 0: self.slideIndex = self.max_index self.slide(self.slideIndex) return False def checkImageType(self, f): "check to see if we have an file with an image extension" ext = self.extension(f) chk = [ i for i in ['jpg', 'gif', 'ppm', 'tif', 'png', 'jpeg'] if i == ext ] if chk == []: return False return True def helpWindow(self): self.pixmap = QtGui.QPixmap() #self.pixmap.setAlignment(QtCore.Qt.AlignCenter) self.pixmap.load(self.helpFile) self.pixmap.setDevicePixelRatio( self.pixel_ratio ) # https://stackoverflow.com/questions/50127246/pyqt-5-10-enabling-high-dpi-support-for-macos-poor-pixmap-quality #self.pixmap4 = self.pixmap.scaled(self.width * self.pixel_ratio, (self.height * self.pixel_ratio)-45, Qt.KeepAspectRatio) self.pixmap4 = self.pixmap.scaled(self.width * self.pixel_ratio, (self.height * self.pixel_ratio), Qt.KeepAspectRatio) try: self.scene.removeItem(self.item) except: print("failed to remove item") self.item = QGraphicsPixmapItem(self.pixmap4) self.scene.addItem(self.item) #myapp.setWindowTitle(os.path.basename("Instructions")) self.setWindowTitle(os.path.basename("Instructions")) self.ui.graphicsView.setScene(self.scene) def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.Quit() if e.key() == Qt.Key_Q: self.Quit() if e.key() == Qt.Key_Space: self.next_slide() if e.key() == Qt.Key_N: self.random_next() if e.key() == Qt.Key_P: self.random_prev() if e.key() == Qt.Key_Comma: self.decrement_slide() if e.key() == Qt.Key_Period: self.increment_slide() if e.key() == Qt.Key_H: self.helpWindow = self.helpWindow() if e.key() == Qt.Key_BracketLeft: self.slideIndex = self.decrement_slide() def mousePressEvent(self, e): if e.button() == QtCore.Qt.LeftButton: print("trapped left mouse click") self.next_slide() if e.button() == QtCore.Qt.RightButton: print("trapped right mouse click") self.prev_slide() def Quit(self): sys.exit(app.exec_())
class MapView(QGraphicsView): """A map of reaction boxes""" def __init__(self, appdata: CnaData, name: str): self.scene = QGraphicsScene() QGraphicsView.__init__(self, self.scene) palette = self.palette() palette.setColor(QPalette.Base, Qt.white) self.setPalette(palette) self.appdata = appdata self.name = name self.setAcceptDrops(True) self.drag = False self.reaction_boxes: Dict[str, ReactionBox] = {} self._zoom = 0 self.drag = False self.drag_start = None # initial scale self._zoom = self.appdata.project.maps[self.name]["zoom"] if self._zoom > 0: for _ in range(1, self._zoom): self.scale(INCREASE_FACTOR, INCREASE_FACTOR) if self._zoom < 0: for _ in range(self._zoom, -1): self.scale(DECREASE_FACTOR, DECREASE_FACTOR) # connect events to methods self.horizontalScrollBar().valueChanged.connect(self.on_hbar_change) self.verticalScrollBar().valueChanged.connect(self.on_vbar_change) def on_hbar_change(self, x): self.appdata.project.maps[self.name]["pos"] = ( x, self.verticalScrollBar().value()) def on_vbar_change(self, y): self.appdata.project.maps[self.name]["pos"] = ( self.horizontalScrollBar().value(), y) def dragEnterEvent(self, event: QGraphicsSceneDragDropEvent): event.setAccepted(True) event.accept() event.acceptProposedAction() def dragMoveEvent(self, event: QGraphicsSceneDragDropEvent): event.setAccepted(True) point = event.pos() point_item = self.mapToScene(point) r_id = event.mimeData().text() if r_id in self.appdata.project.maps[self.name]["boxes"].keys(): self.appdata.project.maps[self.name]["boxes"][r_id] = ( point_item.x(), point_item.y()) self.mapChanged.emit(r_id) else: self.appdata.project.maps[self.name]["boxes"][r_id] = ( point_item.x(), point_item.y()) self.reactionAdded.emit(r_id) self.update() def dragLeaveEvent(self, _event): self.update() def dropEvent(self, event: QGraphicsSceneDragDropEvent): self.drag = False point = event.pos() point_item = self.mapToScene(point) identifier = event.mimeData().text() self.appdata.project.maps[self.name]["boxes"][identifier] = ( point_item.x(), point_item.y()) self.mapChanged.emit(identifier) self.update() def wheelEvent(self, event): modifiers = QApplication.queryKeyboardModifiers() if modifiers == Qt.ControlModifier: if event.angleDelta().y() > 0: self.appdata.project.maps[ self.name]["bg-size"] *= INCREASE_FACTOR else: self.appdata.project.maps[ self.name]["bg-size"] *= DECREASE_FACTOR self.mapChanged.emit("dummy") self.update() if event.angleDelta().y() > 0: self.zoom_in() else: self.zoom_out() def fit(self): self.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio) def zoom_in(self): self._zoom += 1 self.appdata.project.maps[self.name]["zoom"] = self._zoom self.scale(INCREASE_FACTOR, INCREASE_FACTOR) def zoom_out(self): self._zoom -= 1 self.appdata.project.maps[self.name]["zoom"] = self._zoom self.scale(DECREASE_FACTOR, DECREASE_FACTOR) def mousePressEvent(self, event: QMouseEvent): self.drag = True self.drag_start = event.pos() super(MapView, self).mousePressEvent(event) def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent): modifiers = QApplication.queryKeyboardModifiers() if modifiers == Qt.ControlModifier: if self.drag: point = event.pos() move_x = self.drag_start.x() - point.x() move_y = self.drag_start.y() - point.y() self.drag_start = point for key, val in self.appdata.project.maps[ self.name]["boxes"].items(): self.appdata.project.maps[self.name]["boxes"][key] = ( val[0] - move_x, val[1] - move_y) self.mapChanged.emit("dummy") self.update() else: if self.drag: self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.translate(1, 1) super(MapView, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event: QMouseEvent): if self.drag: self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.translate(1, 1) self.drag = False super(MapView, self).mouseReleaseEvent(event) def update_selected(self, string): for r_id in self.reaction_boxes: if string.lower() in r_id.lower(): self.reaction_boxes[r_id].item.setHidden(False) elif string.lower() in self.reaction_boxes[r_id].name.lower(): self.reaction_boxes[r_id].item.setHidden(False) else: self.reaction_boxes[r_id].item.setHidden(True) def focus_reaction(self, reaction: str): x = self.appdata.project.maps[self.name]["boxes"][reaction][0] y = self.appdata.project.maps[self.name]["boxes"][reaction][1] self.centerOn(x, y) def highlight_reaction(self, string): # hide other boxes # for id in self.reaction_boxes: # self.reaction_boxes[id].item.setHidden(True) treffer = self.reaction_boxes[string] treffer.item.setHidden(False) treffer.set_color(Qt.magenta) def update(self): self.scene.clear() background = QGraphicsSvgItem( self.appdata.project.maps[self.name]["background"]) background.setFlags(QGraphicsItem.ItemClipsToShape) background.setScale(self.appdata.project.maps[self.name]["bg-size"]) self.scene.addItem(background) for r_id in self.appdata.project.maps[self.name]["boxes"]: try: name = self.appdata.project.cobra_py_model.reactions.get_by_id( r_id).name box = ReactionBox(self, r_id, name) box.setPos( self.appdata.project.maps[self.name]["boxes"][r_id][0], self.appdata.project.maps[self.name]["boxes"][r_id][1]) self.scene.addItem(box) self.reaction_boxes[r_id] = box except KeyError: print("failed to add reaction box for", r_id) self.set_values() # set scrollbars self.horizontalScrollBar().setValue( self.appdata.project.maps[self.name]["pos"][0]) self.verticalScrollBar().setValue( self.appdata.project.maps[self.name]["pos"][1]) def set_values(self): for r_id in self.appdata.project.maps[self.name]["boxes"]: if r_id in self.appdata.project.scen_values.keys(): self.reaction_boxes[r_id].set_val_and_color( self.appdata.project.scen_values[r_id]) elif r_id in self.appdata.project.comp_values.keys(): self.reaction_boxes[r_id].set_val_and_color( self.appdata.project.comp_values[r_id]) def remove_box(self, reaction: str): del self.appdata.project.maps[self.name]["boxes"][reaction] del self.reaction_boxes[reaction] self.update() self.reactionRemoved.emit(reaction) # def emit_doubleClickedReaction(self, reaction: str): # print("emit_doubleClickedReaction") # self.doubleClickedReaction.emit(reaction) def value_changed(self, reaction: str, value: str): self.reactionValueChanged.emit(reaction, value) self.reaction_boxes[reaction].recolor() switchToReactionMask = Signal(str) maximizeReaction = Signal(str) minimizeReaction = Signal(str) reactionRemoved = Signal(str) reactionValueChanged = Signal(str, str) reactionAdded = Signal(str) mapChanged = Signal(str)
class CroppableCameraView(QGraphicsView): rectChanged = Signal(QRect) imageDisplayed = Signal(np.ndarray) videoStarted = Signal() mouseMoved = Signal(QMouseEvent) mousePressed = Signal(QMouseEvent) mouseReleased = Signal(QMouseEvent) def __init__(self, camera, **settings): super(CroppableCameraView, self).__init__() self.setRenderHint(QPainter.Antialiasing) self.cam = camera self.is_live = False self._cmin = 0 self._cmax = None self.settings = settings self._selecting = False self.needs_resize = False self.latest_array = None self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() #self.setFrameStyle(QFrame.NoFrame) self.setScene(self.scene) self.pixmapitem = self.scene.addPixmap(QPixmap()) self._uncropped_pixmap = None self.setMouseTracking(True) self.start = None c1 = QColor(0, 100, 220, 150) self.c2 = QColor(0, 100, 220, 50) self.c3 = QColor(0, 100, 220, 0) pen = QPen(c1, 2) self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3) self.selrect.setZValue(100) self.selrect.hide() def enable_selecting(self): print("Selection enabled") self._selecting = True def disable_selecting(self): self._selecting = False def mousePressEvent(self, event): if self._selecting: print("Mouse pressed") if not self.selrect.isVisible(): self.selrect.show() if event.button() == Qt.LeftButton: sp = self.mapToScene(event.pos()) self.start = (sp.x(), sp.y()) self.selrect.setRect(sp.x(), sp.y(), 0, 0) self.selrect.setBrush(self.c2) self.mousePressed.emit(event) def mouseMoveEvent(self, event): if self.start: x1, y1 = self.start sp = self.mapToScene(event.pos()) # Image width, height in scene coords ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) size = self.pixmapitem.pixmap().size() x2 = max(sr.left(), min(sr.right()-1, sp.x())) y2 = max(sr.top(), min(sr.bottom()-1, sp.y())) x1, x2 = sorted((x1, x2)) y1, y2 = sorted((y1, y2)) self.selrect.setRect(x1, y1, x2-x1, y2-y1) self.mouseMoved.emit(event) def mouseReleaseEvent(self, event): if self.start and event.button() == Qt.LeftButton: self.start = None self.selrect.setBrush(self.c3) self.rectChanged.emit(self.selrect.rect().toRect()) self.mouseReleased.emit(event) def update_rect(self, x, y, w, h): self.selrect.setRect(x, y, w, h) self.rectChanged.emit(self.selrect.rect().toRect()) def hideRect(self): self.selrect.hide() def showRect(self): self.selrect.show() def setRectVisible(self, visible): self.selrect.setVisible(visible) def isRectVisible(self): return self.selrect.isVisible() def rect(self): """QRect of the selection in camera coordinates""" # selrect in _image_ (pixmap) coordinates i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect(self.selrect.rect()) current_left = self.settings.get('left', 0) current_top = self.settings.get('top', 0) return i_selrect.toRect().translated(current_left, current_top) def crop_to_rect(self): was_live = self.is_live if was_live: self.stop_video() self.hideRect() rect = self.rect() self.settings['left'] = rect.left() self.settings['right'] = rect.right() self.settings['top'] = rect.top() self.settings['bot'] = rect.bottom() if was_live: self.start_video() else: if not self._uncropped_pixmap: self._uncropped_pixmap = self.pixmapitem.pixmap() self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect)) self.setFixedSize(rect.width(), rect.height()) def uncrop(self): was_live = self.is_live if was_live: self.stop_video() for key in ['left', 'right', 'top', 'bot']: if key in self.settings: del self.settings[key] if was_live: self.start_video() else: pixmap = self._uncropped_pixmap self.pixmapitem.setPixmap(pixmap) ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) self.scene.setSceneRect(sr) self.setFixedSize(sr.width(), sr.height()) def mapSceneToPixmap(self, pt): transform = self.pixmapitem.sceneTransform().inverted()[0] return transform.mapRect(pt) if isinstance(pt, (QRect, QRectF)) else transform.map(pt) def mapViewToPixmap(self, view_pt): scene_pt = self.mapToScene(view_pt) return self.mapSceneToPixmap(scene_pt) def mapPixmapToScene(self, pixmap_pt): transform = self.pixmapitem.sceneTransform() map_func = transform.mapRect if isinstance(pixmap_pt, (QRect, QRectF)) else transform.map return map_func(pixmap_pt) def mapSceneToCamera(self, sc_pt): px_pt = self.mapSceneToPixmap(sc_pt) return QPoint(px_pt.x() + self.settings.get('left', 0), px_pt.y() + self.settings.get('top', 0)) def set_image(self, image_arr): pixmap = QPixmap(self._array_to_qimage(image_arr)) if not self.pixmapitem: self.pixmapitem = self.scene.addPixmap(pixmap) else: self.pixmapitem.setPixmap(pixmap) if self.needs_resize: self._autoresize_viewport() self.needs_resize = False def _autoresize_viewport(self): ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) self.scene.setSceneRect(sr) #self.setFixedSize(sr.width(), sr.height()) self.resize(sr.width(), sr.height()) #self.viewport().setMaximumSize(sr.width(), sr.height()) d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setMaximumSize(sr.width() + 2*d, sr.height() + 2*d) def grab_image(self): arr = self.cam.grab_image(**self.settings) self.set_image(arr) self.latest_array = arr self.imageDisplayed.emit(arr) def start_video(self): timer = QTimer() self.timer = timer timer.timeout.connect(self._wait_for_frame) self.cam.start_live_video(**self.settings) timer.start(0) # Run full throttle self.is_live = True self.needs_resize = True self.videoStarted.emit() def stop_video(self): self.timer.stop() self.cam.stop_live_video() self.is_live = False def _wait_for_frame(self): frame_ready = self.cam.wait_for_frame(timeout='0 ms') if frame_ready: arr = self.cam.latest_frame(copy=True) self.set_image(arr) self.latest_array = arr self.imageDisplayed.emit(arr) def _scale_image(self, arr): """Return a bytescaled copy of the image array""" if not self._cmax: self._cmax = arr.max() # Set cmax once from first image return scipy.misc.bytescale(arr, self._cmin, self._cmax) def _lut_scale_image(self, arr): if not self._cmax: self._cmax = arr.max() lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax) return lut[arr] def _create_lut(self, k): A = 2**15 B = 100 # k's scaling factor g = lambda i, k: A*((k-B)*i) / ((2*k)*x - (k+B)*A) def _array_to_qimage(self, arr): bpl = arr.strides[0] is_rgb = len(arr.shape) == 3 if is_rgb and arr.dtype == np.uint8: format = QImage.Format_RGB32 image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format) elif not is_rgb and arr.dtype == np.uint8: # TODO: Somehow need to make sure data is ordered as I'm assuming format = QImage.Format_Indexed8 image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format) self._saved_img = arr elif not is_rgb and arr.dtype == np.uint16: arr = self._scale_image(arr) format = QImage.Format_Indexed8 w, h = self.cam.width, self.cam.height image = QImage(arr.data, w, h, w, format) self._saved_img = arr # Save a reference to keep Qt from crashing else: raise Exception("Unsupported color mode") return image
class Image_Note(QMainWindow, gui_window.Ui_MainWindow): def __init__(self, parent=None): super(Image_Note, self).__init__(parent) self.setupUi(self) self.button_browse.clicked.connect(self.browse_file) self.button_browse_pdf.clicked.connect(self.browse_pdf_file) self.slider.setMinimum(0) self.slider.setMaximum(100) self.slider.setValue(40) self.button_reset.clicked.connect(self.reset) self.slider.valueChanged.connect(self.sensitivity_slider) self.button_delete.clicked.connect(self.remove_residual_images) self.button_save.clicked.connect(self.save_image) self.button_pdf_save.clicked.connect(self.save_pdf) self.visibility_widgets() def visibility_widgets(self, disable: bool = False): self.all_widgets = [ self.button_delete, self.button_pdf_save, self.button_reset, self.button_save, self.slider ] for widget in self.all_widgets: widget.setEnabled(disable) print(type(widget)) def sensitivity_slider(self): value = self.slider.value() print(value) self.thumbnail_image = Image.open(self.thumbnail_address) self.thumbnail_address_converted = \ file_handler.filepath_modified_suffix( self.thumbnail_address) convert_util.convert_sample(self.thumbnail_address, self.thumbnail_address_converted, value) self.load_graphics_image(self.thumbnail_address_converted) def reset(self): self.slider.setValue(40) self.thumbnail_image = Image.open(self.thumbnail_address) self.load_graphics_image(self.thumbnail_address) def remove_residual_images(self): file_handler.remove_file(self.thumbnail_address) file_handler.remove_file(self.thumbnail_address_converted) def save_image(self): value = self.slider.value() convert_util.convert_full_image(self.file_address, self.modified_image_address, value) def save_pdf(self): import os if not os.path.exists(self.modified_image_address): self.save_image() convert_util.convert_image_to_pdf( self.modified_image_address, file_handler.change_path_extension(self.modified_image_address, ".pdf")) # def pdf_convert(self): # self.save_image() # convert_util.convert_image_to_pdf(self.modified_image_address, # file_handler.change_path_extension( # noqa # self.modified_image_address, # ".pdf")) def browse_pdf_file(self): self.pdf_file_address = QFileDialog.getOpenFileName( self, 'Open PDF File')[0] # print(self.pdf_file_address[0]) self.file_address = file_handler.change_path_extension( self.pdf_file_address, ".png") convert_util.convert_pdf_to_image(self.pdf_file_address, self.file_address) self.process_file() def browse_file(self): response = QFileDialog.getOpenFileName(self, 'Open Image File') self.file_address = response[0] if not os.path.exists(self.file_address): return # return self.process_file() def process_file(self): self.thumbnail_address: str = file_handler.filepath_modified_suffix( self.file_address, "_thumbnail") self.modified_image_address: str = \ file_handler.filepath_modified_suffix( self.file_address) image_handler.save_thumbnail(Image.open(self.file_address), self.thumbnail_address) self.visibility_widgets(True) self.load_graphics_image(self.thumbnail_address) def load_graphics_image(self, image_address: str): self.graphics_scene = QGraphicsScene() self.graphics_scene.addPixmap(QPixmap(image_address)) self.graphicsView.setScene(self.graphics_scene)
class GraphicsView(QGraphicsView): def __init__(self, parent=None): super(GraphicsView, self).__init__(parent) self.scene = QGraphicsScene() self.pixmapItem = QGraphicsPixmapItem() self.scene.setSceneRect(0, 0, 500, 500) self.setScene(self.scene) self.scene.addItem(self.pixmapItem) #would eventually make this fit to size of screen, waiting cause it's annoying. self.buildingParams = [] self.scalef = [1, 1] self.Buildings() def Buildings(self): filename = os.getcwd() + "\examplebuildings.png" img = cv2.imread(filename) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imgray, 250, 255, 0) contours , h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) MinCntArea = 5000. MaxCntArea = 100000. for cnt in contours: if cv2.contourArea(cnt) > MinCntArea and cv2.contourArea(cnt) < MaxCntArea: cv2.drawContours(img, cnt, -1, (0, 255, 0), 3) # this is a green rectangle which shows the found contour #cv2.circle(img, (min(cnt.T[0][0]), min(cnt.T[1][0])), 4, 4) #makes a circle around the upper left corner #np.set_printoptions(threshold=np.inf) #this is to make it so that the whole numpy array prints to the terminal self.buildingParams.append([min(cnt.T[0][0]), min(cnt.T[1][0]), max(cnt.T[0][0])-min(cnt.T[0][0]), max(cnt.T[1][0])-min(cnt.T[1][0])]) # x, y, height, width # copy and paste these three lines if you would like to see what an opencv images looks like anywhere in the program #cv2.imshow('img', img) #cv2.waitKey(0) #cv2.destroyAllWindows() #cv2.rectangle(img, (self.buildingParams[0][0], self.buildingParams[0][1]), # (self.buildingParams[0][0] + self.buildingParams[0][2], self.buildingParams[0][1] + self.buildingParams[0][3]), # (255, 0, 0), -1) # draws a blue filled in rectangle - did this to make sure I had the indicies correct for x, y, width, and height height, width, channel = img.shape bytesPerLine = 3*width qimg = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped() ##### need to add not null checks here self.ogimage = QPixmap.fromImage(qimg) self.image = self.ogimage.scaled(self.scene.width(), self.scene.height()) self.pixmapItem.setPixmap(self.image) self.updateScalef() self.buildingParams += self.scalef for i in range(len(self.buildingParams)-2): parameters = self.buildingParams rect = GraphicsRectItem(QRectF(QPointF(parameters[i][0] * parameters[4], parameters[i][1] * parameters[5]), QPointF((parameters[i][0] + parameters[i][2]) * parameters[4], (parameters[i][1] + parameters[i][3]) * parameters[5]))) rect.setAcceptHoverEvents(True) self.scene.addItem(rect) def updateScalef(self): self.scalef[0] = self.image.width()/self.ogimage.width() self.scalef[1] = self.image.height()/self.ogimage.height() def mousePressEvent(self, e): print(e.pos())
self._length = length def spacing(self): return self._spacing def setSpacing(self, spacing): self._spacing = spacing if __name__ == '__main__': import sys from qtpy.QtWidgets import QApplication, QGraphicsView, QGraphicsScene from qtpy.QtGui import QCursor app = QApplication(sys.argv) v = QGraphicsView() s = QGraphicsScene() v.setSceneRect(0, 0, 200, 200) v.setScene(s) # GRADIENT g = drawColorTypeGradient(attrs.HUE, 100, 100) g.setFinalStop(0, 300) s.setBackgroundBrush(QBrush(g)) #LINE l = DualColoredLineSegment() l.setLine(0, 0, 300, 300) s.addItem(l) v.show() v.move(QCursor.pos()) sys.exit(app.exec_())
class CroppableCameraView(QGraphicsView): rectChanged = Signal(QRect) imageDisplayed = Signal(np.ndarray) videoStarted = Signal() mouseMoved = Signal(QMouseEvent) mousePressed = Signal(QMouseEvent) mouseReleased = Signal(QMouseEvent) def __init__(self, camera, **settings): super(CroppableCameraView, self).__init__() self.setRenderHint(QPainter.Antialiasing) self.cam = camera self.is_live = False self._cmin = 0 self._cmax = None self.settings = settings self._selecting = False self.needs_resize = False self.latest_array = None self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scene = QGraphicsScene() #self.setFrameStyle(QFrame.NoFrame) self.setScene(self.scene) self.pixmapitem = self.scene.addPixmap(QPixmap()) self._uncropped_pixmap = None self.setMouseTracking(True) self.start = None c1 = QColor(0, 100, 220, 150) self.c2 = QColor(0, 100, 220, 50) self.c3 = QColor(0, 100, 220, 0) pen = QPen(c1, 2) self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3) self.selrect.setZValue(100) self.selrect.hide() def enable_selecting(self): print("Selection enabled") self._selecting = True def disable_selecting(self): self._selecting = False def mousePressEvent(self, event): if self._selecting: print("Mouse pressed") if not self.selrect.isVisible(): self.selrect.show() if event.button() == Qt.LeftButton: sp = self.mapToScene(event.pos()) self.start = (sp.x(), sp.y()) self.selrect.setRect(sp.x(), sp.y(), 0, 0) self.selrect.setBrush(self.c2) self.mousePressed.emit(event) def mouseMoveEvent(self, event): if self.start: x1, y1 = self.start sp = self.mapToScene(event.pos()) # Image width, height in scene coords ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) size = self.pixmapitem.pixmap().size() x2 = max(sr.left(), min(sr.right() - 1, sp.x())) y2 = max(sr.top(), min(sr.bottom() - 1, sp.y())) x1, x2 = sorted((x1, x2)) y1, y2 = sorted((y1, y2)) self.selrect.setRect(x1, y1, x2 - x1, y2 - y1) self.mouseMoved.emit(event) def mouseReleaseEvent(self, event): if self.start and event.button() == Qt.LeftButton: self.start = None self.selrect.setBrush(self.c3) self.rectChanged.emit(self.selrect.rect().toRect()) self.mouseReleased.emit(event) def update_rect(self, x, y, w, h): self.selrect.setRect(x, y, w, h) self.rectChanged.emit(self.selrect.rect().toRect()) def hideRect(self): self.selrect.hide() def showRect(self): self.selrect.show() def setRectVisible(self, visible): self.selrect.setVisible(visible) def isRectVisible(self): return self.selrect.isVisible() def rect(self): """QRect of the selection in camera coordinates""" # selrect in _image_ (pixmap) coordinates i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect( self.selrect.rect()) current_left = self.settings.get('left', 0) current_top = self.settings.get('top', 0) return i_selrect.toRect().translated(current_left, current_top) def crop_to_rect(self): was_live = self.is_live if was_live: self.stop_video() self.hideRect() rect = self.rect() self.settings['left'] = rect.left() self.settings['right'] = rect.right() self.settings['top'] = rect.top() self.settings['bot'] = rect.bottom() if was_live: self.start_video() else: if not self._uncropped_pixmap: self._uncropped_pixmap = self.pixmapitem.pixmap() self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect)) self.setFixedSize(rect.width(), rect.height()) def uncrop(self): was_live = self.is_live if was_live: self.stop_video() for key in ['left', 'right', 'top', 'bot']: if key in self.settings: del self.settings[key] if was_live: self.start_video() else: pixmap = self._uncropped_pixmap self.pixmapitem.setPixmap(pixmap) ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) self.scene.setSceneRect(sr) self.setFixedSize(sr.width(), sr.height()) def mapSceneToPixmap(self, pt): transform = self.pixmapitem.sceneTransform().inverted()[0] return transform.mapRect(pt) if isinstance( pt, (QRect, QRectF)) else transform.map(pt) def mapViewToPixmap(self, view_pt): scene_pt = self.mapToScene(view_pt) return self.mapSceneToPixmap(scene_pt) def mapPixmapToScene(self, pixmap_pt): transform = self.pixmapitem.sceneTransform() map_func = transform.mapRect if isinstance(pixmap_pt, (QRect, QRectF)) else transform.map return map_func(pixmap_pt) def mapSceneToCamera(self, sc_pt): px_pt = self.mapSceneToPixmap(sc_pt) return QPoint(px_pt.x() + self.settings.get('left', 0), px_pt.y() + self.settings.get('top', 0)) def set_image(self, image_arr): pixmap = QPixmap(self._array_to_qimage(image_arr)) if not self.pixmapitem: self.pixmapitem = self.scene.addPixmap(pixmap) else: self.pixmapitem.setPixmap(pixmap) if self.needs_resize: self._autoresize_viewport() self.needs_resize = False def _autoresize_viewport(self): ir = self.pixmapitem.boundingRect() sr = self.pixmapitem.sceneTransform().mapRect(ir) self.scene.setSceneRect(sr) #self.setFixedSize(sr.width(), sr.height()) self.resize(sr.width(), sr.height()) #self.viewport().setMaximumSize(sr.width(), sr.height()) d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setMaximumSize(sr.width() + 2 * d, sr.height() + 2 * d) def grab_image(self): arr = self.cam.grab_image(**self.settings) self.set_image(arr) self.latest_array = arr self.imageDisplayed.emit(arr) def start_video(self): timer = QTimer() self.timer = timer timer.timeout.connect(self._wait_for_frame) self.cam.start_live_video(**self.settings) timer.start(0) # Run full throttle self.is_live = True self.needs_resize = True self.videoStarted.emit() def stop_video(self): self.timer.stop() self.cam.stop_live_video() self.is_live = False def _wait_for_frame(self): frame_ready = self.cam.wait_for_frame(timeout='0 ms') if frame_ready: arr = self.cam.latest_frame(copy=True) self.set_image(arr) self.latest_array = arr self.imageDisplayed.emit(arr) def _scale_image(self, arr): """Return a bytescaled copy of the image array""" if not self._cmax: self._cmax = arr.max() # Set cmax once from first image return scipy.misc.bytescale(arr, self._cmin, self._cmax) def _lut_scale_image(self, arr): if not self._cmax: self._cmax = arr.max() lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax) return lut[arr] def _create_lut(self, k): A = 2**15 B = 100 # k's scaling factor g = lambda i, k: A * ((k - B) * i) / ((2 * k) * x - (k + B) * A) def _array_to_qimage(self, arr): bpl = arr.strides[0] is_rgb = len(arr.shape) == 3 if is_rgb and arr.dtype == np.uint8: format = QImage.Format_RGB32 image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format) elif not is_rgb and arr.dtype == np.uint8: # TODO: Somehow need to make sure data is ordered as I'm assuming format = QImage.Format_Indexed8 image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format) self._saved_img = arr elif not is_rgb and arr.dtype == np.uint16: arr = self._scale_image(arr) format = QImage.Format_Indexed8 w, h = self.cam.width, self.cam.height image = QImage(arr.data, w, h, w, format) self._saved_img = arr # Save a reference to keep Qt from crashing else: raise Exception("Unsupported color mode") return image
def load_graphics_image(self, image_address: str): self.graphics_scene = QGraphicsScene() self.graphics_scene.addPixmap(QPixmap(image_address)) self.graphicsView.setScene(self.graphics_scene)
class DataGraphWidget(QGraphicsView): selection_changed = Signal() def __init__(self, parent=None): super(DataGraphWidget, self).__init__(parent=parent) # Set up scene self.scene = QGraphicsScene(self) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(0, 0, 800, 300) self.setScene(self.scene) self.setWindowTitle("Glue data graph") self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) self.selection_level = 0 def resizeEvent(self, event): self.scene.setSceneRect(0, 0, self.width(), self.height()) self.relayout(reorder=False) def relayout(self, reorder=True): # Update radius for node in self.nodes: node.radius = self.height() / 30. layout_simple_circle(self.nodes, self.edges, center=(self.width() / 2, self.height() / 2), radius=self.height() / 3, reorder=reorder) # Update edge positions for edge in self.edges: edge.update_position() # Set up labels self.left_nodes = [node for node in self.nodes if node.node_position[0] < self.width() / 2] self.left_nodes = sorted(self.left_nodes, key=lambda x: x.node_position[1], reverse=True) self.right_nodes = [node for node in self.nodes if node not in self.left_nodes] self.right_nodes = sorted(self.right_nodes, key=lambda x: x.node_position[1], reverse=True) for i, node in enumerate(self.left_nodes): y = self.height() - (i + 1) / (len(self.left_nodes) + 1) * self.height() node.label_position = self.width() / 2 - self.height() / 2, y for i, node in enumerate(self.right_nodes): y = self.height() - (i + 1) / (len(self.right_nodes) + 1) * self.height() node.label_position = self.width() / 2 + self.height() / 2, y def set_data_collection(self, data_collection): # Get data and initialize nodes self.data_to_nodes = dict((data, DataNode(data)) for data in data_collection) self.nodes = list(self.data_to_nodes.values()) # Get links and set up edges self.edges = [Edge(self.data_to_nodes[data1], self.data_to_nodes[data2]) for data1, data2 in get_connections(data_collection.external_links)] # Figure out positions self.relayout() # Add nodes and edges to graph for node in self.nodes: node.add_to_scene(self.scene) for edge in self.edges: edge.add_to_scene(self.scene) self.text_adjusted = False self.selected_edge = None self.selected_node1 = None self.selected_node2 = None def set_links(self, links): for edge in self.edges: edge.remove_from_scene(self.scene) self.edges = [Edge(self.data_to_nodes[data1], self.data_to_nodes[data2]) for data1, data2 in get_connections(links)] for edge in self.edges: edge.update_position() for edge in self.edges: edge.add_to_scene(self.scene) self._update_selected_edge() self._update_selected_colors() def paintEvent(self, event): super(DataGraphWidget, self).paintEvent(event) if not self.text_adjusted: for node in self.nodes: width = node.label.boundingRect().width() height = node.label.boundingRect().height() transform = QTransform() if node in self.left_nodes: transform.translate(-width, -height / 2) else: transform.translate(0, -height / 2) node.label.setTransform(transform) self.text_adjusted = True def manual_select(self, data1=None, data2=None): if data1 is None and data2 is not None: data1, data2 = data2, data1 if data2 is not None: self.selection_level = 2 elif data1 is not None: self.selection_level = 1 else: self.selection_level = 0 self.selected_node1 = self.data_to_nodes.get(data1, None) self.selected_node2 = self.data_to_nodes.get(data2, None) self._update_selected_edge() self._update_selected_colors() def find_object(self, event): for obj in list(self.nodes) + self.edges: if obj.contains(event.localPos()): return obj def mouseMoveEvent(self, event): # TODO: Don't update until the end # TODO: Only select object on top selected = self.find_object(event) if selected is None: if self.selection_level == 0: self.selected_node1 = None self.selected_node2 = None self._update_selected_edge() elif self.selection_level == 1: self.selected_node2 = None self._update_selected_edge() elif isinstance(selected, DataNode): if self.selection_level == 0: self.selected_node1 = selected self.selected_node2 = None elif self.selection_level == 1: if selected is not self.selected_node1: self.selected_node2 = selected self._update_selected_edge() elif isinstance(selected, Edge): if self.selection_level == 0: self.selected_edge = selected self.selected_node1 = selected.node_source self.selected_node2 = selected.node_dest self._update_selected_colors() self.selection_changed.emit() def mousePressEvent(self, event): # TODO: Don't update until the end # TODO: Only select object on top selected = self.find_object(event) if selected is None: self.selection_level = 0 self.selected_node1 = None self.selected_node2 = None self._update_selected_edge() elif isinstance(selected, DataNode): if self.selection_level == 0: self.selected_node1 = selected self.selection_level += 1 elif self.selection_level == 1: if selected is self.selected_node1: self.selected_node1 = None self.selection_level = 0 else: self.selected_node2 = selected self.selection_level = 2 elif self.selection_level == 2: if selected is self.selected_node2: self.selected_node2 = None self.selection_level = 1 else: self.selected_node1 = selected self.selected_node2 = None self.selection_level = 1 self._update_selected_edge() elif isinstance(selected, Edge): if self.selected_edge is selected and self.selection_level == 2: self.selected_edge = None self.selected_node1 = None self.selected_node2 = None self.selection_level = 0 else: self.selected_edge = selected self.selected_node1 = selected.node_source self.selected_node2 = selected.node_dest self.selection_level = 2 self.mouseMoveEvent(event) def _update_selected_edge(self): for edge in self.edges: if (edge.node_source is self.selected_node1 and edge.node_dest is self.selected_node2 or edge.node_source is self.selected_node2 and edge.node_dest is self.selected_node1): self.selected_edge = edge break else: self.selected_edge = None def _update_selected_colors(self): colors = {} if self.selected_node1 is not None and self.selection_level < 2: direct, indirect = find_connections(self.selected_node1, self.nodes, self.edges) for node in self.nodes: if node in direct or node in indirect: colors[node] = COLOR_CONNECTED else: colors[node] = COLOR_DISCONNECTED for edge in self.edges: if (edge.node_source is self.selected_node1 or edge.node_dest is self.selected_node1): colors[edge] = COLOR_CONNECTED if self.selected_edge is not None: colors[self.selected_edge] = COLOR_SELECTED if self.selected_node1 is not None: colors[self.selected_node1] = COLOR_SELECTED if self.selected_node2 is not None: colors[self.selected_node2] = COLOR_SELECTED self.set_colors(colors) def set_colors(self, colors): for obj in list(self.nodes) + self.edges: default_color = '0.8' if isinstance(obj, DataNode) else '0.5' obj.color = colors.get(obj, default_color) obj.update()
class DataGraphWidget(QGraphicsView): selection_changed = Signal() def __init__(self, parent=None): super(DataGraphWidget, self).__init__(parent=parent) # Set up scene self.scene = QGraphicsScene(self) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(0, 0, 800, 300) self.setScene(self.scene) self.setWindowTitle("Glue data graph") self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) self.selection_level = 0 def resizeEvent(self, event): self.scene.setSceneRect(0, 0, self.width(), self.height()) self.relayout(reorder=False) def relayout(self, reorder=True): # Update radius for node in self.nodes: node.radius = self.height() / 30. layout_simple_circle(self.nodes, self.edges, center=(self.width() / 2, self.height() / 2), radius=self.height() / 3, reorder=reorder) # Update edge positions for edge in self.background_edges + self.edges: edge.update_position() # Set up labels self.left_nodes = [ node for node in self.nodes if node.node_position[0] < self.width() / 2 ] self.left_nodes = sorted(self.left_nodes, key=lambda x: x.node_position[1], reverse=True) self.right_nodes = [ node for node in self.nodes if node not in self.left_nodes ] self.right_nodes = sorted(self.right_nodes, key=lambda x: x.node_position[1], reverse=True) for i, node in enumerate(self.left_nodes): y = self.height() - (i + 1) / (len(self.left_nodes) + 1) * self.height() node.label_position = self.width() / 2 - self.height() / 2, y for i, node in enumerate(self.right_nodes): y = self.height() - (i + 1) / (len(self.right_nodes) + 1) * self.height() node.label_position = self.width() / 2 + self.height() / 2, y def set_data_collection(self, data_collection, old_links=None, new_links=None): # Get data and initialize nodes self.data_to_nodes = OrderedDict( (data, DataNode(data)) for data in data_collection) self.nodes = list(self.data_to_nodes.values()) # Get links and set up edges if old_links: self.background_edges = [ Edge(self.data_to_nodes[data1], self.data_to_nodes[data2], linewidth=1, zindex=1) for data1, data2 in get_connections( data_collection.external_links) ] else: self.background_edges = [] if new_links: self.edges = [ Edge(self.data_to_nodes[data1], self.data_to_nodes[data2]) for data1, data2 in get_connections(new_links) ] else: self.edges = [] # Figure out positions self.relayout() # Add nodes and edges to graph for node in self.nodes: node.add_to_scene(self.scene) for edge in self.background_edges + self.edges: edge.add_to_scene(self.scene) self.text_adjusted = False self.selected_edge = None self.selected_node1 = None self.selected_node2 = None def set_links(self, links): for edge in self.edges: edge.remove_from_scene(self.scene) self.edges = [ Edge(self.data_to_nodes[data1], self.data_to_nodes[data2]) for data1, data2 in get_connections(links) ] for edge in self.edges: edge.update_position() for edge in self.edges: edge.add_to_scene(self.scene) self._update_selected_edge() self._update_selected_colors() def paintEvent(self, event): super(DataGraphWidget, self).paintEvent(event) if not self.text_adjusted: for node in self.nodes: width = node.label.boundingRect().width() height = node.label.boundingRect().height() transform = QTransform() if node in self.left_nodes: transform.translate(-width, -height / 2) else: transform.translate(0, -height / 2) node.label.setTransform(transform) self.text_adjusted = True def manual_select(self, data1=None, data2=None): if data1 is None and data2 is not None: data1, data2 = data2, data1 if data2 is not None: self.selection_level = 2 elif data1 is not None: self.selection_level = 1 else: self.selection_level = 0 self.selected_node1 = self.data_to_nodes.get(data1, None) self.selected_node2 = self.data_to_nodes.get(data2, None) self._update_selected_edge() self._update_selected_colors() def find_object(self, event): for obj in list(self.nodes) + self.edges: if obj.contains(event.localPos()): return obj def mouseMoveEvent(self, event): # TODO: Don't update until the end # TODO: Only select object on top selected = self.find_object(event) if selected is None: if self.selection_level == 0: self.selected_node1 = None self.selected_node2 = None self._update_selected_edge() elif self.selection_level == 1: self.selected_node2 = None self._update_selected_edge() elif isinstance(selected, DataNode): if self.selection_level == 0: self.selected_node1 = selected self.selected_node2 = None elif self.selection_level == 1: if selected is not self.selected_node1: self.selected_node2 = selected self._update_selected_edge() elif isinstance(selected, Edge): if self.selection_level == 0: self.selected_edge = selected self.selected_node1 = selected.node_source self.selected_node2 = selected.node_dest self._update_selected_colors() self.selection_changed.emit() def mousePressEvent(self, event): # TODO: Don't update until the end # TODO: Only select object on top selected = self.find_object(event) if selected is None: self.selection_level = 0 self.selected_node1 = None self.selected_node2 = None self._update_selected_edge() elif isinstance(selected, DataNode): if self.selection_level == 0: self.selected_node1 = selected self.selection_level += 1 elif self.selection_level == 1: if selected is self.selected_node1: self.selected_node1 = None self.selection_level = 0 else: self.selected_node2 = selected self.selection_level = 2 elif self.selection_level == 2: if selected is self.selected_node2: self.selected_node2 = None self.selection_level = 1 else: self.selected_node1 = selected self.selected_node2 = None self.selection_level = 1 self._update_selected_edge() elif isinstance(selected, Edge): if self.selected_edge is selected and self.selection_level == 2: self.selected_edge = None self.selected_node1 = None self.selected_node2 = None self.selection_level = 0 else: self.selected_edge = selected self.selected_node1 = selected.node_source self.selected_node2 = selected.node_dest self.selection_level = 2 self.mouseMoveEvent(event) def _update_selected_edge(self): for edge in self.edges: if (edge.node_source is self.selected_node1 and edge.node_dest is self.selected_node2 or edge.node_source is self.selected_node2 and edge.node_dest is self.selected_node1): self.selected_edge = edge break else: self.selected_edge = None def _update_selected_colors(self): colors = {} if self.selected_node1 is not None and self.selection_level < 2: direct, indirect = find_connections(self.selected_node1, self.nodes, self.edges) for node in self.nodes: if node in direct or node in indirect: colors[node] = COLOR_CONNECTED else: colors[node] = COLOR_DISCONNECTED for edge in self.edges: if (edge.node_source is self.selected_node1 or edge.node_dest is self.selected_node1): colors[edge] = COLOR_CONNECTED if self.selected_edge is not None: colors[self.selected_edge] = COLOR_SELECTED if self.selected_node1 is not None: colors[self.selected_node1] = COLOR_SELECTED if self.selected_node2 is not None: colors[self.selected_node2] = COLOR_SELECTED self.set_colors(colors) def set_colors(self, colors): for obj in list(self.nodes) + self.edges: default_color = '0.8' if isinstance(obj, DataNode) else '0.5' obj.color = colors.get(obj, default_color) obj.update()
class MovieSelectionWindow(QDialog): __scene__ = None __poster_url__ = 'https://image.tmdb.org/t/p/original' __possibilities__ = None acceptedId = -1 def __init__(self, oFile, possibilities): self.acceptedId = -1 QDialog.__init__(self) self.ui = Ui_MovieSelection() self.ui.setupUi(self) self.ui.btnEnterId.clicked.connect(self.enterId) self.ui.btnEnterTitle.clicked.connect(self.enterTitle) self.ui.btnAccept.clicked.connect(self.accept) self.ui.tablePossibilities.horizontalHeader().setVisible(True) self.ui.tablePossibilities.verticalHeader().setVisible(True) self.ui.tablePossibilities.cellClicked.connect(self.selectionChanged) self.ui.lblOriginalFile.setText(oFile) self.__possibilities__ = possibilities self.actualizeTable() def showImage(self, posterPath: str): self.removeImage() imgData = requests.get(self.__poster_url__ + posterPath) pix = QPixmap() pix.loadFromData(imgData.content) item = QGraphicsPixmapItem(pix) self.__scene__ = QGraphicsScene(self) self.__scene__.addItem(item) self.ui.graphicsView.setScene(self.__scene__) self.resizeImage() def removeImage(self): if self.__scene__ != None: self.__scene__.clear() self.__scene__ = None def resizeEvent(self, event): QDialog.resizeEvent(self, event) self.resizeImage() def resizeImage(self): if (self.__scene__ != None): self.ui.graphicsView.fitInView(self.__scene__.sceneRect(), mode=Qt.KeepAspectRatio) self.ui.graphicsView.show() def actualizeTable(self): self.ui.tablePossibilities.clearContents() r = 0 for p in self.__possibilities__: if 'title' not in p.__dict__ or 'release_date' not in p.__dict__: self.__possibilities__.remove(p) continue self.ui.tablePossibilities.setRowCount(r + 1) self.ui.tablePossibilities.setItem(r, 0, QTableWidgetItem(p.title)) self.ui.tablePossibilities.setItem( r, 1, QTableWidgetItem(p.release_date[:4])) r += 1 self.ui.tablePossibilities.clearSelection() def selectionChanged(self, row, column): self.ui.txtOverview.clear() self.ui.txtOverview.appendPlainText( self.__possibilities__[row].overview) self.ui.lblTitle.setText(self.__possibilities__[row].title + ' (' + self.__possibilities__[row].release_date[:4] + ')') if self.__possibilities__[row].poster_path != None: self.showImage(self.__possibilities__[row].poster_path) else: self.removeImage() def enterId(self): select = CustomEnterWindow(True) select.setWindowModality(Qt.WindowModal) mw = qtmodern.windows.ModernWindow(select) mw.setWindowModality(Qt.WindowModal) mw.show() select.ui.txtId.setFocus() loop = QEventLoop() select.finished.connect(loop.quit) loop.exec() if select.result != None and select.result.isdecimal(): self.acceptedId = int(select.result) self.close() def __enterTitleWindow__(self, search): select = CustomEnterWindow(False) select.setWindowModality(Qt.WindowModal) mw = qtmodern.windows.ModernWindow(select) mw.setWindowModality(Qt.WindowModal) mw.show() select.ui.txtId.setFocus() loop = QEventLoop() select.finished.connect(loop.quit) loop.exec() if select.result != None: self.__possibilities__ = search(select.result) self.actualizeTable() def enterTitle(self): self.__enterTitleWindow__(Movie().search) def accept(self): self.acceptedId = self.__possibilities__[ self.ui.tablePossibilities.currentRow()].id self.close()
def __init__(self, *args, **kwargs): self.scene = QGraphicsScene() super(FlatStem, self).__init__(self.scene, *args, **kwargs)
class FlatStem(MeristemDisplay, QGraphicsView): """A QTGraphics canvas to display a 2D (rolled out) view of a meristem.""" def __init__(self, *args, **kwargs): self.scene = QGraphicsScene() super(FlatStem, self).__init__(self.scene, *args, **kwargs) def thin_line(self, colour=None): """Return a pen that draws a thin line in the given colour.""" pen = QPen(colour) if colour else QPen() pen.setWidth(0) return pen def shadow_if_needed(self, bud): """Check if the bud crosses over the side bars, and if so draw a shadow bud on the opposite side.""" angle = bud.angle2x(bud.angle + math.radians(self.viewing_angle[0])) if abs(angle) < math.pi * bud.radius - bud.scale: return if angle > 0: angle = angle - bud.scale - 2 * math.pi * bud.radius else: angle = angle - bud.scale + 2 * math.pi * bud.radius return self.scene.addEllipse( angle, -bud.height - bud.scale, bud.scale * 2, bud.scale * 2, self.thin_line(), QBrush(qtpy.QtGui.QColor(*(bud.html_colour + [100]))) ) def make_item(self, bud): """Add the given bud to the scene as a ball.""" item = self.scene.addEllipse( bud.angle2x(bud.angle + math.radians(self.viewing_angle[0])) - bud.scale, -bud.height - bud.scale, bud.scale * 2, bud.scale * 2, self.thin_line(), QBrush(qtpy.QtGui.QColor(*bud.html_colour)) ) return item def set_scale(self): """Scale the view in accordance with the zoom level.""" self.resetTransform() size = self.size() dist = math.sqrt(size.width() * size.height())/50.0 zoom = math.pi * 300/(dist + self.zoom + 11) self.scale(zoom, zoom) def draw_side_bars(self): """Draw the bounding lines of the meristem.""" if not self.displayables: return side_bar = self.thin_line(Qt.blue) top = max([b.radius for b in self.displayables if b.height < b.scale] or [0]) for height in range(int(round(self.objects.height))): bottom = top top = max([b.radius for b in self.displayables if abs(b.height - height) < b.scale] or [0]) bot_side_bar_pos = math.pi * bottom top_side_bar_pos = math.pi * top self.scene.addLine(-bot_side_bar_pos, -height + 0.5, -top_side_bar_pos, -height - 0.5, side_bar) self.scene.addLine(bot_side_bar_pos, -height + 0.5, top_side_bar_pos, -height - 0.5, side_bar) def redraw(self): """Redraw all objects on the scene.""" for item in self.scene.items(): self.scene.removeItem(item) # Draw all buds for bud in self.displayables: self.make_item(bud) self.shadow_if_needed(bud) self.draw_side_bars() self.set_scale() def select(self, event): """Select the item that is under the cursor (if enabled).""" if not self.can_select: return scene_pos = self.mapToScene(QPoint(event.x(), event.y())) x, y = scene_pos.x(), -scene_pos.y() offsets = (math.radians(self.viewing_angle[0]), 0) if self.objects.bounds_test(x, y, offsets) > 0: self.objects.select() # signal all and any slots that something new was selected self._signal_selected()