在图像上方画一个x字母

发布于 2025-01-29 04:46:08 字数 1737 浏览 2 评论 0原文

我正在为大学项目写作Java -Javafx的软件,但我在图形上实施投票函数时遇到了一些问题。

我有一个这样的政党偶像:

”“在此处输入图像描述”

我想在java中放置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);

    }
    

}

I'm writing for a university project a software in java - javafx but I have some problems in implementing a vote function graphically speaking.

I have a political party icon like this:

enter image description here

I want in java put a X letter above this icon, to obtain something like this:

enter image description here

My solution could be the possibility to draw one line and other line above the Image, but I don't know how to do.

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);

    }
    

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ぃ双果 2025-02-05 04:46:08

这是基于窗格的替代解决方案。

使用窗格而不是组,以便可以用CSS对窗格进行设计。如果不需要,则可以使用组。

分层是由 Painter的algorithM Javafx使用javafx的使用。该算法绘制了稍后在列表中添加的项目顶部的列表中添加的项目。

该解决方案实现了选择和取消选择图像的能力,这并不是真正提出的问题,而是在您的问题文本中暗示。

可选图像的概念类似于togglebutton或复选框。因此,使用CSS可以使用togglebutton并根据需要进行样式。例如,可以通过CSS中的SVGPATH背景层来实现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);
    }
}

Here is an alternate solution based upon a Pane.

A Pane is used rather than a Group so that the Pane can be styled with CSS. If that wasn't needed, then a Group could be used instead.

The layering is accomplished implicitly by the painter's algorithm which JavaFX uses for rendering. This algorithm paints items added later in a list over the top of items added earlier in the list.

The solution implements the ability to select and deselect images, which wasn't really the question asked, but seemed implied in your question text.

The notion of a selectable image is similar to a ToggleButton or CheckBox. So, a ToggleButton could be used instead and styled as required using CSS. For instance, the X could be achieved via a svgpath background layer in CSS, that is how the in-built controls such as radio button work. However, I have not applied that approach here (it is a bit more sophisticated than what I present).

The example extends from Pane, but, if you wish, you can use aggregation rather than extension.

The images used are provided in the answer to this question:

selectable images

The X is added to the pane's children on top of the image with the following code.

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);
}

Executable Example

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);
    }
}
三生路 2025-02-05 04:46:08

我使用Stackpane

我将画布和图像视图放在堆栈中,然后在画布中绘制线。我还更改了Stackpane中的节点顺序。

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();
        }
    }
}

I used StackPane.

I put a canvas and ImageView in stack and then draw line in canvas. I also change order of nodes in stackpane.

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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文