当前位置: 首页 > 知识库问答 >
问题:

使用滚动窗格javafX时出现空指针异常

凌鹏程
2023-03-14

我一直在构建一个影院预订应用程序,正在尝试创建一个显示电影和放映时间的场景。当我使用锚点窗格和vbox来显示所有信息时,它起作用,但当我尝试插入一个额外的滚动窗格(在scenebuilder中)时,FXML加载程序返回一个空指针异常,我无法找出原因...

这是我的FXML代码

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane prefHeight="598.0" prefWidth="798.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MovieShowingsController">
   <children>
      <MenuBar>
        <menus>
          <Menu mnemonicParsing="false" text="myBookings">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <ScrollPane fx:id="scrollpane" hbarPolicy="NEVER" layoutY="22.0" prefHeight="576.0" prefWidth="798.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="22.0">
         <content>
            <VBox fx:id="vbox" prefHeight="555.0" prefWidth="740.0" />
         </content>
      </ScrollPane>
   </children>
</AnchorPane>

下面是controller类

public class MovieShowingsController {

    @FXML
    private VBox vbox;

    private ArrayList<FilmInfo> filmList;

    private ArrayList<Screening> screeningList;

    private MovieShowings showings;

    //FXML loader instance variable to be accessed by dynamic scene controller
    private VBox holder;

    @FXML
    private void initialize() {
    }

    public MovieShowingsController() {

    }

    public MovieShowingsController(MovieShowings showings) {

        String date = "2019-04-15";
        Date sqlDate = Date.valueOf(date);

         System.out.println("\n");
         System.out.println("***Screenings for " + date + "***");

         filmList = new ArrayList();
         screeningList = DatabaseConnection.getInstance().retrieveScreeningsForDay(sqlDate);

         for (Screening screeningInstance : screeningList) {

             if (!filmList.contains(screeningInstance.getFilmInfo())) {

                 filmList.add(screeningInstance.getFilmInfo());

             }

             System.out.println(screeningInstance.toString());
          }

        Collections.sort(screeningList);

        this.showings = showings;

        //populating FXML instance variable from loader
        this.holder = (VBox) showings.getRoot().lookup("#vbox");

        buildMovieShowings(holder);
    }

    private void buildMovieShowings(VBox holder) {

        holder.setSpacing(50);

        for (int i = 0; i < filmList.size(); i++) {

            VBox infoHolder = new VBox();

            infoHolder.setSpacing(10);

            Label title = new Label(String.format("%s%8s", filmList.get(i).getTitle(),
                    "(" + filmList.get(i).getRating() + ")"));

            title.setStyle("-fx-font: 24 arial;");

            Label duration = new Label(String.format("%s%s%s", "Film Length: ",
                    filmList.get(i).getDuration(), " mins"));

            duration.setStyle("-fx-font: 24 arial;");

            Label director = new Label(String.format("%s%s", "Directed By: ",
                    filmList.get(i).getDirector()));

            director.setStyle("-fx-font: 24 arial;");

            infoHolder.getChildren().addAll(title, duration, director);

            HBox timesHolder = new HBox();

            timesHolder.setSpacing(10);

            for (int j = 0; j < screeningList.size(); j++) {

                if (screeningList.get(j).getFilmInfo().equals(filmList.get(i))){

                    Label time = new Label();

                    Background black = new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY));

                    Background red = new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY));

                    time.setBackground(black);

                    Screen screen = screeningList.get(j).getScreen();
                    Screening screening = screeningList.get(j);

                    time.setOnMouseClicked(new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent e) {

                        try {

                        System.out.println(screening.getFilmInfo().getTitle() + screening.getShowTime());

                        time.setBackground(red);

                        SeatMap seatMap = new SeatMap();

                        SeatMapController seatMapController = new SeatMapController(seatMap, 
                                screen);

                        Scene seatMapScene = seatMap.getScene();

                        Stage window = (Stage) ((Node) e.getSource()).getScene().getWindow();

                        window.setResizable(false);

                        window.setWidth(800);
                        window.setHeight(600);

                        window.setScene(seatMapScene);

                        window.show();

                        }

                        catch (IOException ex) {

                            ex.printStackTrace();

                            }

                        }

                    });

                    time.setPrefSize(100, 100);

                    time.setAlignment(Pos.CENTER);

                    time.setStyle("-fx-border-color: black");

                    time.setStyle("-fx-font: 22 arial;");

                    time.setStyle("-fx-text-fill: white");

                    time.setText(screeningList.get(j).getShowTime());

                    timesHolder.getChildren().add(time);
                }
            }

            infoHolder.getChildren().add(timesHolder);

            holder.getChildren().add(infoHolder);
        }
    }
}
public class MovieShowings{

    private AnchorPane root;

    public MovieShowings() {

        try {

            root = FXMLLoader.load(getClass().getResource("movieshowings.fxml"));
        }

        catch(IOException e){

            e.printStackTrace();
        }

    }


    public Scene getScene() {

    Scene scene = new Scene(root,800,600);

    return scene;

    }

    public AnchorPane getRoot() {

        return root;
    }

}
if(DatabaseConnection.getInstance().login(Username.getText(), Password.getText())) {

            MovieShowings films = new MovieShowings();

            MovieShowingsController filmsController = new MovieShowingsController(films);

            Scene movieShowings = films.getScene();

            Stage window = (Stage) ((Node) e.getSource()).getScene().getWindow();

            window.setScene(movieShowings);

            window.show();

编辑:fx:id'vbox'不会从getRoot()方法访问,即使它已被注入到FXML加载器中

共有1个答案

章建木
2023-03-14

这是因为ScrollPane添加了内容、ScrollBar等。在创建皮肤时的第一次布局传递过程中切换到场景。这个布局传递发生在JavaFX应用程序线程“重新获得控制”之后(即您完成了事件处理程序、application.start方法或让JavaFX执行代码的类似方式)。

注意,您正在以一种非常奇怪的方式使用controller类。我建议使用本问题答案中描述的方法之一与控制器通信:传递参数JavaFX FXML

例如:

public class MovieShowings{

    private AnchorPane root;

    public MovieShowings() {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("movieshowings.fxml"));
            root = loader.load();
            MovieShowingsController controller = loader.getController();
            controller.initMovieShowings(this);
        }

        catch(IOException e){

            e.printStackTrace();
        }

    }
    ...

}
public class MovieShowingsController {

    ...

    public void initMovieShowings(MovieShowings showings) {
        String date = "2019-04-15";
        Date sqlDate = Date.valueOf(date);

         System.out.println("\n");
         System.out.println("***Screenings for " + date + "***");

         filmList = new ArrayList();
         screeningList = DatabaseConnection.getInstance().retrieveScreeningsForDay(sqlDate);

         for (Screening screeningInstance : screeningList) {

             if (!filmList.contains(screeningInstance.getFilmInfo())) {

                 filmList.add(screeningInstance.getFilmInfo());

             }

             System.out.println(screeningInstance.toString());
          }

        Collections.sort(screeningList);

        this.showings = showings;

        //populating FXML instance variable from loader

        // use the injected field here
        buildMovieShowings(vbox);
    }

    ...
}
@FXML
private void initialize()
 类似资料:
  • > 单击 受保护得空onPrepareDialog(int id,Dialog Dialog) 受保护的对话框onCreateDialog(int id) 如果我对timepickerdialog代码做了什么错误,请告诉我。

  • 我有三层根布局、主页和内容(rootlayout.fxml、home.fxml和content.fxml) 像这样,我正在添加内容布局。在rootlayout.fxml中,我有一个home按钮。我的要求是,如果一个用户点击主页按钮,那么我希望内容布局被删除,主页布局是可见的。 在我创建的Controller(在我指向同一个Controller的所有fxml文件中)类中 我面临的问题是我得到了Nul

  • 问题内容: MyClass.java: 编译MyClass.java文件的SimpleCompileTest.java的清单。 SimpleCompileTest.java: 我正在执行SimpleCompileTest类并获取NullPointerException。ToolProvider.getSystemJavaCompiler()返回null。有人可以告诉我代码有什么问题吗 问题答案:

  • 以下是在sun.reflect.nativeMethodAccessorImpl.Invoke0(本机方法)在sun.reflect.nativeMethodAccessorImpl.Invoke(未知源)在sun.reflect.NativeMethodAccessorImpl.Invoke(未知源)在java.lang.Reflect.Method.Invoke(未知源)在com.codena

  • 我试图用Powermock和Mockito编写一个JUnit测试用例。我正在从测试用例下面调用一个方法。此方法从method1调用,而该方法调用Method2。我已经添加了@runwith和@preparefortest注释。 //这是我的测试类: 错误跟踪:

  • 问题内容: 在查询Android日历中的事件之前,我需要检查权限。为此,Android studio警告我在查询之前需要先进行检查。自动生成的代码如下: 尝试运行它时,出现以下错误: 尝试 在空对象引用上调用虚拟方法’int android.content.Context.checkPermission(java.lang.String,int,int)’ 因此很明显,此时某些东西为空,我试图以不