JavaFx处理程序覆盖

时间:2015-05-13 11:14:52

标签: javafx override

我有一个来自fxml构建器的fxml文件构建,我在Java中使用它。

URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");

FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
Pane rootPane = (Pane) loader.load(); 

此fxml文件将click事件映射到我的班级;

<Group id="Group" layoutX="0.0" layoutY="0.0" onMouseReleased="#handleThis" scaleX="1.0" scaleY="1.0">
...
<Group/>

所以我在我的类中实现我的处理程序,我们称之为MyClass;

public class MyClass {
public void createScene() throws IOException
{
    URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");

    FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
    Pane rootPane = (Pane) loader.load(); 
    ...
}

@FXML
public void handleThis(ActionEvent event) {
    System.out.println("from MyClass");
}
        ...
}

现在我将MyClass扩展为MyExtendedClass并覆盖handleThis方法;

public class MyExtendedClass extends MyClass {
    @Override
    public void handleThis(ActionEvent event) {
           System.out.println("from MyExtendedClass");
    }
}

我的问题是,我无法在扩展类中设法处理handle方法。它不会覆盖它。如何使其“从MyExtendedClass”而不是“从MyClass”打印?

1 个答案:

答案 0 :(得分:0)

在MyExtendedClass实例上调用createScene()时,FXMLLoader会解析FXML文件,读取fx:controller="MyClass"属性并实例化 MyClass类型的 new 对象即可。这就是为什么总是调用基本方法的原因。 FXMLLoader不了解MyExtendedClass。

有一种 - hackish - 实现你想要的方式(即在MyClass中加载并仍在FXML中定义控制器):

public class MyClass
{
    public void createScene()
    {
        try
        {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("FXML.fxml"));
            // set a controller factory that returns this instance as controller
            // (works in this case, but not recommended)
            loader.setControllerFactory(controllerType -> this);
            pane = (Pane) loader.load();
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }
}

实例化控制器并将其传递给FXMLLoader会更清晰 为此,必须从FXML文件中删除fx:controller=""属性。

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        MyClass controller = new MyExtendedClass();

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("FXML.fxml"));
        loader.setController(controller);
        Pane pane = (Pane) loader.load();

        primaryStage.setScene(new Scene(pane));
        primaryStage.show();
    }

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

或者使用fx:controller="MyClass"在FXML文件中定义基本类型,让控制器工厂决定实际实现。

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("FXML.fxml"));
        loader.setControllerFactory(controllerType -> {
            if (MyClass.class.equals(controllerType))
                return new MyExtendedClass();
            else
                return null; // return some other controller
        });
        Pane pane = (Pane) loader.load();

        MyClass controller = (MyClass) loader.getController();

        primaryStage.setScene(new Scene(pane));
        primaryStage.show();
    }

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