JavaFX FXML 控制器 ClassNotFoundException [英] JavaFX FXML controller ClassNotFoundException

查看:28
本文介绍了JavaFX FXML 控制器 ClassNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 JavaFX 中获取一个 TableView 来动态显示内容.

I am trying to get a TableView in JavaFX to dynamically display content.

当我运行我的程序时出现此错误:

When I run my program I get this error:

java.lang.ClassNotFoundException: UserInterfaceController

我的控制器名为UserInterfaceController.java",它与 FXML 文件在同一个包下,我也在 FXML 中导入了该包.为什么找不到控制器?

My controller is named "UserInterfaceController.java", it's under the same package as the FXML file and I have imported the package in the FXML as well. Why can't the controller be found?

FXML 文件:

<?import javafx.collections.*?> 
<?import javafx.geometry.Insets?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.layout.*?>
<?import d1example2.*?>

<GridPane alignment="center" hgap="10.0" vgap="10.0" fx:controller="UserInterfaceController"
             xmlns:fx="http://javafx.com/fxml">
     <TableView fx:id="tableView" GridPane.columnIndex="0" GridPane.rowIndex="1">
          <columns>
          </columns>    
     </TableView>
</GridPane>

控制器:

package d1example2;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Text;
import javafx.util.Callback;

public class UserInterfaceController implements Initializable {

    private Label label;
    @FXML
    private AnchorPane MainPane;
    @FXML
    private TextField FirstField;
    @FXML
    private Text TimesText;
    @FXML
    private Text EqualSign;
    @FXML
    private Text EquationResult;
    @FXML
    private TableColumn<?, ?> HalfColumn;
    @FXML
    private TableColumn<?, ?> DoubleColumn;
    @FXML
    private Button SubmitButton;

    @FXML private TableView tableView;

    @FXML
    public void initialize(URL url, ResourceBundle rb) {

    List<String> columns = new ArrayList<String>();
    columns.add("col1");
    columns.add("col2");
    TableColumn [] tableColumns = new TableColumn[columns.size()];     
    int columnIndex = 0;
    for(int i=0 ; i<columns.size(); i++) {
        final int j = i;
        TableColumn col = new TableColumn(columns.get(i));
        col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){                   
           public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {                                                                                             
                return new SimpleStringProperty(param.getValue().get(j).toString());                       
            }                   
        });
        tableView.getColumns().addAll(col);
    }       
    ObservableList<String> row = FXCollections.observableArrayList();
    ObservableList<String> row1 = FXCollections.observableArrayList();
    row.addAll("d1");
    row.addAll("d11");
    row1.addAll("d2");
    row1.addAll("d22");
    tableView.getItems().add(row);
    tableView.getItems().add(row1);
    }    

    @FXML
    private void handleButtonAction(MouseEvent event) {

    }

}

主类:

package d1example2;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class D1Example2 extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("FXML TableView Example");
        Pane myPane = (Pane)FXMLLoader.load(getClass().getResource("UserInterface.fxml"));
        Scene myScene = new Scene(myPane);
        primaryStage.setScene(myScene);
        primaryStage.show();
    }

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

推荐答案

使用 FXML 的完全限定名称引用您的控制器:

Reference your controller from FXML using it's fully qualified name:

fx:controller="d1example2.UserInterfaceController"

回答后续问题

以下问题的答案解释了为什么会这样,但如果您不想,您不一定需要了解原因,以下内容仅供参考.

Answers to the following questions explain why this is so, but you don't necessarily need to understand why if you don't want to, the following is purely informational.

他有import语句的时候为什么一定要全限定呢?

Why must it be fully qualified when he has an import statement?

解析 FXML 控制器类时不会搜索 FXML 文件中的导入.控制器类类型是通过类加载器找到的(我通过阅读 JavaFX FXMLLoader 源代码).类加载器需要一个完全限定的名称(特别是 二进制名称,根据 Java 语言规范).

The imports in the FXML file are not searched when resolving the FXML controller class. The controller class type is found via the class loader (I determined this by reading the JavaFX FXMLLoader source code). The class loader requires a fully qualified name (specifically, a binary name as per the Java language specification).

一旦找到类型,如果没有为 fxml 加载指定控制器工厂,那么 FXMLLoader 将使用反射实例化控制器本身,否则它将将该作业委托给适当的控制器工厂(例如关联的控制器工厂)一个基于 Spring 依赖注入的控制器实例),但即使在该实例中,也必须首先由 FXMLLoader 找到并确定适当的类型,为此它需要控制器的完全限定类名.

Once the type is found, if no controller factory has been specified for the fxml loading, then the FXMLLoader will instantiate the controller itself using reflection, otherwise it will delegate that job to an appropriate controller factory (e.g. a controller factory that associates a controller instance based upon Spring dependency injection) but even in that instance, the appropriate type must be found and determined by the FXMLLoader first and to do that it requires a fully qualified classname for the controller.

如果我需要这样做,import 语句的意义何在?

What's the point of import statements if I need to do that anyway?

导入语句用于解析与文档中的 FXML 元素对应的 Java 类型.这样,文档可以包含以下行:

The import statements are used for resolving the Java types corresponding to the FXML elements in the document. That way, the document can contain the line:

<?import javafx.scene.layout.*?>

当您想在 FXML 中定义新的 GridPane 时,您可以只引用 GridPane 而不是 javafx.scene.layout.GridPane.

And you can just reference GridPane instead of javafx.scene.layout.GridPane, when you want to define a new GridPane in your FXML.

<GridPane alignment="center" ...>

是的,潜在地,FXMLLoader 可以编码为也以相同的方式解析控制器类,但在编写此答案时还没有这样编写.

Yes, potentially, the FXMLLoader could have been coded to also resolve controller classes in the same manner, but it just hasn't been written that way at the time that this answer was written.

这篇关于JavaFX FXML 控制器 ClassNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆