JavaFX FXML 控制器 ClassNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20452035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:02:57  来源:igfitidea点击:

JavaFX FXML controller ClassNotFoundException

javauitableviewdynamicjavafx

提问by user3063257

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

我试图在 JavaFX 中获取一个 TableView 来动态显示内容。

When I run my program I get this error:

当我运行我的程序时,我收到此错误:

java.lang.ClassNotFoundException: UserInterfaceController

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?

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

FXML file:

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>

Controller:

控制器:

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) {

    }

}

Main Class:

主要类:

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);
    }
}

采纳答案by jewelsea

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

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

fx:controller="d1example2.UserInterfaceController"

Answers to follow-up questions

对后续问题的回答

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.

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

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

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

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 nameas per the Java language specification).

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

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.

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

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

如果无论如何我都需要这样做,import 语句有什么意义?

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

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

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

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

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

<GridPane alignment="center" ...>

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.

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