Нарисуйте букву X над изображением

Я пишу для университетского проекта программное обеспечение на java - javafx, но у меня есть некоторые проблемы с графической реализацией функции голосования.

У меня есть такая иконка политической партии:

Нарисуйте букву X над изображением

Я хочу в java поставить букву X над этим значком, чтобы получить что-то вроде этого:

Нарисуйте букву X над изображением

Моим решением может быть возможность нарисовать одну линию и другую линию над изображением, но я не знаю, как это сделать.

package unimi.sysvotes.elettore;

import java.io.File;
import java.io.IOException;

import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;

public class VotoController {
    @FXML Pane listaUnoCandidatoUninominale;
    @FXML ImageView listaUnoSimboloUno;

    @FXML
    private void initialize() {
        File fileUno = new File("C:\\Users\\Administrator\\Desktop\\progettazione\\simboli\\popoloDellaLiberta.jpg");
        
        Image imageUno = new Image("file:///"+fileUno.getAbsolutePath());
        
        listaUnoSimboloUno.setImage(imageUno);

    }

    @FXML
    private void listaUnoSimboloUnoAction(MouseEvent me) throws IOException {
        System.out.println("Votato");

        /*
           How put Two line above ImageView popolo?
         */

        Line lineOne = new Line(10, 10, 80, 80);
        lineOne.setFill(null);
        lineOne.setStroke(Color.BLACK);
        lineOne.setStrokeWidth(2);

        Line lineTwo = new Line(80, 10, 10, 80);
        lineTwo.setFill(null);
        lineTwo.setStroke(Color.BLACK);
        lineTwo.setStrokeWidth(2);

    }
    

}
минимальный воспроизводимый пример пожалуйста..
kleopatra 16.05.2022 10:49

@kleopatra, я редактирую вопрос. Теперь это версия контроллера javafx.

zabitstack 16.05.2022 11:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я использовал StackPane.

Я помещаю холст и ImageView в стек, а затем рисую линию на холсте. Я также меняю порядок узлов в панели стека.

public class VotoController {
    @FXML Pane listaUnoCandidatoUninominale;
    @FXML StackPane listaUnoSimboloUnoStack;

    @FXML ImageView listaUnoSimboloUno;
    @FXML Canvas listaUnoSimboloUnoX;
    
    @FXML
    private void initialize() {
        File fileUno = new File("C:\\Users\\Administrator\\Desktop\\progettazione\\simboli\\popoloDellaLiberta.jpg");
        
        Image imageUno = new Image("file:///"+fileUno.getAbsolutePath());
        
        listaUnoSimboloUno.setImage(imageUno);

    }
    
    @FXML
    private void votoCandidatoUninominalAction(MouseEvent me) throws IOException {
        System.out.println("Votato");
        listaUnoCandidatoUninominale.setStyle("-fx-background-image: url('file:C:/Users/Administrator/Desktop/progettazione/voto/backgroundcandidatouninominale.jpg');");
    }

    @FXML
    private void listaUnoSimboloUnoAction(MouseEvent me) throws IOException {
        System.out.println("Votato");

        GraphicsContext gc = listaUnoSimboloUnoX.getGraphicsContext2D();
        
        Line lineOne = new Line(10, 10, 40, 40);
        lineOne.setFill(null);
        lineOne.setStroke(Color.BLACK);
        lineOne.setStrokeWidth(2);

        gc.beginPath();
        gc.setLineWidth(5);
        gc.moveTo(0, 0);
        gc.lineTo(0, 0);
        gc.lineTo(50, 50);

        gc.stroke();

        gc.beginPath();
        gc.setLineWidth(5);
        gc.moveTo(50, 0);
        gc.lineTo(50, 0);
        gc.lineTo(0, 50);

        gc.stroke();

        ObservableList<Node> childs = listaUnoSimboloUnoStack.getChildren();

        if (childs.size() > 1) {
            //
            Node topNode = childs.get(childs.size()-1);
            topNode.toBack();
        }
    }
}
Ответ принят как подходящий

Вот альтернативное решение, основанное на Pane.

Панель используется, а не группа, поэтому панель можно стилизовать с помощью CSS. Если в этом нет необходимости, вместо этого можно использовать группу.

Слои выполняются неявно с помощью алгоритм художника, который JavaFX использует для рендеринга. Этот алгоритм рисует элементы, добавленные позже в списке, поверх элементов, добавленных ранее в списке.

Решение реализует возможность выбора и отмены выбора изображений, что на самом деле не было задано в вопросе, но, похоже, подразумевается в тексте вашего вопроса.

Понятие выбираемого изображения похоже на ToggleButton или CheckBox. Таким образом, вместо этого можно использовать ToggleButton и при необходимости стилизовать его с помощью CSS. Например, X можно получить с помощью фонового слоя svgpath в CSS, именно так работают встроенные элементы управления, такие как переключатель. Однако я не применил этот подход здесь (он немного сложнее, чем то, что я представляю).

Пример расширяется из Pane, но при желании вы можете использовать агрегацию, а не расширение.

Используемые изображения предоставлены в ответе на этот вопрос:

selectable images

X добавляется к дочерним элементам панели поверх изображения с помощью следующего кода.

public SelectableImageView(Image image) {
    imageView = new ImageView(image);
    getChildren().add(imageView);

    selectionMark = createSelectionMark();

    // ... additional listener and initialization code here.
}


private Node[] createSelectionMark() {
    double w = imageView.getImage().getWidth();
    double h = imageView.getImage().getHeight();

    Line l1 = new Line(INSET, INSET, w - INSET, h - INSET);
    l1.setStrokeWidth(INSET * .75);
    l1.setStrokeLineCap(StrokeLineCap.ROUND);
    Line l2 = new Line(INSET, h - INSET, w - INSET, INSET);
    l2.setStrokeWidth(INSET * .75);
    l2.setStrokeLineCap(StrokeLineCap.ROUND);

    return new Node[] { l1, l2 };
}

private void addSelection() {
    getChildren().addAll(selectionMark);
}

Исполняемый пример

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.shape.*;
import javafx.stage.Stage;

import java.util.*;
import java.util.stream.Collectors;

public class SelectableImagesApp extends Application {

    private static final double PADDING = 20;

    @Override
    public void start(Stage stage) throws Exception {
        TilePane imageTiles = new TilePane(PADDING, PADDING);
        imageTiles.setPadding(
                new Insets(PADDING)
        );
        imageTiles.getChildren().addAll(
                createSelectableImages()
        );
        imageTiles.setPrefColumns(ImageNames.values().length);

        stage.setScene(new Scene(imageTiles));
        stage.show();
    }

    public enum ImageNames {
        Medusa,
        Dragon,
        Treant,
        Unicorn
    }

    private List<SelectableImageView> createSelectableImages() {
        return Arrays.stream(ImageNames.values())
                .map(m ->
                        new SelectableImageView(
                                new Image(
                                        Objects.requireNonNull(
                                                SelectableImagesApp.class.getResource(
                                                        m + "-icon.png"
                                                )
                                        ).toExternalForm()
                                )
                        )
                ).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class SelectableImageView extends Pane {
    private final ImageView imageView;

    private final Node[] selectionMark;

    private BooleanProperty selected = new SimpleBooleanProperty(false);

    private final double INSET = 10;

    public SelectableImageView(Image image) {
        imageView = new ImageView(image);
        getChildren().add(imageView);

        selectionMark = createSelectionMark();

        selected.addListener((observable, wasSelected, isSelected) -> {
            if (isSelected) {
                addSelection();
            } else {
                removeSelection();
            }
        });

        this.setStyle("-fx-background-color: lightblue;");
        this.setPickOnBounds(true);
        this.setOnMouseClicked(e -> {
            selected.set(!selected.get());
        });
    }

    private Node[] createSelectionMark() {
        double w = imageView.getImage().getWidth();
        double h = imageView.getImage().getHeight();

        Line l1 = new Line(INSET, INSET, w - INSET, h - INSET);
        l1.setStrokeWidth(INSET * .75);
        l1.setStrokeLineCap(StrokeLineCap.ROUND);
        Line l2 = new Line(INSET, h - INSET, w - INSET, INSET);
        l2.setStrokeWidth(INSET * .75);
        l2.setStrokeLineCap(StrokeLineCap.ROUND);

        return new Node[] { l1, l2 };
    }

    private void addSelection() {
        getChildren().addAll(selectionMark);
    }

    private void removeSelection() {
        getChildren().removeAll(selectionMark);
    }

    public boolean isSelected() {
        return selected.get();
    }

    public BooleanProperty selectedProperty() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected.set(selected);
    }
}

Другие вопросы по теме