为什么这个JavaFX选项卡窗格示例不起作用?

时间:2017-06-16 10:29:17

标签: javafx

我的MainApp:

package multitabpane;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class MainApp extends Application 
{
  private Stage primaryStage;
  private AnchorPane rootLayout;  

 /** The horizontal offset for making the rootLayout movable */
  private double xOffset = 0;
 /** The vertical offset for making the rootLayout movable */  
  private double yOffset = 0;

  public MainApp() {}

  @Override
  public void start(Stage primaryStage){
    this.primaryStage = primaryStage;
    //Get rid of the windoze crap
    primaryStage.initStyle(StageStyle.UNDECORATED);
    initRootLayout();
    //Make the screen movable by a drag and drop 
    rootLayout.setOnMousePressed((MouseEvent event) -> {
      xOffset = event.getSceneX();
      yOffset = event.getSceneY();
    });
    rootLayout.setOnMouseDragged((MouseEvent event) -> {
      primaryStage.setX(event.getScreenX() - xOffset);
      primaryStage.setY(event.getScreenY() - yOffset);
    });

  }

 /**
  * Initializes the root layout.
  */
  public void initRootLayout() 
  {
    try 
    {
      // Load root layout from fxml file.
      FXMLLoader loader = new FXMLLoader();
     Loader.setLocation(MainApp.class.getResource("view/MainController.fxml"));
      rootLayout = (AnchorPane)loader.load();
      // Show the scene containing the root layout.
      Scene scene = new Scene(rootLayout);
      primaryStage.setScene(scene);
      primaryStage.show();
    } catch (IOException e) {}
  }

 /**
  * Returns the main stage.
  * @return
  */
  public Stage getPrimaryStage() {
    return primaryStage;
  }

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

这是MainController.java和MainController.xml

package multitabpane.view;

import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;

public class MainController {
  // Inject tab content.
    @FXML private AnchorPane fooTabPage;
// Inject controller
    @FXML private FooTabController fooTabPageController;
// Inject tab content. Keep Commented out until the above is working
//    @FXML private BarTabPage barTabPage;
    // Inject controller 
//    @FXML private BarTabController barTabPageController;
}

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

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

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1">
 <TabPane id="tabPane" prefHeight="400.0" prefWidth="600.0">
    <tabs>
        <Tab text="Tab 1">
            <content>
              <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/>
            </content>
        </Tab>
        <Tab text="Tab 2">
            <content>
              <!-- commented out until I can get the above to work -->
              <!-- fx:include fx:id="barTabPage" source="barTabPage.fxml"/ -->
            </content>
        </Tab>
    </tabs>
</TabPane>  
</AnchorPane>

这是FooTabController:

package multitabpane.view;

import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;

class FooTabController {
  @FXML private AnchorPane fooTabPage;
}

最后这是FooTabPage.java和xml:

package multitabpane.view;

class FooTabPage {}

<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

    <AnchorPane fx:id="fooTabPage" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="multitabpane.view.FooTabController" />

当我尝试运行构建的项目时,最后是转储:

Executing D:\J2EE\MultiTabPane\dist\run679227950\MultiTabPane.jar using platform C:\Program Files\Java\jdk1.8.0_60\jre/bin/java
Jun 21, 2017 9:14:22 AM multitabpane.MainApp initRootLayout
Error in MainApp:initRootLayout()
SEVERE: null
file:/D:/J2EE/MultiTabPane/dist/run679227950/MultiTabPane.jar!/multitabpane/view/fooTabPage.fxml:9
javafx.fxml.LoadException: 
file:/D:/J2EE/MultiTabPane/dist/run679227950/MultiTabPane.jar!/multitabpane/view/MainController.fxml:14

文件:/ d:/J2EE/MultiTabPane/dist/run679227950/MultiTabPane.jar /multitabpane/view/fooTabPage.fxml:9 文件:/ d:/J2EE/MultiTabPane/dist/run679227950/MultiTabPane.jar /multitabpane/view/MainController.fxml:14

at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:934)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.access$2700(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$IncludeElement.constructValue(FXMLLoader.java:1143)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:746)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at multitabpane.MainApp.initRootLayout(MainApp.java:58)
at multitabpane.MainApp.start(MainApp.java:35)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$176(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)



 Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil can not access a member of class   multitabpane.view.FooTabController with modifiers ""
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
        at java.lang.Class.newInstance(Class.java:436)
        at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
        at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
        ... 24 more

2 个答案:

答案 0 :(得分:0)

我想问题可能是因为在MainController类中,你将fooTabPage声明为FooTabPage的一个实例,但是在MainController.fxml中,你使用<AnchorPane fx:id="fooTabPage">,简而言之,你在fxml中声明了fooTabPage的差异类型和java类。

只需更改代码

即可
"@FXML private FooTabPage fooTabPage;" 

"@FXML private AnchorPane fooTabPage;" 
在MainController中,问题将得到解决。 因为在你的&#34; fooTabPage.fxml&#34;中,它的根元素是AnchorPane,你应该使用你在fxml根窗格中使用的类型声明相同的类型。

答案 1 :(得分:0)

我通过更改“foo”来解决问题。示例代码中的引用带有更有意义的名称,基于&#39; tab1&#39;和&#39; tab2&#39;。我现在运行构建项目时没有收到错误:

主控制器声明对选项卡的引用:

public class MainController {
   @FXML private AnchorPane tab1Page;   
   @FXML private AnchorPane tab2Page;
} 

在主控制器中,fxml将选项卡引用绑定到其文件源:

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="multitabpane.view.MainController">
  <TabPane id="tabPane" prefHeight="400.0" prefWidth="600.0">
    <tabs>
      <Tab text="Tab 1">
        <content>
          <fx:include fx:id="tab1Page" source="Tab1Controller.fxml"/>
        </content>
      </Tab>
      <Tab text="Tab 2">
        <content>
          <fx:include fx:id="tab2Page" source="Tab2Controller.fxml"/>
        </content>
      </Tab>
    </tabs>
  </TabPane>
</AnchorPane>

在选项卡控制器类中,为选项卡创建引用,并引用用户定义的选项卡的工作区域的任何其他控件。在我的解决方案中,每个选项卡中都有一个按钮控制层次结构,并且按钮的按钮是“按动作”&#39;命令:

public class Tab1Controller {
  @FXML Tab tab1; 
  @FXML Button exitButton;  

  @FXML
  public void exitApp()
  {
    System.exit(1);
  }
}

public class Tab2Controller 
{
  @FXML Tab tab2;
  @FXML Button resetButton;

  @FXML
  public void handleReset()
  {
    System.out.println("Does nothing");
  }
}

标签控制器必须相应地引用它们的控制器:

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="multitabpane.view.Tab1Controller">
  <children>
    <Button fx:id="exitButton" layoutX="92.0" layoutY="136.0" mnemonicParsing="false" onAction="#exitApp" text="Button" />
  </children>
</AnchorPane>

 <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="multitabpane.view.Tab2Controller">
  <children>
    <Button fx:id="resetButton" layoutX="78.0" layoutY="180.0" mnemonicParsing="false" onAction="#handleReset" text="Reset" />
  </children>
</AnchorPane>

总之,有一个MainApp,三个控制器类和3个相应的FXML视图。