为什么我的控制器 class 中的事件没有触发
Why is the event in my controller class not firing
我说的事件方法是changeBackgroundScreen。在我的 css 文件之一中,该按钮被背景图像覆盖。起初我以为是背景阻止了按钮的交互。我把背景图去掉了,还是不行。现在我一点头绪都没有了。
这是 FXML 文件的一部分供您重点关注:
<HBox alignment="CENTER" spacing="200">
<children>
<Button fx:id="optionButton1" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground1"/>
<Button fx:id="optionButton2" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground2"/>
<Button fx:id="optionButton3" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground3"/>
</children>
</HBox>
如果您感兴趣,这里是完整的 FXML 文件:
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<?import java.net.URL?>
<StackPane fx:id="Optionmenu" id="BlueBackground1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="millionairetriviagame.OptionscreenController">
<stylesheets>
<URL value="@BackgroundImages.css" />
</stylesheets>
<stylesheets>
<URL value="@ButtonLayout.css"/>
</stylesheets>
<children>
<VBox alignment="TOP_CENTER" spacing="20">
<ImageView>
<image>
<Image url="@ImageFiles/MillionaireLogo1.png"/>
</image>
</ImageView>
<Label text="Click to Change the Background Color" style="-fx-font-style: Italic;" textFill="white">
<font>
<javafx.scene.text.Font name="sans-serif" size="20" />
</font>
</Label>
<HBox alignment="CENTER" spacing="200">
<children>
<Button fx:id="optionButton1" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground1"/>
<Button fx:id="optionButton2" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground2"/>
<Button fx:id="optionButton3" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground3"/>
</children>
</HBox>
</VBox>
<HBox alignment="BOTTOM_RIGHT" spacing="10" >
<children>
<Button fx:id="backToMain" prefWidth="200" prefHeight="30" onAction="#goToTheMainMenu" text="Back to the Main Menu" styleClass="ButtonLayout">
<shape>
<javafx.scene.shape.Rectangle width="200" height="30" arcHeight="30" arcWidth="30" />
</shape>
</Button>
</children>
</HBox>
</children>
</StackPane>
这是我的控制器Class
package millionairetriviagame;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
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;
@FXML private StackPane mainMenu;
@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(ActionEvent event)
{
try
{
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(MillionaireTriviaGame.MAIN));
myLoader.load();
mainMenu = myLoader.getRoot();
}
catch (IOException ex)
{
Logger.getLogger(OptionscreenController.class.getName()).log(Level.SEVERE, null, ex);
}
if(optionButton2.isPressed())
{
mainMenu.setId("BlueBackground2");
Optionmenu.setId("BlueBackground2");
}
}
@FXML private void goToTheMainMenu(ActionEvent event)
{
isDisabled.setValue(true);
optionMenuPlayer.stop();
controller.loadScreen(MillionaireTriviaGame.MAINSCREENID, MillionaireTriviaGame.MAIN);
controller.setScreen(MillionaireTriviaGame.MAINSCREENID);
}
}
这是我的 CSS 文件,如果你也需要看的话。
#BlueBackground1
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor.jpg");
}
#BlueBackground2
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor2.jpg");
}
#SmallBlueBackground1
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
#SmallBlueBackground2
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor2.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
#SmallBlueBackground3
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor3.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
这是视觉效果
问题
问题出在您的布局上。你有一个带 VBox 的 StackPane
(包含触发 changeBackgroundScreen
方法的按钮),最重要的是你有一个 HBox
(有一个按钮,与右下角对齐)。
乍一看,一切都可能看起来很酷。但是,请记住 VBox
和 HBox
是 填充其父级 的布局。因此,即使您看不到,HBox 位于 VBox 中的按钮之上,会阻止所有交互。
解决方案
一个更复杂的解决方案是使用 StackPane
以外的东西,因为我真的没有看到它的需要。但是,由于您已经有了布局,让我们开始一些不需要对布局进行微调的东西。
一个非常简单的解决方案是将 HBox
移动到 VBox
。这样,就没有阻挡层。但是,由于您希望按钮 固定在场景的右下角 ,我们将在 VBox 的子项之间使用 Region
并设置 VGrow as Always
.这会将新添加的 HBox推送 到场景的底部,并使其固定在那里,无论您的场景大小是多少。
完整的 FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<?import java.net.URL?>
<StackPane id="BlueBackground1" fx:id="Optionmenu" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="millionairetriviagame.OptionscreenController">
<stylesheets>
<URL value="@BackgroundImages.css" />
</stylesheets>
<stylesheets>
<URL value="@ButtonLayout.css" />
</stylesheets>
<children>
<VBox alignment="TOP_CENTER" spacing="20">
<ImageView>
<image>
<Image url="@ImageFiles/MillionaireLogo1.png" />
</image>
</ImageView>
<Label style="-fx-font-style: Italic;" text="Click to Change the Background Color" textFill="white">
<font>
<javafx.scene.text.Font name="sans-serif" size="20" />
</font>
</Label>
<HBox alignment="CENTER" spacing="200">
<children>
<Button id="SmallBlueBackground1" fx:id="optionButton1" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
<Button id="SmallBlueBackground2" fx:id="optionButton2" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
<Button id="SmallBlueBackground3" fx:id="optionButton3" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
</children>
</HBox>
<Region prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<HBox alignment="BOTTOM_RIGHT" spacing="10">
<children>
<Button fx:id="backToMain" onAction="#goToTheMainMenu" prefHeight="30" prefWidth="200" styleClass="ButtonLayout" text="Back to the Main Menu">
<shape>
<javafx.scene.shape.Rectangle arcHeight="30" arcWidth="30" height="30" width="200" />
</shape>
</Button>
</children>
</HBox>
</VBox>
</children>
</StackPane>
我说的事件方法是changeBackgroundScreen。在我的 css 文件之一中,该按钮被背景图像覆盖。起初我以为是背景阻止了按钮的交互。我把背景图去掉了,还是不行。现在我一点头绪都没有了。
这是 FXML 文件的一部分供您重点关注:
<HBox alignment="CENTER" spacing="200">
<children>
<Button fx:id="optionButton1" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground1"/>
<Button fx:id="optionButton2" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground2"/>
<Button fx:id="optionButton3" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground3"/>
</children>
</HBox>
如果您感兴趣,这里是完整的 FXML 文件:
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<?import java.net.URL?>
<StackPane fx:id="Optionmenu" id="BlueBackground1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="millionairetriviagame.OptionscreenController">
<stylesheets>
<URL value="@BackgroundImages.css" />
</stylesheets>
<stylesheets>
<URL value="@ButtonLayout.css"/>
</stylesheets>
<children>
<VBox alignment="TOP_CENTER" spacing="20">
<ImageView>
<image>
<Image url="@ImageFiles/MillionaireLogo1.png"/>
</image>
</ImageView>
<Label text="Click to Change the Background Color" style="-fx-font-style: Italic;" textFill="white">
<font>
<javafx.scene.text.Font name="sans-serif" size="20" />
</font>
</Label>
<HBox alignment="CENTER" spacing="200">
<children>
<Button fx:id="optionButton1" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground1"/>
<Button fx:id="optionButton2" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground2"/>
<Button fx:id="optionButton3" onAction="#changeBackgroundScreen" prefWidth="80" prefHeight="50" id="SmallBlueBackground3"/>
</children>
</HBox>
</VBox>
<HBox alignment="BOTTOM_RIGHT" spacing="10" >
<children>
<Button fx:id="backToMain" prefWidth="200" prefHeight="30" onAction="#goToTheMainMenu" text="Back to the Main Menu" styleClass="ButtonLayout">
<shape>
<javafx.scene.shape.Rectangle width="200" height="30" arcHeight="30" arcWidth="30" />
</shape>
</Button>
</children>
</HBox>
</children>
</StackPane>
这是我的控制器Class
package millionairetriviagame;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
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;
@FXML private StackPane mainMenu;
@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(ActionEvent event)
{
try
{
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(MillionaireTriviaGame.MAIN));
myLoader.load();
mainMenu = myLoader.getRoot();
}
catch (IOException ex)
{
Logger.getLogger(OptionscreenController.class.getName()).log(Level.SEVERE, null, ex);
}
if(optionButton2.isPressed())
{
mainMenu.setId("BlueBackground2");
Optionmenu.setId("BlueBackground2");
}
}
@FXML private void goToTheMainMenu(ActionEvent event)
{
isDisabled.setValue(true);
optionMenuPlayer.stop();
controller.loadScreen(MillionaireTriviaGame.MAINSCREENID, MillionaireTriviaGame.MAIN);
controller.setScreen(MillionaireTriviaGame.MAINSCREENID);
}
}
这是我的 CSS 文件,如果你也需要看的话。
#BlueBackground1
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor.jpg");
}
#BlueBackground2
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor2.jpg");
}
#SmallBlueBackground1
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
#SmallBlueBackground2
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor2.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
#SmallBlueBackground3
{
-fx-background-image: url("/millionairetriviagame/ImageFiles/BlueBackgroundColor3.jpg");
-fx-background-repeat: stretch;
-fx-background-size: 80 50;
-fx-background-position: center center;
-fx-background-insets: 0, 0, 0, 0;
}
这是视觉效果
问题
问题出在您的布局上。你有一个带 VBox 的 StackPane
(包含触发 changeBackgroundScreen
方法的按钮),最重要的是你有一个 HBox
(有一个按钮,与右下角对齐)。
乍一看,一切都可能看起来很酷。但是,请记住 VBox
和 HBox
是 填充其父级 的布局。因此,即使您看不到,HBox 位于 VBox 中的按钮之上,会阻止所有交互。
解决方案
一个更复杂的解决方案是使用 StackPane
以外的东西,因为我真的没有看到它的需要。但是,由于您已经有了布局,让我们开始一些不需要对布局进行微调的东西。
一个非常简单的解决方案是将 HBox
移动到 VBox
。这样,就没有阻挡层。但是,由于您希望按钮 固定在场景的右下角 ,我们将在 VBox 的子项之间使用 Region
并设置 VGrow as Always
.这会将新添加的 HBox推送 到场景的底部,并使其固定在那里,无论您的场景大小是多少。
完整的 FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<?import java.net.URL?>
<StackPane id="BlueBackground1" fx:id="Optionmenu" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="millionairetriviagame.OptionscreenController">
<stylesheets>
<URL value="@BackgroundImages.css" />
</stylesheets>
<stylesheets>
<URL value="@ButtonLayout.css" />
</stylesheets>
<children>
<VBox alignment="TOP_CENTER" spacing="20">
<ImageView>
<image>
<Image url="@ImageFiles/MillionaireLogo1.png" />
</image>
</ImageView>
<Label style="-fx-font-style: Italic;" text="Click to Change the Background Color" textFill="white">
<font>
<javafx.scene.text.Font name="sans-serif" size="20" />
</font>
</Label>
<HBox alignment="CENTER" spacing="200">
<children>
<Button id="SmallBlueBackground1" fx:id="optionButton1" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
<Button id="SmallBlueBackground2" fx:id="optionButton2" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
<Button id="SmallBlueBackground3" fx:id="optionButton3" onAction="#changeBackgroundScreen" prefHeight="50" prefWidth="80" />
</children>
</HBox>
<Region prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<HBox alignment="BOTTOM_RIGHT" spacing="10">
<children>
<Button fx:id="backToMain" onAction="#goToTheMainMenu" prefHeight="30" prefWidth="200" styleClass="ButtonLayout" text="Back to the Main Menu">
<shape>
<javafx.scene.shape.Rectangle arcHeight="30" arcWidth="30" height="30" width="200" />
</shape>
</Button>
</children>
</HBox>
</VBox>
</children>
</StackPane>