gpt4 book ai didi

java - 如何更改所有屏幕上的背景图像并保留更改

转载 作者:行者123 更新时间:2023-11-30 11:05:19 26 4
gpt4 key购买 nike

重要信息和方法

所以我有这个方法(目前还不完整),其唯一目的是更改每个屏幕中的背景图像。这是执行此操作的方法。

if(optionButton1.isArmed())
{
optionButton1.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground1"));
}
else if(optionButton2.isArmed())
{
optionButton2.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground2"));
}
else
{
optionButton3.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground3"));
}

所以这段代码目前所做的是检查按下和释放了哪个按钮,并将旧 ID 更改为新 ID。一旦将其更改为新 ID,它将更改 FXML 文件中的 ID,然后 FXML 文件将进入我的 css 文件并查找与新 ID 匹配的 ID。

现在这个 FXML 变量在我的 Controller 类之一 (OptionscreenController) 中,变量的名称是 Optionmenu。在我的 Controller 类中看起来像这样

@FXML private StackPane Optionmenu;

这意味着 optionmenu 是此方法更改的 FXML 文件的主根。

我面临的挑战之一是找到一种方法将所有节点或根节点引入此类,并尽可能更改这些节点的 ID。

这是我解决这个问题的尝试:

   try
{
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(MillionaireTriviaGame.MAIN));
myLoader.load();
mainMenu = myLoader.getRoot();
mainMenu.setId("BlueBackground2")
}
catch (IOException ex)
{
Logger.getLogger(OptionscreenController.class.getName()).log(Level.SEVERE, null, ex);
}

我想做的是加载一个 FXML 文件和主文件旁边的另一个 FXML 文件,使用 getRoot() 获取 FXML 文件中的对象,将其添加到一个变量具有相同的 fx:id 并使用 setId 更改其旧 ID。

现在这样做有两个问题:首先,这样做会调用初始化为运行的覆盖方法,无论如何(每个 Controller 都必须有这个方法)。所以我说,好吧,我不会使用 FXMLLoader.load()。我会立即直接使用 getRoot()。原来它将 FXML 变量设置为空。

我面临的最后一个挑战是在用户从一个屏幕切换到另一个屏幕时保持对每个背景所做的更改。

这些是我目前面临的挑战。


代码时间

我认为您首先需要了解的是我如何从一个屏幕过渡到另一个屏幕。会有很多代码要看,所以如果可以的话请多多包涵。

ScreenNavigator类-用于加载和设置屏幕

package millionairetriviagame;

import java.io.IOException;
import java.util.HashMap;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;

public class ScreenNavigator extends StackPane
{

private HashMap<String, Node> screens = new HashMap<>();

public ScreenNavigator()
{
super();
}

public void addScreen(String name, Node screen)
{
screens.put(name, screen);
}

public Node getScreen(String name)
{
return screens.get(name);
}

public boolean loadScreen(String name, String resource)
{
try
{
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
Parent loadscreen = myLoader.load();
ControllingScreens ScreenController = myLoader.getController();
ScreenController.setScreenParent(this);
addScreen(name, loadscreen);
return true;
}
catch (IOException e)
{
System.out.println(e.getMessage());
return false;
}
}

public boolean setScreen(String name)
{
if (screens.get(name) != null)
{
if (!getChildren().isEmpty())
{

Timeline transition = new Timeline(new KeyFrame(Duration.seconds(0.5), (ActionEvent event) ->
{
getChildren().clear();
getChildren().add(screens.get(name));
}));

transition.play();
MillionaireTriviaGame.fade(true);
}
else
{
getChildren().add(screens.get(name));
MillionaireTriviaGame.fade(false);
}
return true;
}
else
{
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error Dialog");
alert.setHeaderText(null);
alert.setContentText("The screen wasn't able to load.");

alert.showAndWait();
return false;
}
}
}

接下来是使用这个类的主类。

主类

package millionairetriviagame;

import java.util.Optional;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class MillionaireTriviaGame extends Application
{
private static final Rectangle fillRectangle = new Rectangle();
public static final String MAINSCREENID = "main";
public static final String MAIN = "MenulayoutFXML.fxml";
public static final String OPTIONSCREENID = "option";
public static final String OPTION = "Optionscreen.fxml";

@Override
public void start(Stage menuStage) throws Exception
{
ScreenNavigator controller = new ScreenNavigator();
controller.loadScreen(MillionaireTriviaGame.MAINSCREENID, MillionaireTriviaGame.MAIN);
controller.setScreen(MillionaireTriviaGame.MAINSCREENID);

StackPane root = new StackPane();
root.getChildren().addAll(controller, fillRectangle);
root.setAlignment(Pos.TOP_CENTER);

Scene scene = new Scene(root, 1366, 768);
fillRectangle.setWidth(scene.getWidth());
fillRectangle.setHeight(scene.getHeight());
fillRectangle.setDisable(true);
menuStage.setScene(scene);

menuStage.setOnCloseRequest(e ->
{
Alert exitConfirmation = new Alert(Alert.AlertType.CONFIRMATION, "Are you sure you want to exit this application?");
exitConfirmation.setTitle("Exit Application");
exitConfirmation.setHeaderText("Confirm Exit");
Optional<ButtonType> choice = exitConfirmation.showAndWait();
if (choice.get() == ButtonType.OK)
{
menuStage.close();
}
else
{
e.consume();
}
});

menuStage.setTitle("Let's play who wants to be a millionaire");
menuStage.getIcons().add(new Image(getClass().getResource("/millionairetriviagame/ImageFiles/gameIcon.png").toExternalForm()));
menuStage.setFullScreen(true);
menuStage.show();
}

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

public static void fade(boolean inOut)
{
FadeTransition ft = new FadeTransition(Duration.seconds(5), fillRectangle);
ft.setFromValue(1);
ft.setToValue(0);
if (inOut)
{
ft.setDuration(Duration.seconds(0.5));
ft.setFromValue(0);
ft.setToValue(1);
ft.setAutoReverse(true);
ft.setCycleCount(2);
}
ft.play();
}
}

接下来是负责更改所有屏幕的背景图像的 Controller 类。

选项屏幕 Controller

package millionairetriviagame;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class OptionscreenController implements Initializable, ControllingScreens
{
private ScreenNavigator controller;
private MediaPlayer optionMenuPlayer;
@FXML private Button backToMain;
private BooleanProperty isDisabled;
@FXML private StackPane Optionmenu;
@FXML private Button optionButton1;
@FXML private Button optionButton2;
@FXML private Button optionButton3;

@Override
public void initialize(URL url, ResourceBundle rb)
{
configureProperties();
playSong();
}

private void configureProperties()
{
isDisabled = new SimpleBooleanProperty();
backToMain.disableProperty().bind(isDisabled);
}

@Override
public void setScreenParent(ScreenNavigator parentScreen)
{
controller = parentScreen;
}

private void playSong()
{
Media optionIntroTheme = new Media(getClass().getResource("/millionairetriviagame/AudioFiles/OptionMenuMusic.mp3").toExternalForm());
optionMenuPlayer = new MediaPlayer(optionIntroTheme);
optionMenuPlayer.setAutoPlay(true);
optionMenuPlayer.setVolume(0.1);
optionMenuPlayer.setCycleCount(MediaPlayer.INDEFINITE);
}

@FXML private void changeBackgroundScreen() // This is the method where it all happens.
{
if(optionButton1.isArmed())
{
optionButton1.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground1"));
}
else if(optionButton2.isArmed())
{
optionButton2.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground2"));
}
else
{
optionButton3.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground3"));
}
}

@FXML private void goToTheMainMenu()
{
isDisabled.setValue(true);
optionMenuPlayer.stop();
controller.loadScreen(MillionaireTriviaGame.MAINSCREENID, MillionaireTriviaGame.MAIN);
controller.setScreen(MillionaireTriviaGame.MAINSCREENID);
}
}

以及控制显示哪个画面的接口(interface)(每个controller都有这个方法)。

package millionairetriviagame;

public interface ControllingScreens
{
public void setScreenParent(ScreenNavigator parentScreen);
}

最佳答案

解决方案

这是我想出的一个解决方案:

在我的 screenNavigator 类中,我添加了这个方法:

private String getBackgroundId()
{
BufferedReader br = null;
String backgroundId = "";

try
{
br = new BufferedReader(new FileReader("Background.txt"));
backgroundId = br.readLine();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
finally
{
try
{
if (br != null)
{
br.close();
}
}
catch (IOException ex)
{
System.out.println(ex.getMessage());
}
}

return backgroundId;
}

然后在同一个类中,我在loadScreen方法中添加了两行代码

 mainMenu = myLoader.getRoot();
mainMenu.setId(getBackgroundId());

这里是覆盖文件的方法。

private void changeBackgroundId(String backgroundId)
{
BufferedWriter bw = null;

try
{
bw = new BufferedWriter(new FileWriter("Background.txt", false));
bw.write(backgroundId);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
finally
{
try
{
if (bw != null)
{
bw.close();
}
}
catch (IOException ex)
{
System.out.println(ex.getMessage());
}
}

}

这是 changeBackgroundScreen 现在的样子

@FXML private void changeBackgroundScreen()
{
if(optionButton1.isArmed())
{
optionButton1.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground1"));
changeBackgroundId("BlueBackground1");
}
else if(optionButton2.isArmed())
{
optionButton2.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground2"));
changeBackgroundId("BlueBackground2");
}
else
{
optionButton3.setOnMouseClicked(e-> Optionmenu.setId("BlueBackground3"));
changeBackgroundId("BlueBackground3");
}
}

解释

此解决方案的工作方式是,每次我从一个屏幕转换到另一个屏幕时,我将加载 backgroundId 文件中的唯一行,即 css 文件中的 id。一旦用户单击按钮更改背景(查看 optionScreenController 类),我将写入文件并使用新 Id 覆盖旧 Id,以便每个屏幕都将加载新背景。对于我的两个问题,这是一个不错的解决方案。如果其他人认为他们可以改进此解决方案,请改进。

关于java - 如何更改所有屏幕上的背景图像并保留更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29690239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com