def set_color(self, color): if color != self._color: self._color = color self.colorChanged.emit(self._color) pixmap = QPixmap(self.iconSize()) pixmap.fill(color) self.setIcon(QIcon(pixmap))
def test_zoom_figure_viewer(figbrowser, tmpdir, fmt): """ Test zooming in and out the figure diplayed in the figure viewer. """ fig = add_figures_to_browser(figbrowser, 1, tmpdir, fmt)[0] figcanvas = figbrowser.figviewer.figcanvas # Calculate original figure size in pixels. qpix = QPixmap() qpix.loadFromData(fig, fmt.upper()) fwidth, fheight = qpix.width(), qpix.height() assert figbrowser.zoom_disp.value() == 100 assert figcanvas.width() == fwidth assert figcanvas.height() == fheight # Zoom in and out the figure in the figure viewer. scaling_factor = 0 scaling_step = figbrowser.figviewer._scalestep for zoom_step in [1, 1, -1, -1, -1]: if zoom_step == 1: figbrowser.zoom_in() elif zoom_step == -1: figbrowser.zoom_out() scaling_factor += zoom_step scale = scaling_step**scaling_factor assert figbrowser.zoom_disp.value() == np.floor(scale * 100) assert figcanvas.width() == np.floor(fwidth * scale) assert figcanvas.height() == np.floor(fheight * scale)
def copy_figure(self): """Copy figure to clipboard.""" if self.fmt in ['image/png', 'image/jpeg']: qpixmap = QPixmap() qpixmap.loadFromData(self.fig, self.fmt.upper()) QApplication.clipboard().setImage(qpixmap.toImage()) elif self.fmt == 'image/svg+xml': svg_to_clipboard(self.fig) else: return self.blink_figure()
def test_save_all_figures(figbrowser, tmpdir, mocker, fmt): """ Test saving all figures contained in the thumbnail scrollbar in batch into a single directory. """ figs = add_figures_to_browser(figbrowser, 3, tmpdir, fmt) # Save all figures, but cancel the dialog to get a directory. mocker.patch( 'spyder.plugins.plots.widgets.figurebrowser.getexistingdirectory', return_value=None) fignames = figbrowser.save_all_figures() assert fignames is None # Save all figures. mocker.patch( 'spyder.plugins.plots.widgets.figurebrowser.getexistingdirectory', return_value=to_text_string(tmpdir.mkdir('all_saved_figures'))) fignames = figbrowser.save_all_figures() assert len(fignames) == len(figs) for fig, figname in zip(figs, fignames): expected_qpix = QPixmap() expected_qpix.loadFromData(fig, fmt.upper()) saved_qpix = QPixmap() saved_qpix.load(figname) assert osp.exists(figname) assert expected_qpix.toImage() == saved_qpix.toImage()
def imageFiles(self, new_files): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Parameters ---------- new_files : str """ self._state_images_string = str(new_files) try: new_file_dict = json.loads(self._state_images_string) except Exception: self._state_images = {} return self._sizeHint = QSize(0, 0) for (state, filename) in new_file_dict.items(): if is_pydm_app(): try: file_path = self.app.get_path(filename) except Exception as e: logger.exception("Couldn't get file with path %s", filename) file_path = filename else: file_path = filename # First, lets try SVG. We have to try SVG first, otherwise # QPixmap will happily load the SVG and turn it into a raster image. # Really annoying: We have to try to load the file as SVG, # and we expect it will fail often (because many images aren't SVG). # Qt prints a warning message to stdout any time SVG loading fails. # So we have to temporarily silence Qt warning messages here. qInstallMessageHandler(self.qt_message_handler) svg = QSvgRenderer() svg.repaintNeeded.connect(self.update) if svg.load(file_path): self._state_images[int(state)] = (filename, svg) self._sizeHint = self._sizeHint.expandedTo(svg.defaultSize()) qInstallMessageHandler(None) continue qInstallMessageHandler(None) # SVG didn't work, lets try QPixmap image = QPixmap(file_path) if not image.isNull(): self._state_images[int(state)] = (filename, image) self._sizeHint = self._sizeHint.expandedTo(image.size()) continue # If we get this far, the file specified could not be loaded at all. logger.error("Could not load image: {}".format(filename)) self._state_images[int(state)] = (filename, None)
def _set_pixmap_from_array(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.camera.width, self.camera.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.camera.width, self.camera.height, bpl, format) self._saved_img = arr elif not is_rgb and arr.dtype == np.uint16: if not self._cmax: self._cmax = arr.max() # Set cmax once from first image arr = scipy.misc.bytescale(arr, self._cmin, self._cmax) format = QImage.Format_Indexed8 w, h = self.camera.width, self.camera.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") self.setPixmap(QPixmap.fromImage(image)) pixmap_size = self.pixmap().size() if pixmap_size != self.size(): self.setMinimumSize(self.pixmap().size())
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)
def set_data(self, title, content, current, image, run, frames=None, step=None): """ """ self.label_title.setText(title) self.combo_title.clear() self.combo_title.addItems(frames) self.combo_title.setCurrentIndex(step) # min_content_len = max([len(f) for f in frames]) # self.combo_title.setMinimumContentsLength(min_content_len) # Fix and try to see how it looks with a combo box self.label_current.setText(current) self.button_current.setText(current) self.label_content.setText(content) self.image = image if image is None: self.label_image.setFixedHeight(1) self.label_image.setFixedWidth(1) else: extension = image.split('.')[-1] self.image = QPixmap(get_image_path(image), extension) self.label_image.setPixmap(self.image) self.label_image.setFixedSize(self.image.size()) if run is None: self.button_run.setVisible(False) else: self.button_run.setDisabled(False) self.button_run.setVisible(True) # Refresh layout self.layout().activate()
def __init__(self, parent=None, icon=True): super(SearchLineEdit, self).__init__(parent) self.setTextMargins(1, 0, 20, 0) if icon: self.setTextMargins(18, 0, 20, 0) self._label = QLabel(self) self._pixmap_icon = QPixmap(get_image_path('conda_search.png')) self._label.setPixmap(self._pixmap_icon) self._label.setStyleSheet('''border: 0px; padding-bottom: 0px; padding-left: 2px;''') self._pixmap = QPixmap(get_image_path('conda_del.png')) self.button_clear = QToolButton(self) self.button_clear.setIcon(QIcon(self._pixmap)) self.button_clear.setIconSize(QSize(18, 18)) self.button_clear.setCursor(Qt.ArrowCursor) self.button_clear.setStyleSheet("""QToolButton {background: transparent; padding-right: 2px; border: none; margin:0px; }""") self.button_clear.setVisible(False) # Layout self._layout = QHBoxLayout(self) self._layout.addWidget(self.button_clear, 0, Qt.AlignRight) self._layout.setSpacing(0) self._layout.setContentsMargins(0, 2, 2, 0) # Signals and slots self.button_clear.clicked.connect(self.clear_text) self.textChanged.connect(self._toggle_visibility) self.textEdited.connect(self._toggle_visibility)
def load_figure(self, fig, fmt): """ Load the figure from a png, jpg, or svg image, convert it in a QPixmap, and force a repaint of the widget. """ self.fig = fig self.fmt = fmt if fmt in ['image/png', 'image/jpeg']: self._qpix_orig = QPixmap() self._qpix_orig.loadFromData(fig, fmt.upper()) elif fmt == 'image/svg+xml': self._qpix_orig = QPixmap(svg_to_image(fig)) self._qpix_buffer = [self._qpix_orig] self.fwidth = self._qpix_orig.width() self.fheight = self._qpix_orig.height()
def get_icon(iconpath, size=None): image = QImage(iconpath) if size is not None: qsize = QtCore.QSize(*size) image = image.scaled(qsize) pixmap = QPixmap.fromImage(image) iconw = QIcon(pixmap) return iconw
class SearchLineEdit(QLineEdit): """Line edit search widget with icon and remove all button""" def __init__(self, parent=None, icon=True): super(SearchLineEdit, self).__init__(parent) self.setTextMargins(1, 0, 20, 0) if icon: self.setTextMargins(18, 0, 20, 0) self._label = QLabel(self) self._pixmap_icon = QPixmap(get_image_path('conda_search.png')) self._label.setPixmap(self._pixmap_icon) self._label.setStyleSheet('''border: 0px; padding-bottom: 0px; padding-left: 2px;''') self._pixmap = QPixmap(get_image_path('conda_del.png')) self.button_clear = QToolButton(self) self.button_clear.setIcon(QIcon(self._pixmap)) self.button_clear.setIconSize(QSize(18, 18)) self.button_clear.setCursor(Qt.ArrowCursor) self.button_clear.setStyleSheet("""QToolButton {background: transparent; padding-right: 2px; border: none; margin:0px; }""") self.button_clear.setVisible(False) # Layout self._layout = QHBoxLayout(self) self._layout.addWidget(self.button_clear, 0, Qt.AlignRight) self._layout.setSpacing(0) self._layout.setContentsMargins(0, 2, 2, 0) # Signals and slots self.button_clear.clicked.connect(self.clear_text) self.textChanged.connect(self._toggle_visibility) self.textEdited.connect(self._toggle_visibility) def _toggle_visibility(self): """ """ if len(self.text()) == 0: self.button_clear.setVisible(False) else: self.button_clear.setVisible(True) def sizeHint(self): return QSize(200, self._pixmap_icon.height()) # Public api # ---------- def clear_text(self): """ """ self.setText('') self.setFocus()
def cmap2pixmap(cmap, steps=50): """Convert a Ginga colormap into a QPixmap """ inds = numpy.linspace(0, 1, steps) n = len(cmap.clst) - 1 tups = [ cmap.clst[int(x*n)] for x in inds ] rgbas = [QColor(int(r * 255), int(g * 255), int(b * 255), 255).rgba() for r, g, b in tups] im = QImage(steps, 1, QImage.Format_Indexed8) im.setColorTable(rgbas) for i in range(steps): im.setPixel(i, 0, i) im = im.scaled(128, 32) pm = QPixmap.fromImage(im) return pm
def test_save_figure_to_file(figbrowser, tmpdir, mocker, fmt, fext): """ Test saving png and svg figures to file with the figure browser. """ fig = add_figures_to_browser(figbrowser, 1, tmpdir, fmt)[0] expected_qpix = QPixmap() expected_qpix.loadFromData(fig, fmt.upper()) # Save the figure to disk with the figure browser. saved_figname = osp.join(to_text_string(tmpdir), 'spyfig' + fext) mocker.patch('spyder.plugins.plots.widgets.figurebrowser.getsavefilename', return_value=(saved_figname, fext)) figbrowser.save_figure() saved_qpix = QPixmap() saved_qpix.load(saved_figname) assert osp.exists(saved_figname) assert expected_qpix.toImage() == saved_qpix.toImage()
def test_save_thumbnails(figbrowser, tmpdir, qtbot, mocker, fmt): """ Test saving figures by clicking on the thumbnail icon. """ figs = add_figures_to_browser(figbrowser, 3, tmpdir, fmt) fext = '.svg' if fmt == 'image/svg+xml' else '.png' # Save the second thumbnail of the scrollbar. figname = osp.join(to_text_string(tmpdir), 'figname' + fext) mocker.patch('spyder.plugins.plots.widgets.figurebrowser.getsavefilename', return_value=(figname, fext)) qtbot.mouseClick( figbrowser.thumbnails_sb._thumbnails[1].savefig_btn, Qt.LeftButton) expected_qpix = QPixmap() expected_qpix.loadFromData(figs[1], fmt.upper()) saved_qpix = QPixmap() saved_qpix.load(figname) assert osp.exists(figname) assert expected_qpix.toImage() == saved_qpix.toImage()
def __alignment(self) -> None: """Menu of alignment function.""" def switch_icon(m: int, icon_name: str) -> Callable[[], None]: @Slot() def func() -> None: self.alignment_mode = m self.alignment_button.setIcon(QIcon(QPixmap(icon_name))) return func menu = QMenu(self) for i, (text, icon) in enumerate([ ("Vertical alignment", "vertical_align"), ("Horizontal alignment", "horizontal_align"), ]): icon = f":/icons/{icon}.png" action = QAction(QIcon(QPixmap(icon)), text, self) action.triggered.connect(switch_icon(i, icon)) menu.addAction(action) self.alignment_button.setMenu(menu) self.alignment_button.clicked.connect(self.point_alignment)
def show_expr(self) -> None: """Output as expression.""" expr = [vpoint.expr() for vpoint in self.vpoint_list] context = ",\n".join(" " * 4 + e for e in expr) script = _PREFIX + f"\"{self.project_widget.base_file_name()}\"\n" if context: script += f"M[\n{context}\n]" else: script += "M[]" dlg = ScriptDialog(QIcon(QPixmap(":/icons/id.png")), script, PMKSLexer, "Pyslvs expression", ["Text file (*.txt)"], self, compressed_script="M[" + ','.join(expr).replace(", ", ",") + "]" if expr else "") dlg.show() dlg.exec_() dlg.deleteLater()
def __init__(self, parent: MainWindowBase): """Create two widget page and using main window to make their parent.""" super(Collections, self).__init__(parent) layout = QVBoxLayout(self) self.tab_widget = QTabWidget(self) layout.addWidget(self.tab_widget) self.setWindowIcon(QIcon(QPixmap("icons:collections.png"))) self.structure_widget = StructureWidget(parent) self.configure_widget = ConfigureWidget( self.structure_widget.add_collection, parent) self.tab_widget.addTab(self.structure_widget, self.structure_widget.windowIcon(), "Structures") self.tab_widget.addTab(self.configure_widget, self.configure_widget.windowIcon(), "Configuration") self.structure_widget.configure_button.clicked.connect( lambda: self.tab_widget.setCurrentIndex(1)) self.structure_widget.layout_sender.connect( self.configure_widget.set_graph)
def __init__(self, parent, arr): QLabel.__init__(self) # we need to hold a reference to # arr because QImage doesn't copy the data # and the buffer must be alive as long # as the image is alive. self.arr = arr # we also need to pass in the row-stride to # the constructor, because we can't guarantee # that every row of the numpy data is # 4-byte aligned. Which Qt would require # if we didn't pass the stride. self.img = QImage(arr.data, arr.shape[1], arr.shape[0], arr.strides[0], QImage.Format_RGB888) self.pm = QPixmap.fromImage(self.img) self.setPixmap(self.pm) self.setAlignment(QtCore.Qt.AlignTop) self.setMinimumSize(100, 100)
def __add_result(self, result: Mapping[str, Any]) -> None: """Add result items, except add to the list.""" item = QListWidgetItem(result['algorithm']) interrupt = result['interrupted'] if interrupt == 'False': interrupt_icon = "task_completed.png" elif interrupt == 'N/A': interrupt_icon = "question.png" else: interrupt_icon = "interrupted.png" item.setIcon(QIcon(QPixmap(f":/icons/{interrupt_icon}"))) if interrupt == 'False': interrupt_text = "No interrupt." else: interrupt_text = f"Interrupt at: {interrupt}" text = f"{result['algorithm']} ({interrupt_text})" if interrupt == 'N/A': text += "\n※Completeness is unknown." item.setToolTip(text) self.result_list.addItem(item)
def __init__(self, *args, **kwargs): super(QuitApplicationDialog, self).__init__(*args, **kwargs) self.label_icon = QLabel() self.label_about = QLabel('Quit Anaconda Navigator?') self.button_ok = QPushButton('Yes') self.button_cancel = ButtonCancel('No') self.buttonbox = QDialogButtonBox(Qt.Horizontal) self.checkbox = QCheckBox("Don't show again") # Widget setup if CONF.get('main', 'hide_quit_dialog'): hide_dialog = Qt.Checked else: hide_dialog = Qt.Unchecked self.checkbox.setChecked(hide_dialog) self.buttonbox.addButton(self.button_ok, QDialogButtonBox.ActionRole) self.buttonbox.addButton(self.button_cancel, QDialogButtonBox.ActionRole) self.label_icon.setPixmap(QPixmap(images.ANACONDA_ICON_64_PATH)) self.setWindowTitle("Quit application") # Layouts h_layout = QHBoxLayout() h_layout.addWidget(self.label_icon, 0, Qt.AlignTop) h_layout.addSpacing(10) h_layout.addWidget(self.label_about) main_layout = QVBoxLayout() main_layout.addLayout(h_layout) main_layout.addWidget(self.checkbox, 0, Qt.AlignRight) main_layout.addSpacing(24) main_layout.addWidget(self.buttonbox) self.setLayout(main_layout) # Signals self.button_ok.clicked.connect(self.accept) self.button_cancel.clicked.connect(self.reject) # Setup self.update_style_sheet()
def __init__( self, vpoints: List[VPoint], vlinks: List[VLink], row: Union[int, bool], parent: QWidget ): """Input data reference from main window. + Needs VPoints and VLinks information. + If row is false: Create action. """ super(EditLinkDialog, self).__init__(parent) self.setupUi(self) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) self.vpoints = vpoints self.vlinks = vlinks icon = self.windowIcon() self.icon = QIcon(QPixmap("icons:bearing.png")) for i, e in enumerate(color_names): self.color_box.insertItem(i, color_icon(e), e) for i in range(len(self.vpoints)): self.no_selected.addItem(QListWidgetItem(self.icon, f'Point{i}')) if row is False: names = {vlink.name for vlink in self.vlinks} n = 1 name = f"link_{n}" while name in names: n += 1 name = f"link_{n}" self.name_edit.setText(name) self.name_box.setEnabled(False) self.name_box.addItem(icon, "New link") self.color_box.setCurrentIndex(self.color_box.findText('blue')) else: for i, vlink in enumerate(self.vlinks): self.name_box.insertItem(i, icon, vlink.name) self.name_box.setCurrentIndex(row) self.name_edit.textChanged.connect(self.__is_ok) self.__is_ok()
def set_content_list(self): """ Add items to the list, gradually. Called by a timer. """ for i in range(self.step, self.step + self.step_size): if i < len(self.content_info): item = self.content_info[i] banner = item.get('banner', '') path = item.get('image_file_path', '') content_item = ListItemContent( title=item['title'], subtitle=item.get('subtitle', "") or "", uri=item['uri'], date=item.get('date', '') or "", summary=item.get('summary', '') or "", tags=item.get('tags', []), banner=banner, path=path, pixmap=self.default_pixmap, ) self.list.addItem(content_item) # self.update_style_sheet(self.style_sheet) # This allows the content to look for the pixmap content_item.pixmaps = self.pixmaps # Use images shipped with Navigator, if no image try the # download image_file = item.get('image_file', 'NaN') local_image = os.path.join(LOGO_PATH, image_file) if os.path.isfile(local_image): self.pixmaps[path] = QPixmap(local_image) else: self.download_thumbnail(content_item, banner, path) else: self.timer_load.stop() self.sig_ready.emit(self._tab_name) break self.step += self.step_size self.filter_content()
def __init__(self, parent=None): super(Titlebar, self).__init__(parent) self.setObjectName("titlebar") self.setMouseTracking(True) self.menus = [] self.setAutoFillBackground(True) self.setFixedHeight(30) self.setContentsMargins(0, 0, 0, 0) self.setBackgroundRole(QPalette.Highlight) self.layout = QHBoxLayout(self) self.layout.setAlignment(Qt.AlignVCenter) self.layout.setAlignment(Qt.AlignLeft) self.layout.setContentsMargins(8, 0, 0, 0) self.layout.setSpacing(0) self.setLayout(self.layout) self.appLogoLabel = AppLogo(self) if qrainbowstyle.APP_ICON_PATH: self.appLogoLabel.setPixmap(QPixmap(qrainbowstyle.APP_ICON_PATH)) self.layout.setContentsMargins(2, 0, 0, 0) self.layout.addWidget(self.appLogoLabel) if qrainbowstyle.ALIGN_BUTTONS_LEFT: self.appLogoLabel.setVisible(False) self.layout.setContentsMargins(8, 0, 0, 0) self.layout.insertStretch(50) self.buttonsWidget = ButtonsWidget(self) if qrainbowstyle.ALIGN_BUTTONS_LEFT: self.layout.insertWidget(0, self.buttonsWidget) else: self.layout.addWidget(self.buttonsWidget) # auto connect signals QMetaObject.connectSlotsByName(self) if self.window().parent() is not None: self.buttonsWidget.btnRestore.setVisible(False) self.buttonsWidget.btnMaximize.setVisible(False) self.buttonsWidget.btnMinimize.setVisible(False)
def create_splash_screen(): """Create splash screen.""" if not running_under_pytest(): image = QImage(500, 400, QImage.Format_ARGB32_Premultiplied) image.fill(0) painter = QPainter(image) renderer = QSvgRenderer(get_image_path('splash')) renderer.render(painter) painter.end() pm = QPixmap.fromImage(image) pm = pm.copy(0, 0, 500, 400) splash = QSplashScreen(pm) splash_font = splash.font() splash_font.setPixelSize(14) splash.setFont(splash_font) else: splash = None return splash
def __init__( self, env: str, file_name: str, vpoints: Sequence[VPoint], v_to_slvs: Callable[[], Iterable[Tuple[int, int]]], parent: QWidget ): """Comes in environment variable and project name.""" super(OutputDialog, self).__init__(parent) self.setupUi(self) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) self.setWindowTitle(f"Export {self.format_name} module project") self.setWindowIcon(QIcon(QPixmap(f":/icons/{self.format_icon}"))) self.assembly_label.setText(self.assembly_description) self.frame_label.setText(self.frame_description) self.path_edit.setPlaceholderText(env) self.filename_edit.setPlaceholderText(file_name) self.vpoints = vpoints self.v_to_slvs = v_to_slvs
def _on_colormap_change(self, event=None): """Receive layer model colormap change event and update dropdown menu. Parameters ---------- event : napari.utils.event.Event, optional The napari event that triggered this method, by default None. """ name = self.layer.colormap.name if name not in self.colormapComboBox._allitems: self.colormapComboBox._allitems.add(name) self.colormapComboBox.addItem(name) if name != self.colormapComboBox.currentText(): self.colormapComboBox.setCurrentText(name) # Note that QImage expects the image width followed by height cbar = self.layer.colormap.colorbar image = QImage( cbar, cbar.shape[1], cbar.shape[0], QImage.Format_RGBA8888, ) self.colorbarLabel.setPixmap(QPixmap.fromImage(image))
def show_message_box(text, info_text="", buttons=QMessageBox.Ok): """ Shows a message box :param text: :param info_text: :param buttons: :return: """ message_box = QMessageBox() try: message_box.setIconPixmap(QPixmap( ":/res/ui/guiscrcpy_logo.png").scaledToHeight(100)) except Exception as e: print("WARN: {e}: loading guiscrcpy " "message box pixmap failed. " "Ignoring".format(e=e)) message_box.setText("<b>{}</b>".format(text)) message_box.setTextFormat(QtCore.Qt.RichText) message_box.setInformativeText(info_text) message_box.setStandardButtons(buttons) return message_box
def gui_qt(*, startup_logo=False): """Start a Qt event loop in which to run the application. Parameters ---------- startup_logo : bool Show a splash screen with the napari logo during startup. Notes ----- This context manager is not needed if running napari within an interactive IPython session. In this case, use the ``%gui qt`` magic command, or start IPython with the Qt GUI event loop enabled by default by using ``ipython --gui=qt``. """ splash_widget = None app = QApplication.instance() if not app: # automatically determine monitor DPI. # Note: this MUST be set before the QApplication is instantiated QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # if this is the first time the Qt app is being instantiated, we set # the name, so that we know whether to raise_ in Window.show() app = QApplication(sys.argv) app.setApplicationName('napari') if startup_logo: logopath = join(dirname(__file__), '..', 'resources', 'logo.png') pm = QPixmap(logopath).scaled( 360, 360, Qt.KeepAspectRatio, Qt.SmoothTransformation ) splash_widget = QSplashScreen(pm) splash_widget.show() yield app # if the application already existed before this function was called, # there's no need to start it again. By avoiding unnecessary calls to # ``app.exec_``, we avoid blocking. if app.applicationName() == 'napari': if splash_widget and startup_logo: splash_widget.close() app.exec_()
def _add_buttons(self, workflows: List[WorkflowDefinition]): """ Add all buttons given a List of WorkflowDefinitions """ for workflow in workflows: # Some images are RGBA and others are Grayscale # TODO?: convert all images to RBGA pre: np.ndarray = workflow.thumbnail_pre post: np.ndarray = workflow.thumbnail_post # TODO: We need a way to a) track dimension order if present in metadata and b) try to guess dimension order color_channel_size: int = min(np.shape(workflow.thumbnail_pre)) min_index: int = np.shape(workflow.thumbnail_pre).index(color_channel_size) # If RGBA convert to grayscale if len(workflow.thumbnail_pre.shape) > 2: # cv2 expects color channel dim to be last index pre = cv2.cvtColor(np.moveaxis(workflow.thumbnail_pre, min_index, -1), cv2.COLOR_RGBA2GRAY) if len(workflow.thumbnail_post.shape) > 2: # cv2 expects color channel dim to be last index post = cv2.cvtColor(np.moveaxis(workflow.thumbnail_post, min_index, -1), cv2.COLOR_RGBA2GRAY) # Stitch Image image_stitched: np.ndarray = np.hstack([pre, post]) button: QPushButton = QPushButton("") # Get np image into QPixmap image: QPixmap = QPixmap( QImage(image_stitched.data, image_stitched.shape[1], image_stitched.shape[0], QImage.Format_Indexed8) ) button.setIcon(QIcon(image)) button.setIconSize(QtCore.QSize(PAGE_CONTENT_WIDTH - 40, 200)) button.setFixedSize(PAGE_CONTENT_WIDTH, 200) button.setToolTip(workflow.name) button.setEnabled(False) button.setObjectName(workflow.name) button.clicked.connect(self._workflow_button_clicked) self.layout().addWidget(button)
def drawImage(self): if self._imageData is None: self._scene.setImage(QPixmap()) return img_buf = self._imageData.astype(np.float) if (self._intensityMin is None) or (self._intensityMax is None): self._intensityMin = np.min(img_buf) self._intensityMax = np.max(img_buf) img_buf -= float(self._intensityMin) img_buf *= 255. / float(self._intensityMax - self._intensityMin) np.clip(img_buf, 0., 255., img_buf) # convert grayscale to RGB 32bit # far faster than calling img_buf.astype(np.uint8).repeat(4) qi = np.empty((img_buf.shape[0], img_buf.shape[1], 4), dtype=np.uint8) qi[:, :, 0] = qi[:, :, 1] = qi[:, :, 2] = qi[:, :, 3] = img_buf # prevent QImage from being garbage collected self._qImg = QImage(qi, self._imageData.shape[1], self._imageData.shape[0], QImage.Format_RGB32) self._scene.setImage(self._qImg)
def _on_colormap_change(self): """Receive layer model colormap change event and update dropdown menu.""" name = self.layer.colormap.name if name not in self.colormapComboBox._allitems: cm = AVAILABLE_COLORMAPS.get(name) if cm: self.colormapComboBox._allitems.add(name) self.colormapComboBox.addItem(cm._display_name, name) if name != self.colormapComboBox.currentData(): index = self.colormapComboBox.findData(name) self.colormapComboBox.setCurrentIndex(index) # Note that QImage expects the image width followed by height cbar = self.layer.colormap.colorbar image = QImage( cbar, cbar.shape[1], cbar.shape[0], QImage.Format_RGBA8888, ) self.colorbarLabel.setPixmap(QPixmap.fromImage(image))
def __init__(self, *args, **kwargs): super(OpenSpaceDataViewer, self).__init__(*args, **kwargs) self._logo = QLabel() self._image = QPixmap.fromImage(QImage(LOGO)) self._logo.setPixmap(self._image) self._logo.setAlignment(Qt.AlignCenter) self._ip = QLineEdit() self._ip.setText('ws://localhost:4682/websocket') self._button = QPushButton('Connect') self._button.clicked.connect(self.connect_to_openspace) self._layout = QVBoxLayout() self._layout.addWidget(self._logo) self._horizontal = QHBoxLayout() self._horizontal.addWidget(self._ip) self._horizontal.addWidget(self._button) self._layout.addLayout(self._horizontal) self._main = QWidget() self._main.setLayout(self._layout) self.setCentralWidget(self._main)
def __init__(self, icons, icon_size, short_desc, long_desc, parent=None): """Initialize the HelpDialog.""" super().__init__(parent) assert len(icons.values()) == len(short_desc) == len(long_desc) layout = QGridLayout() for idx, icon in enumerate(icons.values()): pix = QPixmap(icon.pixmap(*icon_size)) label = QLabel() label.setPixmap(pix) layout.addWidget(label, idx, 0) layout.addWidget(QLabel('<b>' + short_desc[idx] + '</b>'), idx, 1) layout.addWidget(QLabel(long_desc[idx]), idx, 2) self.ok_button = QPushButton("OK") self.ok_button.clicked.connect(self.close) layout.addWidget(self.ok_button, idx + 1, 0, 1, 3) self.setWindowTitle("Help") self.setModal(True) self.setLayout(layout)
def __init__(self): """Main Window UI를 설정한다.""" super().__init__() self.setWindowTitle(f"Typing Number - {VER}") icon = QIcon() icon.addPixmap(QPixmap(r'ok_64x64.ico'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.setMinimumSize(800, 100) # Typing Info self.typing = ManageTyping() # Setup StatusBar self.statusBar().showMessage("") self.statusBar().addPermanentWidget(VLine()) self.label_typing_avg = QLabel("평균타수 : 0.0타/초", self) self.statusBar().addPermanentWidget(self.label_typing_avg) self.statusBar().addPermanentWidget(VLine()) self.label_total_time = QLabel("총 연습시간", self) self.statusBar().addPermanentWidget(self.label_total_time) # Setup LineEdit self.line_for_number = QLineEdit(self) self.line_for_typing = QLineEdit(self) self.line_for_error = QLineEdit(self) self.setup_lineedit() vbox = QVBoxLayout() vbox.addWidget(self.line_for_number) vbox.addWidget(self.line_for_typing) vbox.addWidget(self.line_for_error) central_widget = QWidget(self) central_widget.setLayout(vbox) self.setCentralWidget(central_widget) self.new_game()
def _on_colormap_change(self, event=None): """Receive layer model colormap change event and update dropdown menu. Parameters ---------- event : qtpy.QtCore.QEvent, optional. Event from the Qt context, by default None. """ name = self.layer.colormap[0] if name not in self.colormapComboBox._allitems: self.colormapComboBox._allitems.add(name) self.colormapComboBox.addItem(name) if name != self.colormapComboBox.currentText(): self.colormapComboBox.setCurrentText(name) # Note that QImage expects the image width followed by height image = QImage( self.layer._colorbar, self.layer._colorbar.shape[1], self.layer._colorbar.shape[0], QImage.Format_RGBA8888, ) self.colorbarLabel.setPixmap(QPixmap.fromImage(image))
def __structure_list_context_menu(self, point) -> None: """Context menu for the type synthesis results.""" index = self.structure_list.currentIndex().row() self.to_collection.setEnabled(index > -1) self.copy_edges.setEnabled(index > -1) self.copy_image.setEnabled(index > -1) action = self.pop_menu_topo.exec_(self.structure_list.mapToGlobal(point)) if not action: return clipboard = QApplication.clipboard() if action == self.to_collection: self.add_collection(self.answer[index].edges) elif action == self.copy_edges: clipboard.setText(str(self.answer[index].edges)) elif action == self.copy_image: # Turn the transparent background to white image1 = self.__atlas_image() image2 = QImage(image1.size(), image1.format()) image2.fill(Qt.white) painter = QPainter(image2) painter.drawImage(QPointF(0, 0), image1) painter.end() clipboard.setPixmap(QPixmap.fromImage(image2))
def __init__(self): """Init Main Window.""" super().__init__() # Title and set icon self.setWindowTitle(f"LightsOut by ok97465 - {VER}") icon = QIcon() icon.addPixmap(QPixmap(r'ok_64x64.ico'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) # Setup toolbar self.toolbar = QToolBar() self.new_btn = None self.clear_btn = None self.n_lights_1axis_spinbox = None self.show_solution_chkbox = None self.setup_toolbar() # Setup Button self.btn_grid_table = QTableWidget(self) # Setup Status Bar self.n_clicked = 0 self.clicked_label = QLabel("0", self) self.n_solution_1_label = QLabel("0", self) self.setup_status_bar() # Setup info of lights out self.manage_puzzle = ManageLightsOutPuzzle() self.new_game() # Setup Main Layout self.setCentralWidget(self.btn_grid_table) self.resize_main_window() QTimer.singleShot(100, self.resize_main_window)
def gui_qt(*, startup_logo=False): """Start a Qt event loop in which to run the application. Parameters ---------- startup_logo : bool Show a splash screen with the napari logo during startup. Notes ----- This context manager is not needed if running napari within an interactive IPython session. In this case, use the ``%gui qt`` magic command, or start IPython with the Qt GUI event loop enabled by default by using ``ipython --gui=qt``. """ app = QApplication.instance() or QApplication(sys.argv) if startup_logo: logopath = join(dirname(__file__), '..', 'resources', 'logo.png') splash_widget = QSplashScreen(QPixmap(logopath).scaled(400, 400)) splash_widget.show() yield if startup_logo: splash_widget.close() app.exec_()
def test_autofit_figure_viewer(figbrowser, tmpdir, fmt): """ Test figure diplayed when `Fit plots to window` is True. """ fig = add_figures_to_browser(figbrowser, 1, tmpdir, fmt)[0] figviewer = figbrowser.figviewer figcanvas = figviewer.figcanvas # Calculate original figure size in pixels. qpix = QPixmap() qpix.loadFromData(fig, fmt.upper()) fwidth, fheight = qpix.width(), qpix.height() # Test when `Fit plots to window` is set to True. # Otherwise, test should fall into `test_zoom_figure_viewer` figbrowser.change_auto_fit_plotting(True) size = figviewer.size() style = figviewer.style() width = (size.width() - style.pixelMetric(QStyle.PM_LayoutLeftMargin) - style.pixelMetric(QStyle.PM_LayoutRightMargin)) height = (size.height() - style.pixelMetric(QStyle.PM_LayoutTopMargin) - style.pixelMetric(QStyle.PM_LayoutBottomMargin)) if (fwidth / fheight) > (width / height): new_width = int(width) new_height = int(width / fwidth * fheight) else: new_height = int(height) new_width = int(height / fheight * fwidth) assert figcanvas.width() == new_width assert figcanvas.height() == new_height assert (figbrowser.zoom_disp_value == round(figcanvas.width() / fwidth * 100))
def __save_atlas(self) -> None: """Save function as same as type synthesis widget.""" count = self.collection_list.count() if count < 1: return lateral, ok = QInputDialog.getInt( self, "Atlas", "The number of lateral:", 5, 1 ) if not ok: return file_name = self.output_to("atlas image", qt_image_format) if not file_name: return icon_size = self.collection_list.iconSize() width = icon_size.width() image = self.collection_list.item(0).icon().pixmap(icon_size).toImage() image_main = QImage(QSize( lateral if count > lateral else count, (count // lateral) + bool(count % lateral) ) * width, image.format()) image_main.fill(Qt.transparent) painter = QPainter(image_main) for row in range(count): image = self.collection_list.item(row).icon().pixmap(icon_size).toImage() painter.drawImage(QPointF(row % lateral, row // lateral) * width, image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(file_name) self.save_reply_box("Atlas", file_name)
class FadingTipBox(FadingDialog): """ """ def __init__(self, parent, opacity, duration, easing_curve, tour=None, color_top=None, color_back=None, combobox_background=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets def toolbutton(icon): bt = QToolButton() bt.setAutoRaise(True) bt.setIcon(icon) return bt self.button_close = toolbutton(ima.icon("tour.close")) self.button_home = toolbutton(ima.icon("tour.home")) self.button_previous = toolbutton(ima.icon("tour.previous")) self.button_end = toolbutton(ima.icon("tour.end")) self.button_next = toolbutton(ima.icon("tour.next")) self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [ self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current ] arrow = get_image_path('hide.png') self.color_top = color_top self.color_back = color_back self.combobox_background = combobox_background self.stylesheet = '''QComboBox {{ padding-left: 5px; background-color: {} border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; }} QComboBox::drop-down {{ subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; }} QComboBox::down-arrow {{ image: url({}); }} '''.format(self.combobox_background.name(), arrow) # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu) # signals and slots # These are defined every time by the AnimatedTour Class def _disable_widgets(self): """ """ for widget in self.widgets: widget.setDisabled(True) def _enable_widgets(self): """ """ self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) for widget in self.widgets: widget.setDisabled(False) if self.button_disable == 'previous': self.button_previous.setDisabled(True) self.button_home.setDisabled(True) elif self.button_disable == 'next': self.button_next.setDisabled(True) self.button_end.setDisabled(True) def set_data(self, title, content, current, image, run, frames=None, step=None): """ """ self.label_title.setText(title) self.combo_title.clear() self.combo_title.addItems(frames) self.combo_title.setCurrentIndex(step) # min_content_len = max([len(f) for f in frames]) # self.combo_title.setMinimumContentsLength(min_content_len) # Fix and try to see how it looks with a combo box self.label_current.setText(current) self.button_current.setText(current) self.label_content.setText(content) self.image = image if image is None: self.label_image.setFixedHeight(1) self.label_image.setFixedWidth(1) else: extension = image.split('.')[-1] self.image = QPixmap(get_image_path(image), extension) self.label_image.setPixmap(self.image) self.label_image.setFixedSize(self.image.size()) if run is None: self.button_run.setVisible(False) else: self.button_run.setDisabled(False) self.button_run.setVisible(True) # Refresh layout self.layout().activate() def set_pos(self, x, y): """ """ self.x = ceil(x) self.y = ceil(y) self.move(QPoint(self.x, self.y)) def build_paths(self): """ """ geo = self.geometry() radius = 0 shadow = self.offset_shadow x0, y0 = geo.x(), geo.y() width, height = geo.width() - shadow, geo.height() - shadow left, top = 0, 0 right, bottom = width, height self.round_rect_path = QPainterPath() self.round_rect_path.moveTo(right, top + radius) self.round_rect_path.arcTo(right - radius, top, radius, radius, 0.0, 90.0) self.round_rect_path.lineTo(left + radius, top) self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.round_rect_path.lineTo(left, bottom - radius) self.round_rect_path.arcTo(left, bottom - radius, radius, radius, 180.0, 90.0) self.round_rect_path.lineTo(right - radius, bottom) self.round_rect_path.arcTo(right - radius, bottom - radius, radius, radius, 270.0, 90.0) self.round_rect_path.closeSubpath() # Top path header = 36 offset = 2 left, top = offset, offset right = width - (offset) self.top_rect_path = QPainterPath() self.top_rect_path.lineTo(right, top + radius) self.top_rect_path.moveTo(right, top + radius) self.top_rect_path.arcTo(right - radius, top, radius, radius, 0.0, 90.0) self.top_rect_path.lineTo(left + radius, top) self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.top_rect_path.lineTo(left, top + header) self.top_rect_path.lineTo(right, top + header) def paintEvent(self, event): """ """ self.build_paths() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillPath(self.round_rect_path, self.color_back) painter.fillPath(self.top_rect_path, self.color_top) painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1)) # TODO: Build the pointing arrow? def keyReleaseEvent(self, event): """ """ key = event.key() self.key_pressed = key keys = [ Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up, Qt.Key_Escape, Qt.Key_PageUp, Qt.Key_PageDown, Qt.Key_Home, Qt.Key_End, Qt.Key_Menu ] if key in keys: if not self.is_fade_running(): self.sig_key_pressed.emit() def mousePressEvent(self, event): """override Qt method""" # Raise the main application window on click self.parent.raise_() self.raise_() if event.button() == Qt.RightButton: pass # clicked_widget = self.childAt(event.x(), event.y()) # if clicked_widget == self.label_current: # self.context_menu_requested(event) def focusOutEvent(self, event): """Override Qt method.""" # To be used so tips do not appear outside spyder self.tour.lost_focus() def context_menu_requested(self, event): """ """ pos = QPoint(event.x(), event.y()) menu = QMenu(self) actions = [] action_title = create_action(self, _('Go to step: '), icon=QIcon()) action_title.setDisabled(True) actions.append(action_title) # actions.append(create_action(self, _(': '), icon=QIcon())) add_actions(menu, actions) menu.popup(self.mapToGlobal(pos)) def reject(self): """Qt method to handle escape key event""" if not self.is_fade_running(): key = Qt.Key_Escape self.key_pressed = key self.sig_key_pressed.emit()
class FigureCanvas(QFrame): """ A basic widget on which can be painted a custom png, jpg, or svg image. """ def __init__(self, parent=None, background_color=None): super(FigureCanvas, self).__init__(parent) self.setLineWidth(2) self.setMidLineWidth(1) self.setObjectName("figcanvas") self.setStyleSheet("#figcanvas {background-color:" + str(background_color) + "}") self.fig = None self.fmt = None self.fwidth, self.fheight = 200, 200 self._blink_flag = False self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu_requested) def context_menu_requested(self, event): """Popup context menu.""" if self.fig: pos = QPoint(event.x(), event.y()) context_menu = QMenu(self) context_menu.addAction(ima.icon('editcopy'), "Copy Image", self.copy_figure, QKeySequence(get_shortcut('plots', 'copy'))) context_menu.popup(self.mapToGlobal(pos)) @Slot() def copy_figure(self): """Copy figure to clipboard.""" if self.fmt in ['image/png', 'image/jpeg']: qpixmap = QPixmap() qpixmap.loadFromData(self.fig, self.fmt.upper()) QApplication.clipboard().setImage(qpixmap.toImage()) elif self.fmt == 'image/svg+xml': svg_to_clipboard(self.fig) else: return self.blink_figure() def blink_figure(self): """Blink figure once.""" if self.fig: self._blink_flag = not self._blink_flag self.repaint() if self._blink_flag: timer = QTimer() timer.singleShot(40, self.blink_figure) def clear_canvas(self): """Clear the figure that was painted on the widget.""" self.fig = None self.fmt = None self._qpix_buffer = [] self.repaint() def load_figure(self, fig, fmt): """ Load the figure from a png, jpg, or svg image, convert it in a QPixmap, and force a repaint of the widget. """ self.fig = fig self.fmt = fmt if fmt in ['image/png', 'image/jpeg']: self._qpix_orig = QPixmap() self._qpix_orig.loadFromData(fig, fmt.upper()) elif fmt == 'image/svg+xml': self._qpix_orig = QPixmap(svg_to_image(fig)) self._qpix_buffer = [self._qpix_orig] self.fwidth = self._qpix_orig.width() self.fheight = self._qpix_orig.height() def paintEvent(self, event): """Qt method override to paint a custom image on the Widget.""" super(FigureCanvas, self).paintEvent(event) # Prepare the rect on which the image is going to be painted : fw = self.frameWidth() rect = QRect(0 + fw, 0 + fw, self.size().width() - 2 * fw, self.size().height() - 2 * fw) if self.fig is None or self._blink_flag: return # Check/update the qpixmap buffer : qpix2paint = None for qpix in self._qpix_buffer: if qpix.size().width() == rect.width(): qpix2paint = qpix break else: if self.fmt in ['image/png', 'image/jpeg']: qpix2paint = self._qpix_orig.scaledToWidth( rect.width(), mode=Qt.SmoothTransformation) elif self.fmt == 'image/svg+xml': qpix2paint = QPixmap(svg_to_image(self.fig, rect.size())) self._qpix_buffer.append(qpix2paint) if qpix2paint is not None: # Paint the image on the widget : qp = QPainter() qp.begin(self) qp.drawPixmap(rect, qpix2paint) qp.end()
def update_image(self): width = self.width() pm = QPixmap.fromImage(self.img) pm = pm.scaledToWidth(width) self.setPixmap(pm)
class FadingTipBox(FadingDialog): """ """ def __init__(self, parent, opacity, duration, easing_curve, tour=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.color_top = QColor.fromRgb(230, 230, 230) self.color_back = QColor.fromRgb(255, 255, 255) self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets def toolbutton(icon): bt = QToolButton() bt.setAutoRaise(True) bt.setIcon(icon) return bt self.button_close = toolbutton(ima.icon("tour.close")) self.button_home = toolbutton(ima.icon("tour.home")) self.button_previous = toolbutton(ima.icon("tour.previous")) self.button_end = toolbutton(ima.icon("tour.end")) self.button_next = toolbutton(ima.icon("tour.next")) self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current] arrow = get_image_path('hide.png') self.stylesheet = '''QComboBox { padding-left: 5px; background-color: rgbs(230,230,230,100%); border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; } QComboBox::down-arrow { image: url(''' + arrow + '''); } ''' # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu) # signals and slots # These are defined every time by the AnimatedTour Class def _disable_widgets(self): """ """ for widget in self.widgets: widget.setDisabled(True) def _enable_widgets(self): """ """ self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) for widget in self.widgets: widget.setDisabled(False) if self.button_disable == 'previous': self.button_previous.setDisabled(True) self.button_home.setDisabled(True) elif self.button_disable == 'next': self.button_next.setDisabled(True) self.button_end.setDisabled(True) def set_data(self, title, content, current, image, run, frames=None, step=None): """ """ self.label_title.setText(title) self.combo_title.clear() self.combo_title.addItems(frames) self.combo_title.setCurrentIndex(step) # min_content_len = max([len(f) for f in frames]) # self.combo_title.setMinimumContentsLength(min_content_len) # Fix and try to see how it looks with a combo box self.label_current.setText(current) self.button_current.setText(current) self.label_content.setText(content) self.image = image if image is None: self.label_image.setFixedHeight(1) self.label_image.setFixedWidth(1) else: extension = image.split('.')[-1] self.image = QPixmap(get_image_path(image), extension) self.label_image.setPixmap(self.image) self.label_image.setFixedSize(self.image.size()) if run is None: self.button_run.setVisible(False) else: self.button_run.setDisabled(False) self.button_run.setVisible(True) # Refresh layout self.layout().activate() def set_pos(self, x, y): """ """ self.x = x self.y = y self.move(QPoint(x, y)) def build_paths(self): """ """ geo = self.geometry() radius = 0 shadow = self.offset_shadow x0, y0 = geo.x(), geo.y() width, height = geo.width() - shadow, geo.height() - shadow left, top = 0, 0 right, bottom = width, height self.round_rect_path = QPainterPath() self.round_rect_path.moveTo(right, top + radius) self.round_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0) self.round_rect_path.lineTo(left+radius, top) self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.round_rect_path.lineTo(left, bottom-radius) self.round_rect_path.arcTo(left, bottom-radius, radius, radius, 180.0, 90.0) self.round_rect_path.lineTo(right-radius, bottom) self.round_rect_path.arcTo(right-radius, bottom-radius, radius, radius, 270.0, 90.0) self.round_rect_path.closeSubpath() # Top path header = 36 offset = 2 left, top = offset, offset right = width - (offset) self.top_rect_path = QPainterPath() self.top_rect_path.lineTo(right, top + radius) self.top_rect_path.moveTo(right, top + radius) self.top_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0) self.top_rect_path.lineTo(left+radius, top) self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0) self.top_rect_path.lineTo(left, top + header) self.top_rect_path.lineTo(right, top + header) def paintEvent(self, event): """ """ self.build_paths() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillPath(self.round_rect_path, self.color_back) painter.fillPath(self.top_rect_path, self.color_top) painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1)) # TODO: Build the pointing arrow? def keyReleaseEvent(self, event): """ """ key = event.key() self.key_pressed = key keys = [Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up, Qt.Key_Escape, Qt.Key_PageUp, Qt.Key_PageDown, Qt.Key_Home, Qt.Key_End, Qt.Key_Menu] if key in keys: if not self.is_fade_running(): self.sig_key_pressed.emit() def mousePressEvent(self, event): """override Qt method""" # Raise the main application window on click self.parent.raise_() self.raise_() if event.button() == Qt.RightButton: pass # clicked_widget = self.childAt(event.x(), event.y()) # if clicked_widget == self.label_current: # self.context_menu_requested(event) def focusOutEvent(self, event): """Override Qt method.""" # To be used so tips do not appear outside spyder self.tour.lost_focus() def context_menu_requested(self, event): """ """ pos = QPoint(event.x(), event.y()) menu = QMenu(self) actions = [] action_title = create_action(self, _('Go to step: '), icon=QIcon()) action_title.setDisabled(True) actions.append(action_title) # actions.append(create_action(self, _(': '), icon=QIcon())) add_actions(menu, actions) menu.popup(self.mapToGlobal(pos)) def reject(self): """Qt method to handle escape key event""" if not self.is_fade_running(): key = Qt.Key_Escape self.key_pressed = key self.sig_key_pressed.emit()
def __init__(self, viewer): super().__init__() QCoreApplication.setAttribute( Qt.AA_UseStyleSheetPropagationInWidgetStyles, True ) self.viewer = viewer self.dims = QtDims(self.viewer.dims) self.controls = QtControls(self.viewer) self.layers = QtLayerList(self.viewer.layers) self.buttons = QtLayersButtons(self.viewer) self.console = QtConsole({'viewer': self.viewer}) if self.console.shell is not None: self.console.style().unpolish(self.console) self.console.style().polish(self.console) self.console.hide() self.buttons.consoleButton.clicked.connect( lambda: self._toggle_console() ) else: self.buttons.consoleButton.setEnabled(False) self.canvas = SceneCanvas(keys=None, vsync=True) self.canvas.native.setMinimumSize(QSize(200, 200)) self.canvas.connect(self.on_mouse_move) self.canvas.connect(self.on_mouse_press) self.canvas.connect(self.on_mouse_release) self.canvas.connect(self.on_key_press) self.canvas.connect(self.on_key_release) self.canvas.connect(self.on_draw) self.view = self.canvas.central_widget.add_view() self._update_camera() center = QWidget() center_layout = QVBoxLayout() center_layout.setContentsMargins(15, 20, 15, 10) center_layout.addWidget(self.canvas.native) center_layout.addWidget(self.dims) center.setLayout(center_layout) right = QWidget() right_layout = QVBoxLayout() right_layout.addWidget(self.layers) right_layout.addWidget(self.buttons) right.setLayout(right_layout) right.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) left = self.controls top = QWidget() top_layout = QHBoxLayout() top_layout.addWidget(left) top_layout.addWidget(center) top_layout.addWidget(right) top.setLayout(top_layout) self.setOrientation(Qt.Vertical) self.addWidget(top) if self.console.shell is not None: self.addWidget(self.console) self._last_visited_dir = str(Path.home()) self._cursors = { 'disabled': QCursor( QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20) ), 'cross': Qt.CrossCursor, 'forbidden': Qt.ForbiddenCursor, 'pointing': Qt.PointingHandCursor, 'standard': QCursor(), } self._update_palette(viewer.palette) self._key_release_generators = {} self.viewer.events.interactive.connect(self._on_interactive) self.viewer.events.cursor.connect(self._on_cursor) self.viewer.events.reset_view.connect(self._on_reset_view) self.viewer.events.palette.connect( lambda event: self._update_palette(event.palette) ) self.viewer.layers.events.reordered.connect(self._update_canvas) self.viewer.dims.events.display.connect( lambda event: self._update_camera() ) self.setAcceptDrops(True)
def png_to_qimage(png): """Return a QImage from the raw data of a png image.""" qpix = QPixmap() qpix.loadFromData(png, 'image/png'.upper()) return qpix.toImage()
def get_image_label(name, default="not_found.png"): """Return image inside a QLabel object""" label = QLabel() label.setPixmap(QPixmap(get_image_path(name, default))) return label
class FigureCanvas(QFrame): """ A basic widget on which can be painted a custom png, jpg, or svg image. """ def __init__(self, parent=None): super(FigureCanvas, self).__init__(parent) self.setLineWidth(2) self.setMidLineWidth(1) self.setStyleSheet("background-color: white") self.fig = None self.fmt = None self.fwidth, self.fheight = 200, 200 def clear_canvas(self): """Clear the figure that was painted on the widget.""" self.fig = None self.fmt = None self._qpix_buffer = [] self.repaint() def load_figure(self, fig, fmt): """ Load the figure from a png, jpg, or svg image, convert it in a QPixmap, and force a repaint of the widget. """ self.fig = fig self.fmt = fmt if fmt in ['image/png', 'image/jpeg']: self._qpix_orig = QPixmap() self._qpix_orig.loadFromData(fig, fmt.upper()) elif fmt == 'image/svg+xml': self._qpix_orig = QPixmap(svg_to_image(fig)) self._qpix_buffer = [self._qpix_orig] self.fwidth = self._qpix_orig.width() self.fheight = self._qpix_orig.height() def paintEvent(self, event): """Qt method override to paint a custom image on the Widget.""" super(FigureCanvas, self).paintEvent(event) # Prepare the rect on which the image is going to be painted : fw = self.frameWidth() rect = QRect(0 + fw, 0 + fw, self.size().width() - 2 * fw, self.size().height() - 2 * fw) if self.fig is None: return # Check/update the qpixmap buffer : qpix2paint = None for qpix in self._qpix_buffer: if qpix.size().width() == rect.width(): qpix2paint = qpix break else: if self.fmt in ['image/png', 'image/jpeg']: qpix2paint = self._qpix_orig.scaledToWidth( rect.width(), mode=Qt.SmoothTransformation) elif self.fmt == 'image/svg+xml': qpix2paint = QPixmap(svg_to_image(self.fig, rect.size())) self._qpix_buffer.append(qpix2paint) if qpix2paint is not None: # Paint the image on the widget : qp = QPainter() qp.begin(self) qp.drawPixmap(rect, qpix2paint) qp.end()
class MapGraphicsScene(QGraphicsScene): """Graphics scene for showing a slippy map. """ sigZoomChanged = Signal(int) 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) @Slot() def close(self): self._tileSource.close() def setTileSource(self, newTileSource): self._tileSource.tileReceived.disconnect(self.setTilePixmap) self._tileSource.close() self._tilePixmaps.clear() self._tileInDownload = list() self._tileSource = newTileSource self._tileSource.setParent(self) self._tileSource.tileReceived.connect(self.setTilePixmap) self.requestTiles() self.invalidate() self.update() @Slot(QRectF) def onSceneRectChanged(self, rect): """Callback for the changing of the visible rect. Evaluate the visible tiles and request to load the new tiles. Args: rect(QRectF): Current visible area. """ tdim = self._tileSource.tileSize() center = rect.center() ct = self.tileFromPos(center.x(), center.y()) tx = ct.x() ty = ct.y() width = rect.width() height = rect.height() # top left corner of the center tile xp = int(width / 2.0 - (tx - floor(tx)) * tdim) yp = int(height / 2.0 - (ty - floor(ty)) * tdim) # first tile vertical and horizontal xs = tx - (xp + tdim - 1) / tdim ys = ty - (yp + tdim - 1) / tdim # last tile vertical and horizontal xe = (width - xp - 1) / tdim - xs + 1 + tx ye = (height - yp - 1) / tdim - ys + 1 + ty # define the rect of visible tiles self._tilesRect = QRect(xs, ys, xe, ye) # Request the loading of new tiles (if needed) self.requestTiles() self.invalidate() self.update() def drawBackground(self, painter, rect): """Draw the background tiles. If a tile is not available, draw a gray rectangle. Args: painter(QPainter): Painter for drawing. rect(QRectF): Current visible area. """ tilesRect = self._tilesRect left = tilesRect.left() top = tilesRect.top() numXtiles = tilesRect.width() numYtiles = tilesRect.height() tdim = self._tileSource.tileSize() pixRect = QRectF(0.0, 0.0, tdim, tdim) emptyTilePix = self._emptyTile tilePixmaps = self._tilePixmaps for x in iterRange(numXtiles+1): for y in iterRange(numYtiles+1): tp = (x + left, y + top) box = self.tileRect(tp[0], tp[1]) # Use default gray image if tile image is missing pix = tilePixmaps.get(tp, emptyTilePix) painter.drawPixmap(box, pix, pixRect) def zoomTo(self, pos, zoomlevel): """Zoom to a specific zoom level. If the level is out of range, the zoom action is ignored. clear the current tile cache, evaluate the new center and update the position of all the items. Args: zoomlevel(int): New zoom level. """ tileSource = self._tileSource if zoomlevel > tileSource.maxZoom() or zoomlevel < tileSource.minZoom(): return # Get the coordinates of the center using the position in pixels of the mouse pos_corr = self.views()[0].mapToScene(pos) coord = self.lonLatFromPos(pos_corr.x(), pos_corr.y()) # Set the new zoom level self._zoom = zoomlevel # Clear cache and abort active requests self._tileSource.abortAllRequests() self._tilePixmaps.clear() # Re-center map so that the point on which it was zoomed is in the same position self.setCenter(coord[0], coord[1]) pos_corr = self.views()[0].mapToScene(pos) center = self.sceneRect().center() self.translate(center.x() - pos_corr.x(), center.y() - pos_corr.y()) self.sigZoomChanged.emit(zoomlevel) def zoomIn(self, pos=None): """Increments the zoom level Args: pos (QPointF): Center position, Latitude and Longitude. Default None for the current center position. """ if pos is None: pos = self.sceneRect().center() self.zoomTo(pos, self._zoom + 1) def zoomOut(self, pos=None): """Decrements the zoom level Args: pos (QPointF): Center position, Latitude and Longitude. Default None for the current center position. """ if pos is None: pos = self.sceneRect().center() self.zoomTo(pos, self._zoom - 1) def zoom(self): return self._zoom @Slot(int, int, int, QPixmap) def setTilePixmap(self, x, y, zoom, pixmap): """Set the image of the tile. Args: x(int): X coordinate of the tile. y(int): Y coordinate of the tile. zoom(int): Zoom coordinate of the tile. pixmap(QPixmap): Image for the tile. """ if self._zoom == zoom: self._tilePixmaps[(x, y)] = pixmap self.update() def requestTiles(self): """Request the loading of tiles. Check the loaded tiles and requests only the missing tiles. """ tilesRect = self._tilesRect tilePixmaps = self._tilePixmaps numXtiles = tilesRect.width() numYtiles = tilesRect.height() left = tilesRect.left() top = tilesRect.top() tileSource = self._tileSource zoom = self._zoom # Request load of new tiles for x in iterRange(numXtiles): for y in iterRange(numYtiles): tp = (left + x, top + y) # Request tile only if missing if tp not in tilePixmaps: pix = tileSource.requestTile(tp[0], tp[1], zoom) if pix is not None: tilePixmaps[tp] = pix self.update() def tileRect(self, tx, ty): """Area for a specific tile. Args: tx(int): X coordinate of the tile. ty(int): Y coordinate of the tile. Returns: QRectF, the area of the tile. """ tdim = self._tileSource.tileSize() return QRectF(tx * tdim, ty * tdim, tdim, tdim) def setSize(self, width, height): """Set the size of the visible area in pixels. Update the scene rect. Args: width(int): Width of the visible area. height(int): Height of the visible area. """ rect = QRectF(self.sceneRect().topLeft(), QSizeF(width, height)) self.setSceneRect(rect) def setCenter(self, lon, lat): """Move the center of the visible area to new coordinates. Update the scene rect. Args: lon(float): New longitude of the center. lat(float): New latitude of the center. """ rect = QRectF(self.sceneRect()) pos = self.posFromLonLat(lon, lat) rect.moveCenter(QPointF(pos[0], pos[1])) self.setSceneRect(rect) def center(self): centerPos = self.sceneRect().center() centerCoord = self.lonLatFromPos(centerPos.x(), centerPos.y()) return QPointF(centerCoord[0], centerCoord[1]) def translate(self, dx, dy): """Translate the visible area by dx, dy pixels. Update the scene rect. Args: dx(int): Increments for the center x coord in pixels. dy(int): Increments for the center y coord in pixels. """ self.setSceneRect(self.sceneRect().translated(dx, dy)) def posFromLonLat(self, lon, lat): """Position in scene coordinate of the WGS84 coordinates. Convert from WGS84 reference system to scene reference system. Args: lon(float or numpy.ndarray): Longitude value or values. lat(float or numpy.ndarray): Latitude value or values. Returns: tuple: (x, y) with the positions of the input coordinates. """ return posFromLonLat(lon, lat, self._zoom, self._tileSource.tileSize()) def lonLatFromPos(self, x, y): """Position in WGS84 coordinate of the scene coordinates. Convert from scene reference system to WGS84 reference system. Args: x(float, int or numpy.ndarray): X value or values. y(float, int or numpy.ndarray): Y value or values. Returns: tuple: (lon, lat) with the coordinates of the input positions. """ return lonLatFromPos(x, y, self._zoom, self._tileSource.tileSize()) def tileFromPos(self, x, y): """Tile in the selected position. Args: x(float, int): X value for position. y(float, int): Y value for position. Returns: QPointF with the coordinates of the tile. """ tdim = float(self._tileSource.tileSize()) return QPointF(x / tdim, y / tdim) def addCircle(self, longitude, latitude, radius): """Add a new circle to the graphics scene. Args: longitude(float): Longitude of the center of the circle. latitude(float): Latitude of the center of the circle. radius(float): Longitude of the center of the circle. Returns: MapGraphicsCircleItem added to the scene. """ item = MapGraphicsCircleItem(longitude, latitude, radius) self.addItem(item) return item def addLine(self, lon0, lat0, lon1, lat1): """Add a newline) to the graphics scene. Args: lon0(float): Longitude of the start point. lat0(float): Latitude of the start point. lon1(float): Longitude of the end point. lat1(float): Latitude of the end point. Returns: MapGraphicsLineItem added to the scene. """ item = MapGraphicsLineItem(lon0, lat0, lon1, lat1) self.addItem(item) return item def addRect(self, lon0, lat0, lon1, lat1): """Add a newline) to the graphics scene. Args: lon0(float): Longitude of the top left point. lat0(float): Latitude of the top left point. lon1(float): Longitude of the bottom right point. lat1(float): Latitude of the bottom right point. Returns: MapGraphicsLineItem added to the scene. """ item = MapGraphicsRectItem(lon0, lat0, lon1, lat1) self.addItem(item) return item def addPolyline(self, longitudes, latitudes): """Add a new circle (point) to the graphics scene. Args: longitudes(iterable): Longitudes of all the points of the polyline. latitudes(iterable): Latitudes of all the points of the polyline. Returns: MapGraphicsPolylineItem added to the scene. """ item = MapGraphicsPolylineItem(longitudes, latitudes) self.addItem(item) return item def addPixmap(self, longitude, latitude, pixmap): """Add a new circle (point) to the graphics scene. Args: longitude(float): Longitude of the origin of the pixmap. latitude(float): Latitude of the center of the pixmap. pixmap(QPixmap): Pixmap. Returns: MapGraphicsPixmapItem added to the scene. Note: Use `MapGraphicsPixmapItem.setOffset(off)` to translate by `off` pixels the pixmap respect the origin coordinates. """ item = MapGraphicsPixmapItem(longitude, latitude, pixmap) self.addItem(item) return item def addText(self, longitude, latitude, text): """Add a test item to the graphics scene. Args: longitude(float): Longitude of the origin of the text latitude(float): Latitude of the origin of the text Returns: MapGraphicsTextItem added to the scene. """ item = MapGraphicsTextItem(longitude, latitude, text) self.addItem(item) return item def addLegend(self, pos=QPointF(10.0, 10.0)): legend = MapLegendItem(pos=pos) self.addItem(legend) return legend def addScale(self, **kwargs): """Add a scale bar with text on the right bottom of the map Keyword Args: textPen: QPen to use for drawing the text. Default 'black'. barBrush: QBrush to use for drawing the scale bar. Default (190, 190, 190, 160) barPen: QPen to use for drawing the scale bar border. Default (190, 190, 190, 240) barBrushHover: QBrush to use for drawing the scale bar when the mouse is over it. Default (110, 110, 110, 255). barPenHover: QPen to use for drawing the scale bar borderwhen the mouse is over it. Default (90, 90, 90, 255). Note: Almost all the argumnets accepted by the functions.makeBrush() and functions.makePen() are accepted. """ scaleItem = MapScaleItem(**kwargs) self.addItem(scaleItem) return scaleItem def addLinesGroup(self, longitudes, latitudes): item = MapGraphicsLinesGroupItem(longitudes, latitudes) self.addItem(item) return item
def __init__(self): QMainWindow.__init__(self) view = MapGraphicsView(tileSource=MapTileSourceHere()) self.setCentralWidget(view) view.scene().setCenter(10.065990, 44.861041) view.setOptimizationFlag(QGraphicsView.DontSavePainterState, True) view.setRenderHint(QPainter.Antialiasing, True) view.setRenderHint(QPainter.SmoothPixmapTransform, True) pointItem = view.scene().addCircle(10.068640, 44.860767, 3.0) pointItem.setBrush(Qt.black) pointItem.setToolTip('10.068640, 44.860767') pointItem.setFlag(QGraphicsItem.ItemIsSelectable, True) lats = list() lons = list() for p in POINTS: pointItem = view.scene().addCircle(p[1], p[0], 5.0) pointItem.setBrush(Qt.green) pointItem.setPen(QPen(Qt.NoPen)) pointItem.setToolTip('%f, %f' % (p[1], p[0])) pointItem.setFlag(QGraphicsItem.ItemIsSelectable, True) lons.append(p[1]) lats.append(p[0]) lineItem = view.scene().addLine(10.191037, 44.832810, 10.201736, 44.837632) lineItem.setPen(QPen(QBrush(Qt.blue), 3.0)) polylineItem = view.scene().addPolyline(lons, lats) polylineItem.setPen(QPen(QBrush(Qt.red), 3.0)) pix = QPixmap(24, 24) pix.fill(Qt.red) pixmapItem = view.scene().addPixmap(10.090598, 44.857893, pix) pixmapItem.setOffset(-12, -12) pointItemPixmapOrigin = view.scene().addCircle(10.090598, 44.857893, 3.0) pointItemPixmapOrigin.setBrush(Qt.black) pointItemWithChild = view.scene().addCircle(10.083103, 44.858014, 3.0) pointItemWithChild.setBrush(Qt.blue) pointItemWithChild.setPen(QPen(Qt.NoPen)) textItem = QGraphicsSimpleTextItem('Annotation\nfor blue point', parent=pointItemWithChild) textItem.setBrush(QBrush(QColor(Qt.blue))) textItem.setPos(-5, 3) lats_2 = list() lons_2 = list() for p in POINTS_2: lons_2.append(p[1]) lats_2.append(p[0]) linesGroupItem = view.scene().addLinesGroup(lons_2, lats_2) linesGroupItem.setLineStyle(POINTS_2_COLORS, width=POINTS_2_SIZES) legendItem = view.scene().addLegend() legendItem.addPoint('Point 1', '#FF0000', border=None) legendItem.addRect('Rect 2', '#00FF00', border=None) legendItem.addPoint('Circle 3', '#0000FF', border=None) legendItem.addRect('Sphere 4', '#00FFFF', border=None) legendItem.addPoint('Polygon 5', '#FF00FF', border=None) scaleItem = view.scene().addScale(anchor=Qt.BottomRightCorner)
class FigureCanvas(QFrame): """ A basic widget on which can be painted a custom png, jpg, or svg image. """ def __init__(self, parent=None, background_color=None): super(FigureCanvas, self).__init__(parent) self.setLineWidth(2) self.setMidLineWidth(1) self.setObjectName("figcanvas") self.setStyleSheet( "#figcanvas {background-color:" + str(background_color) + "}") self.fig = None self.fmt = None self.fwidth, self.fheight = 200, 200 self._blink_flag = False self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu_requested) def context_menu_requested(self, event): """Popup context menu.""" if self.fig: pos = QPoint(event.x(), event.y()) context_menu = QMenu(self) context_menu.addAction(ima.icon('editcopy'), "Copy Image", self.copy_figure, QKeySequence( get_shortcut('plots', 'copy'))) context_menu.popup(self.mapToGlobal(pos)) @Slot() def copy_figure(self): """Copy figure to clipboard.""" if self.fmt in ['image/png', 'image/jpeg']: qpixmap = QPixmap() qpixmap.loadFromData(self.fig, self.fmt.upper()) QApplication.clipboard().setImage(qpixmap.toImage()) elif self.fmt == 'image/svg+xml': svg_to_clipboard(self.fig) else: return self.blink_figure() def blink_figure(self): """Blink figure once.""" if self.fig: self._blink_flag = not self._blink_flag self.repaint() if self._blink_flag: timer = QTimer() timer.singleShot(40, self.blink_figure) def clear_canvas(self): """Clear the figure that was painted on the widget.""" self.fig = None self.fmt = None self._qpix_buffer = [] self.repaint() def load_figure(self, fig, fmt): """ Load the figure from a png, jpg, or svg image, convert it in a QPixmap, and force a repaint of the widget. """ self.fig = fig self.fmt = fmt if fmt in ['image/png', 'image/jpeg']: self._qpix_orig = QPixmap() self._qpix_orig.loadFromData(fig, fmt.upper()) elif fmt == 'image/svg+xml': self._qpix_orig = QPixmap(svg_to_image(fig)) self._qpix_buffer = [self._qpix_orig] self.fwidth = self._qpix_orig.width() self.fheight = self._qpix_orig.height() def paintEvent(self, event): """Qt method override to paint a custom image on the Widget.""" super(FigureCanvas, self).paintEvent(event) # Prepare the rect on which the image is going to be painted : fw = self.frameWidth() rect = QRect(0 + fw, 0 + fw, self.size().width() - 2 * fw, self.size().height() - 2 * fw) if self.fig is None or self._blink_flag: return # Check/update the qpixmap buffer : qpix2paint = None for qpix in self._qpix_buffer: if qpix.size().width() == rect.width(): qpix2paint = qpix break else: if self.fmt in ['image/png', 'image/jpeg']: qpix2paint = self._qpix_orig.scaledToWidth( rect.width(), mode=Qt.SmoothTransformation) elif self.fmt == 'image/svg+xml': qpix2paint = QPixmap(svg_to_image(self.fig, rect.size())) self._qpix_buffer.append(qpix2paint) if qpix2paint is not None: # Paint the image on the widget : qp = QPainter() qp.begin(self) qp.drawPixmap(rect, qpix2paint) qp.end()
def resizeEvent(self, evt): width = self.width() pm = QPixmap.fromImage(self.img) self.pm = pm.scaledToWidth(width) self.setPixmap(self.pm)
def handleTileDataLoaded(self, x, y, zoom, data): pix = QPixmap() pix.loadFromData(data) self.tileReceived.emit(x, y, zoom, pix)
def pixmap(self, size, mode, state): pm = QPixmap(size) pm.fill(Qt.transparent) self.paint(QPainter(pm), QRect(QPoint(0, 0), size), mode, state) return pm