Search in sources :

Example 6 with Project

use of qupath.lib.projects.Project in project qupath by qupath.

the class ProjectBrowser method getPopup.

ContextMenu getPopup() {
    Action actionOpenImage = new Action("Open image", e -> qupath.openImageEntry(getSelectedEntry()));
    Action actionRemoveImage = new Action("Remove image(s)", e -> {
        Collection<ImageRow> imageRows = getSelectedImageRowsRecursive();
        Collection<ProjectImageEntry<BufferedImage>> entries = ProjectTreeRow.getEntries(imageRows);
        if (entries.isEmpty())
            return;
        // Don't allow us to remove any entries that are currently open (in any viewer)
        for (var viewer : qupath.getViewers()) {
            var imageData = viewer.getImageData();
            var entry = imageData == null ? null : getProject().getEntry(imageData);
            if (entry != null && entries.contains(entry)) {
                Dialogs.showErrorMessage("Remove project entries", "Please close all images you want to remove!");
                return;
            }
        }
        if (entries.size() == 1) {
            if (!Dialogs.showConfirmDialog("Remove project entry", "Remove " + entries.iterator().next().getImageName() + " from project?"))
                return;
        } else if (!Dialogs.showYesNoDialog("Remove project entries", String.format("Remove %d entries?", entries.size())))
            return;
        var result = Dialogs.showYesNoCancelDialog("Remove project entries", "Delete all associated data?");
        if (result == DialogButton.CANCEL)
            return;
        project.removeAllImages(entries, result == DialogButton.YES);
        refreshTree(null);
        syncProject(project);
        if (tree != null) {
            boolean isExpanded = tree.getRoot() != null && tree.getRoot().isExpanded();
            tree.setRoot(model.getRoot());
            tree.getRoot().setExpanded(isExpanded);
        }
    });
    Action actionDuplicateImages = new Action("Duplicate image(s)", e -> {
        Collection<ImageRow> imageRows = getSelectedImageRowsRecursive();
        if (imageRows.isEmpty()) {
            logger.debug("Nothing to duplicate - no entries selected");
            return;
        }
        boolean singleImage = false;
        String name = "";
        String title = "Duplicate images";
        String namePrompt = "Append to image name";
        String nameHelp = "Specify text to append to the image name to distinguish duplicated images";
        if (imageRows.size() == 1) {
            title = "Duplicate image";
            namePrompt = "Duplicate image name";
            nameHelp = "Specify name for the duplicated image";
            singleImage = true;
            name = imageRows.iterator().next().getDisplayableString();
            name = GeneralTools.generateDistinctName(name, project.getImageList().stream().map(p -> p.getImageName()).collect(Collectors.toSet()));
        }
        var params = new ParameterList().addStringParameter("name", namePrompt, name, nameHelp).addBooleanParameter("copyData", "Also duplicate data files", true, "Duplicate any associated data files along with the image");
        if (!Dialogs.showParameterDialog(title, params))
            return;
        boolean copyData = params.getBooleanParameterValue("copyData");
        name = params.getStringParameterValue("name");
        // Ensure we have a single space and then the text to append, with extra whitespace removed
        if (!singleImage && !name.isBlank())
            name = " " + name.strip();
        for (var imageRow : imageRows) {
            try {
                var newEntry = project.addDuplicate(ProjectTreeRow.getEntry(imageRow), copyData);
                if (newEntry != null && !name.isBlank()) {
                    if (singleImage)
                        newEntry.setImageName(name);
                    else
                        newEntry.setImageName(newEntry.getImageName() + name);
                }
            } catch (Exception ex) {
                Dialogs.showErrorNotification("Duplicating image", "Error duplicating " + ProjectTreeRow.getEntry(imageRow).getImageName());
                logger.error(ex.getLocalizedMessage(), ex);
            }
        }
        try {
            project.syncChanges();
        } catch (Exception ex) {
            logger.error("Error synchronizing project changes: " + ex.getLocalizedMessage(), ex);
        }
        refreshProject();
        if (imageRows.size() == 1)
            logger.debug("Duplicated 1 image entry");
        else
            logger.debug("Duplicated {} image entries");
    });
    Action actionSetImageName = new Action("Rename image", e -> {
        TreeItem<ProjectTreeRow> path = tree.getSelectionModel().getSelectedItem();
        if (path == null)
            return;
        if (path.getValue().getType() == ProjectTreeRow.Type.IMAGE) {
            if (setProjectEntryImageName(ProjectTreeRow.getEntry(path.getValue())) && project != null)
                syncProject(project);
        }
    });
    // Add a metadata value
    Action actionAddMetadataValue = new Action("Add metadata", e -> {
        Project<BufferedImage> project = getProject();
        Collection<ImageRow> imageRows = getSelectedImageRowsRecursive();
        if (project != null && !imageRows.isEmpty()) {
            TextField tfMetadataKey = new TextField();
            var suggestions = project.getImageList().stream().map(p -> p.getMetadataKeys()).flatMap(Collection::stream).distinct().sorted().collect(Collectors.toList());
            TextFields.bindAutoCompletion(tfMetadataKey, suggestions);
            TextField tfMetadataValue = new TextField();
            Label labKey = new Label("New key");
            Label labValue = new Label("New value");
            labKey.setLabelFor(tfMetadataKey);
            labValue.setLabelFor(tfMetadataValue);
            tfMetadataKey.setTooltip(new Tooltip("Enter the name for the metadata entry"));
            tfMetadataValue.setTooltip(new Tooltip("Enter the value for the metadata entry"));
            ProjectImageEntry<BufferedImage> entry = imageRows.size() == 1 ? ProjectTreeRow.getEntry(imageRows.iterator().next()) : null;
            int nMetadataValues = entry == null ? 0 : entry.getMetadataKeys().size();
            GridPane pane = new GridPane();
            pane.setVgap(5);
            pane.setHgap(5);
            pane.add(labKey, 0, 0);
            pane.add(tfMetadataKey, 1, 0);
            pane.add(labValue, 0, 1);
            pane.add(tfMetadataValue, 1, 1);
            String name = imageRows.size() + " images";
            if (entry != null) {
                name = entry.getImageName();
                if (nMetadataValues > 0) {
                    Label labelCurrent = new Label("Current metadata");
                    TextArea textAreaCurrent = new TextArea();
                    textAreaCurrent.setEditable(false);
                    String keyString = entry.getMetadataSummaryString();
                    if (keyString.isEmpty())
                        textAreaCurrent.setText("No metadata entries yet");
                    else
                        textAreaCurrent.setText(keyString);
                    textAreaCurrent.setPrefRowCount(3);
                    labelCurrent.setLabelFor(textAreaCurrent);
                    pane.add(labelCurrent, 0, 2);
                    pane.add(textAreaCurrent, 1, 2);
                }
            }
            Dialog<ButtonType> dialog = new Dialog<>();
            dialog.setTitle("Metadata");
            dialog.getDialogPane().getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL);
            dialog.getDialogPane().setHeaderText("Set metadata for " + name);
            dialog.getDialogPane().setContent(pane);
            Optional<ButtonType> result = dialog.showAndWait();
            if (result.isPresent() && result.get() == ButtonType.OK) {
                String key = tfMetadataKey.getText().trim();
                String value = tfMetadataValue.getText();
                if (key.isEmpty()) {
                    logger.warn("Attempted to set metadata value for {}, but key was empty!", name);
                } else {
                    // Set metadata for all entries
                    for (var temp : imageRows) ProjectTreeRow.getEntry(temp).putMetadataValue(key, value);
                    syncProject(project);
                    tree.refresh();
                }
            }
        } else {
            Dialogs.showErrorMessage("Edit image description", "No entry is selected!");
        }
    });
    // Edit the description for the image
    Action actionEditDescription = new Action("Edit description", e -> {
        Project<?> project = getProject();
        ProjectImageEntry<?> entry = getSelectedEntry();
        if (project != null && entry != null) {
            if (showDescriptionEditor(entry)) {
                descriptionText.set(entry.getDescription());
                syncProject(project);
            }
        } else {
            Dialogs.showErrorMessage("Edit image description", "No entry is selected!");
        }
    });
    // Mask the name of the images and shuffle the entry
    Action actionMaskImageNames = ActionTools.createSelectableAction(PathPrefs.maskImageNamesProperty(), "Mask image names");
    // Refresh thumbnail according to current display settings
    Action actionRefreshThumbnail = new Action("Refresh thumbnail", e -> {
        TreeItem<ProjectTreeRow> path = tree.getSelectionModel().getSelectedItem();
        if (path == null)
            return;
        if (path.getValue().getType() == ProjectTreeRow.Type.IMAGE) {
            ProjectImageEntry<BufferedImage> entry = ProjectTreeRow.getEntry(path.getValue());
            if (!isCurrentImage(entry)) {
                logger.warn("Cannot refresh entry for image that is not open!");
                return;
            }
            BufferedImage imgThumbnail = qupath.getViewer().getRGBThumbnail();
            imgThumbnail = resizeForThumbnail(imgThumbnail);
            try {
                entry.setThumbnail(imgThumbnail);
            } catch (IOException e1) {
                logger.error("Error writing thumbnail", e1);
            }
            tree.refresh();
        }
    });
    // Open the project directory using Explorer/Finder etc.
    Action actionOpenProjectDirectory = createBrowsePathAction("Project...", () -> getProjectPath());
    Action actionOpenProjectEntryDirectory = createBrowsePathAction("Project entry...", () -> getProjectEntryPath());
    Action actionOpenImageServerDirectory = createBrowsePathAction("Image server...", () -> getImageServerPath());
    Menu menuSort = new Menu("Sort by...");
    ContextMenu menu = new ContextMenu();
    var hasProjectBinding = qupath.projectProperty().isNotNull();
    var menuOpenDirectories = MenuTools.createMenu("Open directory...", actionOpenProjectDirectory, actionOpenProjectEntryDirectory, actionOpenImageServerDirectory);
    menuOpenDirectories.visibleProperty().bind(hasProjectBinding);
    // MenuItem miOpenProjectDirectory = ActionUtils.createMenuItem(actionOpenProjectDirectory);
    MenuItem miOpenImage = ActionUtils.createMenuItem(actionOpenImage);
    MenuItem miRemoveImage = ActionUtils.createMenuItem(actionRemoveImage);
    MenuItem miDuplicateImage = ActionUtils.createMenuItem(actionDuplicateImages);
    MenuItem miSetImageName = ActionUtils.createMenuItem(actionSetImageName);
    MenuItem miRefreshThumbnail = ActionUtils.createMenuItem(actionRefreshThumbnail);
    MenuItem miEditDescription = ActionUtils.createMenuItem(actionEditDescription);
    MenuItem miAddMetadata = ActionUtils.createMenuItem(actionAddMetadataValue);
    MenuItem miMaskImages = ActionUtils.createCheckMenuItem(actionMaskImageNames);
    // Set visibility as menu being displayed
    menu.setOnShowing(e -> {
        TreeItem<ProjectTreeRow> selected = tree.getSelectionModel().getSelectedItem();
        ProjectImageEntry<BufferedImage> selectedEntry = selected == null ? null : ProjectTreeRow.getEntry(selected.getValue());
        var entries = getSelectedImageRowsRecursive();
        boolean isImageEntry = selectedEntry != null;
        // miOpenProjectDirectory.setVisible(project != null && project.getBaseDirectory().exists());
        miOpenImage.setVisible(isImageEntry);
        miDuplicateImage.setVisible(isImageEntry);
        miSetImageName.setVisible(isImageEntry);
        miAddMetadata.setVisible(!entries.isEmpty());
        miEditDescription.setVisible(isImageEntry);
        miRefreshThumbnail.setVisible(isImageEntry && isCurrentImage(selectedEntry));
        miRemoveImage.setVisible(selected != null && project != null && !project.getImageList().isEmpty());
        if (project == null) {
            menuSort.setVisible(false);
            return;
        }
        Map<String, MenuItem> newItems = new TreeMap<>();
        for (ProjectImageEntry<?> entry : project.getImageList()) {
            // Add all entry metadata keys
            for (String key : entry.getMetadataKeys()) {
                if (!newItems.containsKey(key))
                    newItems.put(key, ActionUtils.createMenuItem(createSortByKeyAction(key, key)));
            }
            // Add all additional keys
            for (String key : baseMetadataKeys) {
                if (!newItems.containsKey(key))
                    newItems.put(key, ActionUtils.createMenuItem(createSortByKeyAction(key, key)));
            }
        }
        menuSort.getItems().setAll(newItems.values());
        menuSort.getItems().add(0, ActionUtils.createMenuItem(createSortByKeyAction("None", null)));
        menuSort.getItems().add(1, new SeparatorMenuItem());
        menuSort.setVisible(true);
        if (menu.getItems().isEmpty())
            e.consume();
    });
    SeparatorMenuItem separator = new SeparatorMenuItem();
    separator.visibleProperty().bind(menuSort.visibleProperty());
    menu.getItems().addAll(miOpenImage, miRemoveImage, miDuplicateImage, new SeparatorMenuItem(), miSetImageName, miAddMetadata, miEditDescription, miMaskImages, miRefreshThumbnail, separator, menuSort);
    separator = new SeparatorMenuItem();
    separator.visibleProperty().bind(menuOpenDirectories.visibleProperty());
    if (Desktop.isDesktopSupported()) {
        menu.getItems().addAll(separator, menuOpenDirectories);
    }
    return menu;
}
Also used : Button(javafx.scene.control.Button) ImageServer(qupath.lib.images.servers.ImageServer) DoubleBinding(javafx.beans.binding.DoubleBinding) ActionUtils(org.controlsfx.control.action.ActionUtils) LoggerFactory(org.slf4j.LoggerFactory) RenderingHints(java.awt.RenderingHints) StackPane(javafx.scene.layout.StackPane) Side(javafx.geometry.Side) ParameterList(qupath.lib.plugins.parameters.ParameterList) MasterDetailPane(org.controlsfx.control.MasterDetailPane) ContextMenu(javafx.scene.control.ContextMenu) Map(java.util.Map) URI(java.net.URI) Path(java.nio.file.Path) QuPathGUI(qupath.lib.gui.QuPathGUI) Pane(javafx.scene.layout.Pane) TextField(javafx.scene.control.TextField) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) IconFactory(qupath.lib.gui.tools.IconFactory) Collection(java.util.Collection) Set(java.util.Set) Canvas(javafx.scene.canvas.Canvas) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) TreeView(javafx.scene.control.TreeView) Objects(java.util.Objects) Platform(javafx.application.Platform) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) List(java.util.List) Project(qupath.lib.projects.Project) GuiTools(qupath.lib.gui.tools.GuiTools) Optional(java.util.Optional) ThreadTools(qupath.lib.common.ThreadTools) ObservableList(javafx.collections.ObservableList) BorderPane(javafx.scene.layout.BorderPane) StringProperty(javafx.beans.property.StringProperty) IntStream(java.util.stream.IntStream) TextArea(javafx.scene.control.TextArea) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) ButtonType(javafx.scene.control.ButtonType) TreeItem(javafx.scene.control.TreeItem) Action(org.controlsfx.control.action.Action) ImageRow(qupath.lib.gui.panes.ProjectTreeRow.ImageRow) FXCollections(javafx.collections.FXCollections) PathIcons(qupath.lib.gui.tools.IconFactory.PathIcons) Supplier(java.util.function.Supplier) Bindings(javafx.beans.binding.Bindings) HashSet(java.util.HashSet) Dialogs(qupath.lib.gui.dialogs.Dialogs) TextFields(org.controlsfx.control.textfield.TextFields) Insets(javafx.geometry.Insets) Graphics2D(java.awt.Graphics2D) ActionTools(qupath.lib.gui.ActionTools) Tooltip(javafx.scene.control.Tooltip) ExecutorService(java.util.concurrent.ExecutorService) GridPane(javafx.scene.layout.GridPane) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) KeyCode(javafx.scene.input.KeyCode) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) Dialog(javafx.scene.control.Dialog) Label(javafx.scene.control.Label) TitledPane(javafx.scene.control.TitledPane) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) GeneralTools(qupath.lib.common.GeneralTools) IOException(java.io.IOException) MetadataRow(qupath.lib.gui.panes.ProjectTreeRow.MetadataRow) ProjectCommands(qupath.lib.gui.commands.ProjectCommands) MenuTools(qupath.lib.gui.tools.MenuTools) Menu(javafx.scene.control.Menu) SelectionMode(javafx.scene.control.SelectionMode) TreeMap(java.util.TreeMap) Type(qupath.lib.gui.panes.ProjectTreeRow.Type) ImageView(javafx.scene.image.ImageView) SwingFXUtils(javafx.embed.swing.SwingFXUtils) TreeCell(javafx.scene.control.TreeCell) ObservableValue(javafx.beans.value.ObservableValue) ChangeListener(javafx.beans.value.ChangeListener) Collections(java.util.Collections) Image(javafx.scene.image.Image) PathPrefs(qupath.lib.gui.prefs.PathPrefs) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) PaneTools(qupath.lib.gui.tools.PaneTools) Action(org.controlsfx.control.action.Action) ImageRow(qupath.lib.gui.panes.ProjectTreeRow.ImageRow) TextArea(javafx.scene.control.TextArea) Label(javafx.scene.control.Label) ContextMenu(javafx.scene.control.ContextMenu) BufferedImage(java.awt.image.BufferedImage) Dialog(javafx.scene.control.Dialog) TextField(javafx.scene.control.TextField) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) ContextMenu(javafx.scene.control.ContextMenu) Menu(javafx.scene.control.Menu) ButtonType(javafx.scene.control.ButtonType) GridPane(javafx.scene.layout.GridPane) Tooltip(javafx.scene.control.Tooltip) MenuItem(javafx.scene.control.MenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) IOException(java.io.IOException) TreeMap(java.util.TreeMap) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) IOException(java.io.IOException) ParameterList(qupath.lib.plugins.parameters.ParameterList)

Example 7 with Project

use of qupath.lib.projects.Project in project qupath by qupath.

the class ObjectClassifierLoadCommand method run.

@Override
public void run() {
    project = qupath.getProject();
    var listClassifiers = new ListView<String>();
    externalObjectClassifiers = new HashMap<>();
    listClassifiers.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    var labelPlaceholder = new Label("Object classifiers in the\n" + "current project will appear here");
    labelPlaceholder.setAlignment(Pos.CENTER);
    labelPlaceholder.setTextAlignment(TextAlignment.CENTER);
    listClassifiers.setPlaceholder(labelPlaceholder);
    refreshNames(listClassifiers.getItems());
    // Provide an option to remove a classifier
    var popup = new ContextMenu();
    var miAdd = new MenuItem("Add classifier");
    miAdd.setOnAction(e -> {
        List<File> files = Dialogs.promptForMultipleFiles(title, null, "QuPath classifier file", "json");
        if (files == null || files.isEmpty())
            return;
        try {
            addClassifierFiles(files);
            List<String> updatedNames = new ArrayList<>();
            updatedNames.addAll(project.getPixelClassifiers().getNames());
            updatedNames.addAll(externalObjectClassifiers.keySet());
        } catch (IOException ex) {
            Dialogs.showErrorMessage(title, ex);
        }
    });
    var miRemove = new MenuItem("Delete selected");
    popup.getItems().setAll(miAdd, miRemove);
    miRemove.disableProperty().bind(listClassifiers.getSelectionModel().selectedItemProperty().isNull());
    listClassifiers.setContextMenu(popup);
    miRemove.setOnAction(e -> {
        var selectedItems = new ArrayList<>(listClassifiers.getSelectionModel().getSelectedItems());
        if (selectedItems.isEmpty() || project == null)
            return;
        try {
            String message = selectedItems.size() == 1 ? "'" + selectedItems.get(0) + "'" : selectedItems.size() + " classifiers";
            if (!Dialogs.showConfirmDialog(title, "Are you sure you want to delete " + message + "?"))
                return;
            for (var selected : selectedItems) {
                if (!project.getObjectClassifiers().getNames().contains(selected)) {
                    Dialogs.showErrorMessage(title, "Unable to delete " + selected + " - not found in the current project");
                    return;
                }
                project.getObjectClassifiers().remove(selected);
                listClassifiers.getItems().remove(selected);
            }
        } catch (Exception ex) {
            Dialogs.showErrorMessage("Error deleting classifier", ex);
        }
    });
    // listClassifiers.setOnMouseClicked(e -> {
    // if (e.getClickCount() == 2) {
    // List<File> files = Dialogs.promptForMultipleFiles(title, null, "QuPath classifier file", "json");
    // if (files == null || files.isEmpty())
    // return;
    // 
    // try {
    // addClassifierFiles(files);
    // List<String> updatedNames = new ArrayList<>();
    // updatedNames.addAll(project.getPixelClassifiers().getNames());
    // updatedNames.addAll(externalObjectClassifiers.keySet());
    // } catch (IOException ex) {
    // Dialogs.showErrorMessage(title, ex);
    // }
    // }
    // });
    // Support drag & drop for classifiers
    listClassifiers.setOnDragOver(e -> {
        e.acceptTransferModes(TransferMode.COPY);
        e.consume();
    });
    listClassifiers.setOnDragDropped(e -> {
        Dragboard dragboard = e.getDragboard();
        if (dragboard.hasFiles()) {
            logger.trace("File(s) dragged onto classifier listView");
            try {
                var files = dragboard.getFiles().stream().filter(f -> f.isFile() && !f.isHidden()).collect(Collectors.toList());
                addClassifierFiles(files);
            } catch (Exception ex) {
                String plural = dragboard.getFiles().size() == 1 ? "" : "s";
                Dialogs.showErrorMessage("Error adding classifier" + plural, ex.getLocalizedMessage());
            }
        }
        refreshNames(listClassifiers.getItems());
        e.consume();
    });
    var label = new Label("Choose classifier");
    label.setLabelFor(listClassifiers);
    // var enableButtons = qupath.viewerProperty().isNotNull().and(selectedClassifier.isNotNull());
    var btnApplyClassifier = new Button("Apply classifier");
    btnApplyClassifier.textProperty().bind(Bindings.createStringBinding(() -> {
        if (listClassifiers.getSelectionModel().getSelectedItems().size() > 1)
            return "Apply classifiers sequentially";
        return "Apply classifier";
    }, listClassifiers.getSelectionModel().getSelectedItems()));
    btnApplyClassifier.disableProperty().bind(listClassifiers.getSelectionModel().selectedItemProperty().isNull());
    btnApplyClassifier.setOnAction(e -> {
        var imageData = qupath.getImageData();
        if (imageData == null) {
            Dialogs.showErrorMessage(title, "No image open!");
            return;
        }
        runClassifier(imageData, project, externalObjectClassifiers, listClassifiers.getSelectionModel().getSelectedItems(), true);
    });
    // var pane = new BorderPane();
    // pane.setPadding(new Insets(10.0));
    // pane.setTop(label);
    // pane.setCenter(comboClassifiers);
    // pane.setBottom(btnApplyClassifier);
    var pane = new GridPane();
    pane.setPadding(new Insets(10.0));
    pane.setHgap(5);
    pane.setVgap(10);
    int row = 0;
    PaneTools.setFillWidth(Boolean.TRUE, label, listClassifiers, btnApplyClassifier);
    PaneTools.setVGrowPriority(Priority.ALWAYS, listClassifiers);
    PaneTools.setHGrowPriority(Priority.ALWAYS, label, listClassifiers, btnApplyClassifier);
    PaneTools.setMaxWidth(Double.MAX_VALUE, label, listClassifiers, btnApplyClassifier);
    PaneTools.addGridRow(pane, row++, 0, "Choose object classification model to apply to the current image", label);
    PaneTools.addGridRow(pane, row++, 0, "Drag and drop a file here to add a new classifier", listClassifiers);
    PaneTools.addGridRow(pane, row++, 0, "Apply object classification to all open images", btnApplyClassifier);
    PaneTools.setMaxWidth(Double.MAX_VALUE, listClassifiers, btnApplyClassifier);
    var stage = new Stage();
    stage.setTitle(title);
    stage.setScene(new Scene(pane));
    stage.initOwner(qupath.getStage());
    // stage.sizeToScene();
    stage.setWidth(300);
    stage.setHeight(400);
    stage.focusedProperty().addListener((v, o, n) -> {
        if (n)
            refreshNames(listClassifiers.getItems());
    });
    // stage.setResizable(false);
    stage.show();
}
Also used : Button(javafx.scene.control.Button) Pos(javafx.geometry.Pos) Scene(javafx.scene.Scene) Arrays(java.util.Arrays) ListView(javafx.scene.control.ListView) GsonTools(qupath.lib.io.GsonTools) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) Bindings(javafx.beans.binding.Bindings) TransferMode(javafx.scene.input.TransferMode) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Dialogs(qupath.lib.gui.dialogs.Dialogs) Dragboard(javafx.scene.input.Dragboard) Insets(javafx.geometry.Insets) ObjectClassifiers(qupath.lib.classifiers.object.ObjectClassifiers) ContextMenu(javafx.scene.control.ContextMenu) Map(java.util.Map) TextAlignment(javafx.scene.text.TextAlignment) UpdateUrisCommand(qupath.lib.gui.commands.UpdateUrisCommand) GridPane(javafx.scene.layout.GridPane) QuPathGUI(qupath.lib.gui.QuPathGUI) ImageData(qupath.lib.images.ImageData) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) Files(java.nio.file.Files) GeneralTools(qupath.lib.common.GeneralTools) UriUpdater(qupath.lib.io.UriUpdater) IOException(java.io.IOException) WorkflowStep(qupath.lib.plugins.workflow.WorkflowStep) Collectors(java.util.stream.Collectors) File(java.io.File) Priority(javafx.scene.layout.Priority) List(java.util.List) Project(qupath.lib.projects.Project) SelectionMode(javafx.scene.control.SelectionMode) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) Stage(javafx.stage.Stage) ObjectClassifier(qupath.lib.classifiers.object.ObjectClassifier) ObservableList(javafx.collections.ObservableList) UriResource(qupath.lib.io.UriResource) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) PaneTools(qupath.lib.gui.tools.PaneTools) GridPane(javafx.scene.layout.GridPane) Insets(javafx.geometry.Insets) Label(javafx.scene.control.Label) ArrayList(java.util.ArrayList) ContextMenu(javafx.scene.control.ContextMenu) MenuItem(javafx.scene.control.MenuItem) IOException(java.io.IOException) Scene(javafx.scene.Scene) IOException(java.io.IOException) ListView(javafx.scene.control.ListView) Button(javafx.scene.control.Button) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) Stage(javafx.stage.Stage) File(java.io.File) Dragboard(javafx.scene.input.Dragboard)

Example 8 with Project

use of qupath.lib.projects.Project in project qupath by qupath.

the class QuPathGUI method createRecentProjectsMenu.

private Menu createRecentProjectsMenu() {
    // Create a recent projects list in the File menu
    ObservableList<URI> recentProjects = PathPrefs.getRecentProjectList();
    Menu menuRecent = MenuTools.createMenu("Recent projects...");
    EventHandler<Event> validationHandler = e -> {
        menuRecent.getItems().clear();
        for (URI uri : recentProjects) {
            if (uri == null)
                continue;
            String name = Project.getNameFromURI(uri);
            name = ".../" + name;
            MenuItem item = new MenuItem(name);
            item.setOnAction(e2 -> {
                Project<BufferedImage> project;
                try {
                    project = ProjectIO.loadProject(uri, BufferedImage.class);
                    setProject(project);
                } catch (Exception e1) {
                    Dialogs.showErrorMessage("Project error", "Cannot find project " + uri);
                    logger.error("Error loading project", e1);
                }
            });
            menuRecent.getItems().add(item);
        }
    };
    // Ensure the menu is populated
    menuRecent.parentMenuProperty().addListener((v, o, n) -> {
        if (o != null && o.getOnMenuValidation() == validationHandler)
            o.setOnMenuValidation(null);
        if (n != null)
            n.setOnMenuValidation(validationHandler);
    });
    return menuRecent;
}
Also used : Change(javafx.collections.ListChangeListener.Change) PathObjectHierarchyView(qupath.lib.gui.panes.PathObjectHierarchyView) SelectedMeasurementTableView(qupath.lib.gui.panes.SelectedMeasurementTableView) Version(qupath.lib.common.Version) ProjectBrowser(qupath.lib.gui.panes.ProjectBrowser) ListChangeListener(javafx.collections.ListChangeListener) Map(java.util.Map) Path(java.nio.file.Path) ReleaseVersion(qupath.lib.gui.extensions.UpdateChecker.ReleaseVersion) Rectangle2D(javafx.geometry.Rectangle2D) PathObjects(qupath.lib.objects.PathObjects) Rectangle(javafx.scene.shape.Rectangle) BooleanProperty(javafx.beans.property.BooleanProperty) Project(qupath.lib.projects.Project) ObservableList(javafx.collections.ObservableList) Divider(javafx.scene.control.SplitPane.Divider) QuPathExtension(qupath.lib.gui.extensions.QuPathExtension) ByteArrayOutputStream(java.io.ByteArrayOutputStream) FXCollections(javafx.collections.FXCollections) PathIcons(qupath.lib.gui.tools.IconFactory.PathIcons) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Bindings(javafx.beans.binding.Bindings) LinkedHashMap(java.util.LinkedHashMap) TreeTableView(javafx.scene.control.TreeTableView) PreferencePane(qupath.lib.gui.panes.PreferencePane) Commands(qupath.lib.gui.commands.Commands) QuPathStyleManager(qupath.lib.gui.prefs.QuPathStyleManager) IOException(java.io.IOException) OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) Preferences(java.util.prefs.Preferences) ROI(qupath.lib.roi.interfaces.ROI) PathTools(qupath.lib.gui.viewer.tools.PathTools) ParameterPanelFX(qupath.lib.gui.dialogs.ParameterPanelFX) DragDropImportListener(qupath.lib.gui.viewer.DragDropImportListener) ImageView(javafx.scene.image.ImageView) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) Image(javafx.scene.image.Image) PathIO(qupath.lib.io.PathIO) EventHandler(javafx.event.EventHandler) ImageServer(qupath.lib.images.servers.ImageServer) BooleanBinding(javafx.beans.binding.BooleanBinding) TextInputControl(javafx.scene.control.TextInputControl) URLDecoder(java.net.URLDecoder) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) Date(java.util.Date) URISyntaxException(java.net.URISyntaxException) ObjectInputStream(java.io.ObjectInputStream) KeyCombination(javafx.scene.input.KeyCombination) DefaultImageRegionStore(qupath.lib.gui.images.stores.DefaultImageRegionStore) ByteArrayInputStream(java.io.ByteArrayInputStream) Locale(java.util.Locale) GitHubProject(qupath.lib.gui.extensions.GitHubProject) ImageIO(javax.imageio.ImageIO) RotateEvent(javafx.scene.input.RotateEvent) WindowEvent(javafx.stage.WindowEvent) PathInteractivePlugin(qupath.lib.plugins.PathInteractivePlugin) Orientation(javafx.geometry.Orientation) MenuItem(javafx.scene.control.MenuItem) Ellipse(javafx.scene.shape.Ellipse) ImageServerProvider(qupath.lib.images.servers.ImageServerProvider) Collection(java.util.Collection) Font(javafx.scene.text.Font) ServiceLoader(java.util.ServiceLoader) Collectors(java.util.stream.Collectors) BorderStroke(javafx.scene.layout.BorderStroke) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) ImageTypeSetting(qupath.lib.gui.prefs.PathPrefs.ImageTypeSetting) ProjectIO(qupath.lib.projects.ProjectIO) GuiTools(qupath.lib.gui.tools.GuiTools) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) Scene(javafx.scene.Scene) ListView(javafx.scene.control.ListView) ReadOnlyObjectProperty(javafx.beans.property.ReadOnlyObjectProperty) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) Action(org.controlsfx.control.action.Action) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) ScriptEditor(qupath.lib.gui.scripting.ScriptEditor) TableColumn(javafx.scene.control.TableColumn) HashSet(java.util.HashSet) Insets(javafx.geometry.Insets) DetectionDisplayMode(qupath.lib.gui.viewer.OverlayOptions.DetectionDisplayMode) ExecutorService(java.util.concurrent.ExecutorService) KeyCode(javafx.scene.input.KeyCode) ActionAccelerator(qupath.lib.gui.ActionTools.ActionAccelerator) Logger(org.slf4j.Logger) Dialog(javafx.scene.control.Dialog) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) ActionIcon(qupath.lib.gui.ActionTools.ActionIcon) ServerBuilder(qupath.lib.images.servers.ImageServerBuilder.ServerBuilder) ScrollEvent(javafx.scene.input.ScrollEvent) Consumer(java.util.function.Consumer) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) ViewerPlusDisplayOptions(qupath.lib.gui.viewer.ViewerPlusDisplayOptions) Window(javafx.stage.Window) Comparator(java.util.Comparator) PathTool(qupath.lib.gui.viewer.tools.PathTool) Arrays(java.util.Arrays) ServerTools(qupath.lib.images.servers.ServerTools) ActionUtils(org.controlsfx.control.action.ActionUtils) ActionDescription(qupath.lib.gui.ActionTools.ActionDescription) ReadOnlyBooleanProperty(javafx.beans.property.ReadOnlyBooleanProperty) StackPane(javafx.scene.layout.StackPane) AnnotationPane(qupath.lib.gui.panes.AnnotationPane) JFXPanel(javafx.embed.swing.JFXPanel) ParameterList(qupath.lib.plugins.parameters.ParameterList) TabPane(javafx.scene.control.TabPane) ScriptException(javax.script.ScriptException) CountingPanelCommand(qupath.lib.gui.commands.CountingPanelCommand) SplitPane(javafx.scene.control.SplitPane) Border(javafx.scene.layout.Border) Event(javafx.event.Event) Set(java.util.Set) KeyEvent(javafx.scene.input.KeyEvent) Screen(javafx.stage.Screen) AffineTransform(java.awt.geom.AffineTransform) QuPathViewerListener(qupath.lib.gui.viewer.QuPathViewerListener) StandardCharsets(java.nio.charset.StandardCharsets) Executors(java.util.concurrent.Executors) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Platform(javafx.application.Platform) Region(javafx.scene.layout.Region) CommandFinderTools(qupath.lib.gui.tools.CommandFinderTools) InputDisplayCommand(qupath.lib.gui.commands.InputDisplayCommand) ImageRegionStoreFactory(qupath.lib.gui.images.stores.ImageRegionStoreFactory) ThreadTools(qupath.lib.common.ThreadTools) DefaultScriptEditor(qupath.lib.gui.scripting.DefaultScriptEditor) GitHubRepo(qupath.lib.gui.extensions.GitHubProject.GitHubRepo) BorderPane(javafx.scene.layout.BorderPane) ButtonData(javafx.scene.control.ButtonBar.ButtonData) SimpleDateFormat(java.text.SimpleDateFormat) PathPlugin(qupath.lib.plugins.PathPlugin) Projects(qupath.lib.projects.Projects) StandardCopyOption(java.nio.file.StandardCopyOption) ArrayList(java.util.ArrayList) TabClosingPolicy(javafx.scene.control.TabPane.TabClosingPolicy) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus) ObjectOutputStream(java.io.ObjectOutputStream) LinkedHashSet(java.util.LinkedHashSet) Color(javafx.scene.paint.Color) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) TitledPane(javafx.scene.control.TitledPane) Files(java.nio.file.Files) ToolBar(javafx.scene.control.ToolBar) GeneralTools(qupath.lib.common.GeneralTools) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) ProjectCommands(qupath.lib.gui.commands.ProjectCommands) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Menu(javafx.scene.control.Menu) Cursor(javafx.scene.Cursor) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) Paths(java.nio.file.Paths) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) Tab(javafx.scene.control.Tab) PathPrefs(qupath.lib.gui.prefs.PathPrefs) StringBinding(javafx.beans.binding.StringBinding) Pos(javafx.geometry.Pos) Area(java.awt.geom.Area) CheckMenuItem(javafx.scene.control.CheckMenuItem) LoggerFactory(org.slf4j.LoggerFactory) UpdateChecker(qupath.lib.gui.extensions.UpdateChecker) Parent(javafx.scene.Parent) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) ImageServers(qupath.lib.images.servers.ImageServers) TableView(javafx.scene.control.TableView) ImageType(qupath.lib.images.ImageData.ImageType) Shape(java.awt.Shape) BufferedImage(java.awt.image.BufferedImage) GroovyLanguage(qupath.lib.gui.scripting.languages.GroovyLanguage) ImageServerBuilder(qupath.lib.images.servers.ImageServerBuilder) FileNotFoundException(java.io.FileNotFoundException) TreeView(javafx.scene.control.TreeView) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) Duration(javafx.util.Duration) ColorToolsFX(qupath.lib.gui.tools.ColorToolsFX) Optional(java.util.Optional) LogManager(qupath.lib.gui.logging.LogManager) RadioMenuItem(javafx.scene.control.RadioMenuItem) WorkflowCommandLogView(qupath.lib.gui.panes.WorkflowCommandLogView) TextArea(javafx.scene.control.TextArea) ButtonType(javafx.scene.control.ButtonType) MouseEvent(javafx.scene.input.MouseEvent) HashMap(java.util.HashMap) BrightnessContrastCommand(qupath.lib.gui.commands.BrightnessContrastCommand) UriImageSupport(qupath.lib.images.servers.ImageServerBuilder.UriImageSupport) Dialogs(qupath.lib.gui.dialogs.Dialogs) SwingUtilities(javax.swing.SwingUtilities) HostServices(javafx.application.HostServices) ZoomEvent(javafx.scene.input.ZoomEvent) TMACommands(qupath.lib.gui.commands.TMACommands) Tooltip(javafx.scene.control.Tooltip) ImageDetailsPane(qupath.lib.gui.panes.ImageDetailsPane) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) RoiTools(qupath.lib.roi.RoiTools) ObjectProperty(javafx.beans.property.ObjectProperty) Iterator(java.util.Iterator) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) TableRow(javafx.scene.control.TableRow) PathClass(qupath.lib.objects.classes.PathClass) TMACoreObject(qupath.lib.objects.TMACoreObject) DropShadow(javafx.scene.effect.DropShadow) MenuTools(qupath.lib.gui.tools.MenuTools) BorderStrokeStyle(javafx.scene.layout.BorderStrokeStyle) ActionEvent(javafx.event.ActionEvent) ToggleGroup(javafx.scene.control.ToggleGroup) LogViewerCommand(qupath.lib.gui.commands.LogViewerCommand) SwingFXUtils(javafx.embed.swing.SwingFXUtils) ChangeListener(javafx.beans.value.ChangeListener) Collections(java.util.Collections) InputStream(java.io.InputStream) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) Project(qupath.lib.projects.Project) GitHubProject(qupath.lib.gui.extensions.GitHubProject) RotateEvent(javafx.scene.input.RotateEvent) WindowEvent(javafx.stage.WindowEvent) ScrollEvent(javafx.scene.input.ScrollEvent) Event(javafx.event.Event) KeyEvent(javafx.scene.input.KeyEvent) MouseEvent(javafx.scene.input.MouseEvent) ZoomEvent(javafx.scene.input.ZoomEvent) ActionEvent(javafx.event.ActionEvent) MenuItem(javafx.scene.control.MenuItem) CheckMenuItem(javafx.scene.control.CheckMenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) RadioMenuItem(javafx.scene.control.RadioMenuItem) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) Menu(javafx.scene.control.Menu) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) ScriptException(javax.script.ScriptException) FileNotFoundException(java.io.FileNotFoundException)

Aggregations

List (java.util.List)8 Collectors (java.util.stream.Collectors)8 Logger (org.slf4j.Logger)8 LoggerFactory (org.slf4j.LoggerFactory)8 Dialogs (qupath.lib.gui.dialogs.Dialogs)8 Project (qupath.lib.projects.Project)8 BufferedImage (java.awt.image.BufferedImage)7 IOException (java.io.IOException)7 ArrayList (java.util.ArrayList)7 Map (java.util.Map)7 GeneralTools (qupath.lib.common.GeneralTools)7 QuPathGUI (qupath.lib.gui.QuPathGUI)7 PathPrefs (qupath.lib.gui.prefs.PathPrefs)7 ImageData (qupath.lib.images.ImageData)7 File (java.io.File)6 Set (java.util.Set)6 Bindings (javafx.beans.binding.Bindings)6 Insets (javafx.geometry.Insets)6 Label (javafx.scene.control.Label)6 MenuItem (javafx.scene.control.MenuItem)6