用JavaFX打开多个窗口 [英] Opening multiple windows with JavaFX

查看:1117
本文介绍了用JavaFX打开多个窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用JavaFX打开多个窗口,当一个按钮点击它时,我有一个eventlistener打开一个新窗口,如下所示:

  @FXML 
private void joinAction(){
父根;
try {
Stage stage =(Stage)joinButton.getScene()。getWindow();
stage.close();

root = FXMLLoader.load(getClass()。getResource(main.fxml));
stage = new Stage();
stage.setTitle(TuneUs);
stage.setScene(new Scene(root));
stage.show();

} catch(IOException e){e.printStackTrace();}
}

第一个窗口打开,新的打开,但是我的问题是让事件在第二个窗口中使用



main.fxml 我有这个行:

 < TextField id =chat_baronAction = #sendChatlayoutX =14.0layoutY =106.0prefHeight =22.0prefWidth =403.0/> 

然后在我的控制器类中,我有这个方法:

  @FXML 
private void sendChat(){
System.out.println(test);
}

但Intellij告诉我;没有为顶级元素指定的控制器



所以,我的问题是:我需要创建多个控制器类,如果是这样,我可以使用一个多窗口? / p>

解决方案

推荐的方法是为每个FXML定义一个控制器。由于控制器非常轻便,所以不应该增加太多的开销。您的main.fxml文件的控制器可能与

  import javafx.fxml.FXML一样简单; 

public class MainController {
@FXML
private void sendChat(){
// ...
}
}
/ / code>

我在一个项目中使用了相当大量的FXML文件和相应的控制器,并且没有管理代码的问题等等。我建议使用 Main.fxml< - >的形式的命名约定MainController



如果您的控制器需要共享数据,请使用传递参数JavaFX FXML



正如@Vertex在评论中指出的那样是由 FXMLLoader.setController(...)方法提供的另一种方法。所以在上面的例子中,你可以执行

  @FXML 
private void joinAction(){
Parent根;
try {
Stage stage =(Stage)joinButton.getScene()。getWindow();
stage.close();

FXMLLoader loader = new FXMLLoader(getClass()。getResource(main.fxml));
loader.setController(this);
root = loader.load();
stage = new Stage();
stage.setTitle(TuneUs);
stage.setScene(new Scene(root));
stage.show();

} catch(IOException e){e.printStackTrace();}
}

@FXML
private void sendChat(){
// ...
}

如果您没有设置任何通过FXML注入(即在fxml中使用 fx:id 属性的字段(控件)和相应的 @FXML 注释在控制器中)。如果你是这样,那么很难跟踪这些字段何时被设置。此外,如果您的 joinAction 处理程序被多次调用,则将有多个由main.fxml创建的节点实例,但是所有实例都共享一个控制器实例(并因此覆盖相同的注入场)。还要注意,使用这种方法,当加载原始的fxml文件时, c c>初始化()将被调用 strong>当main.fxml文件被加载时,几乎肯定会导致不必要的影响。



最后一个注意事项:如果你有很多FXML文件和相应的控制器,你可能要查看 afterburner.fx框架。这是一个非常轻量级的框架,它要求对FXML文件及其对应的控制器进行命名约定,并且还提供了一种(非常)容易的在它们之间共享数据的机制。


I'm trying to open multiple windows with JavaFX, I have an eventlistener that opens a new window when a button is clicked it looks like this:

@FXML
private void joinAction() {
    Parent root;
    try {
        Stage stage = (Stage) joinButton.getScene().getWindow();
        stage.close();

        root = FXMLLoader.load(getClass().getResource("main.fxml"));
        stage = new Stage();
        stage.setTitle("TuneUs");
        stage.setScene(new Scene(root));
        stage.show();

    } catch (IOException e) {e.printStackTrace();}
}

the first window opens and the new one opens, but my problem is getting events to work with my second window

in main.fxml I have this line:

<TextField id="chat_bar" onAction="#sendChat" layoutX="14.0" layoutY="106.0" prefHeight="22.0" prefWidth="403.0"/>

Then in my controller class I have this method:

@FXML
private void sendChat() {
    System.out.println("test");
}

but Intellij is telling me that; no controller specified for top level element

So, my question is: Do I need to create multiple controller classes or can I use just one for multiple windows if so how?

解决方案

The recommended approach is to define a controller for each FXML. Since controllers are very lightweight this shouldn't add much overhead. The controller for your main.fxml file might be as simple as

import javafx.fxml.FXML ;

public class MainController {
  @FXML
  private void sendChat() {
    // ...
  }
}

I have used this approach with fairly large numbers of FXML files and corresponding controllers in a single project, and have had no issues with managing the code etc. I recommend using a naming convention of the form Main.fxml <-> MainController.

If your controllers need to share data, use the techniques outlined in Passing Parameters JavaFX FXML

As @Vertex points out in the comments, there is an alternative approach provided by the FXMLLoader.setController(...) method. So in your example above, you could do

@FXML
private void joinAction() {
    Parent root;
    try {
        Stage stage = (Stage) joinButton.getScene().getWindow();
        stage.close();

        FXMLLoader loader = new FXMLLoader (getClass().getResource("main.fxml"));
        loader.setController(this);
        root = loader.load();
        stage = new Stage();
        stage.setTitle("TuneUs");
        stage.setScene(new Scene(root));
        stage.show();

    } catch (IOException e) {e.printStackTrace();}
}

@FXML
private void sendChat() {
    // ...
}

This approach is fine if you are not setting any fields (controls) via FXML injection (i.e. with an fx:id attribute in the fxml and a corresponding @FXML annotation in the controller). If you are, it will be very difficult to keep track of when those fields have been set. Moreover, if your joinAction handler is invoked multiple times, you will have multiple instances of the node created by main.fxml, but all sharing a single controller instance (and consequently overwriting the same injected fields). Also note that with this approach, your initialize() method will be invoked both when the original fxml file is loaded, and when the main.fxml file is loaded, which will almost certainly cause undesired effects.

One last note: if you have many FXML files, and corresponding controllers, you might want to look at the afterburner.fx framework. This is a very lightweight framework that mandates a naming convention on FXML files and their corresponding controllers, and also provides a (very) easy mechanism for sharing data between them.

这篇关于用JavaFX打开多个窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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