Как заставить кнопки перекрывать изображение в JavaFX?

#java #javafx

#java #javafx

Вопрос:

 package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.awt.*;

public class Main extends Application {
    Stage window;
    Scene scene1, scene2;

    Button button1, button2;
    ImageView iv = new ImageView();

    @Override
    public void start(Stage primaryStage) throws Exception{
        window = primaryStage;
        Label label1 = new Label("First stage");
        Button button1 = new Button("PLAY");

        //Layout 1
        VBox layout1 = new VBox(20);
        scene1 = new Scene(layout1, 1280, 720);
        layout1.getChildren().add(changeBackground("file:menuBackground.png"));
        layout1.getChildren().addAll(label1, button1);

        //defines dimensions of vbox so button and label can be centered
        layout1.prefWidthProperty().bind(window.widthProperty());
        layout1.prefHeightProperty().bind(window.heightProperty());

        layout1.setAlignment(Pos.CENTER);
        button1.setOnAction(event -> window.setScene(scene2));

        //Button 2
        Button button2 = new Button("This scene sucks, go back to scene 1");
        button2.setOnAction(event -> window.setScene(scene1));

        //Layout 2
        StackPane layout2 = new StackPane();
        layout2.getChildren().add(button2);
        scene2 = new Scene(layout2, 1280, 720);
        layout2.getChildren().add(changeBackground("file:gameBackground.png"));

        window.setScene(scene1);
        window.setTitle("Scramblo");
        window.show();
    }

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

    public Node changeBackground(String imageFile){
        ImageView iv = new ImageView();
        Image image = new Image(imageFile);
        iv.setImage(image);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        double width = screenSize.getWidth();
        double height = screenSize.getWidth();
        iv.setFitHeight(height);
        iv.setFitHeight(width);
        iv.setPreserveRatio(true);
        return iv;
    }
}
  

Итак, я хочу, чтобы кнопки перекрывали фоновые изображения. Я хочу видеть кнопки и иметь возможность взаимодействовать с ними, просто имея там фоновое охлаждение. Прямо сейчас, когда я добавляю фон, он полностью удаляет кнопки / ярлыки и все остальное, что я туда поместил. Я не понимаю, как это сделать! Спасибо!

Комментарии:

1. Есть ли шанс, что вы могли бы опубликовать ссылку на изображение, чтобы я мог попробовать запустить ваш код на своем компьютере? Кстати, вы можете использовать class Screen вместо java.awt.Toolkit

2. @Abra gyazo.com/6ef9e0d7537351f209c3fcff12a5a884

3. что бы вы ни делали, не смешивайте awt / swing и javafx — за исключением случаев, когда вы точно знаете, что делаете. А затем импортируйте отдельные классы, которые вам нужны (по сравнению с импортом подстановочных знаков)

Ответ №1:

Сделайте layout1 a StackPane , а не a VBox . Используйте a VBox в качестве контейнера для label1 и button1 и добавьте VBox to layout1 .

A StackPane размещает добавленные к нему узлы один поверх другого. Первый добавленный узел является самым низким. Следовательно, вы хотите сначала добавить фоновое изображение к StackPane , а затем к кнопке. Таким образом, кнопка появляется поверх изображения.

Аналогично layout2 , поскольку вы сначала добавили button2 , а затем добавили изображение, изображение находится поверх кнопки и, следовательно, скрывает кнопку. Вам просто нужно поменять их местами, т. Е. Сначала Добавить изображение, а затем добавить кнопку.

Обратите внимание, что URL-адрес изображения в вашем коде мне кажется неправильным. Я просто поместил изображение в ту же папку, что и скомпилированный Main.class файл, и использовал метод getResource() для получения файла изображения.

Кроме того, я не думаю, что смешивать AWT и JavaFX — хорошая идея. В JavaFX есть класс Screen, который предоставит вам размеры экрана.

Вот ваш код с моими исправлениями. Сравните это с вашим кодом, чтобы увидеть различия.

 import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Screen;
import javafx.stage.Stage;

import java.net.URL;

public class Main extends Application {
    Stage window;
    Scene scene1, scene2;
    Button button1, button2;
    ImageView iv = new ImageView();

    @Override
    public void start(Stage primaryStage) throws Exception {
        Screen screen = Screen.getPrimary();
        Rectangle2D screenBounds =  screen.getBounds();
        primaryStage.setWidth(screenBounds.getWidth());
        primaryStage.setHeight(screenBounds.getHeight());
        window = primaryStage;

        Label label1 = new Label("First stage");
        Button button1 = new Button("PLAY");
        VBox vBox = new VBox(20);
        vBox.getChildren().addAll(label1, button1);
        vBox.setAlignment(Pos.CENTER);

        // Layout 1
        StackPane layout1 = new StackPane();
        scene1 = new Scene(layout1, 1280, 720);
        layout1.getChildren().addAll(changeBackground("snowymountains.png"), vBox);

        // defines dimensions of vbox so button and label can be centered
        layout1.prefWidthProperty().bind(window.widthProperty());
        layout1.prefHeightProperty().bind(window.heightProperty());

        layout1.setAlignment(Pos.CENTER);
        button1.setOnAction(event -> window.setScene(scene2));

        // Button 2
        Button button2 = new Button("This scene sucks, go back to scene 1");
        button2.setOnAction(event -> window.setScene(scene1));

        // Layout 2
        StackPane layout2 = new StackPane();
        scene2 = new Scene(layout2, 1280, 720);
        layout2.getChildren().addAll(changeBackground("gameBackground.jpg"), button2);

        window.setScene(scene1);
        window.setTitle("Scramblo");
        window.show();

    }

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

    public Node changeBackground(String imageFile) {
        URL url = getClass().getResource(imageFile);
        ImageView iv = new ImageView();
        Image image = new Image(url.toExternalForm());
        iv.setImage(image);
        iv.setFitHeight(window.getHeight());
        iv.setFitHeight(window.getWidth());
        iv.setPreserveRatio(true);
        return iv;
    }
}