如何在javafx中传递参数到辅助窗口?是否有与相应控制器通信的方法?

例如: 用户从TableView中选择一个客户,然后打开一个新窗口,显示该客户的信息。

Stage newStage = new Stage();
try 
{
    AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
    Scene scene = new Scene(page);
    newStage.setScene(scene);
    newStage.setTitle(windowTitle);
    newStage.setResizable(isResizable);
    if(showRightAway) 
    {
        newStage.show();
    }
}

newStage将是新窗口。问题是,我找不到一种方法告诉控制器在哪里寻找客户的信息(通过传递id作为参数)。

什么好主意吗?


当前回答

下面是一个使用Guice注入的控制器的例子。

/**
 * Loads a FXML file and injects its controller from the given Guice {@code Provider}
 */
public abstract class GuiceFxmlLoader {

   public GuiceFxmlLoader(Stage stage, Provider<?> provider) {
      mStage = Objects.requireNonNull(stage);
      mProvider = Objects.requireNonNull(provider);
   }

   /**
    * @return the FXML file name
    */
   public abstract String getFileName();

   /**
    * Load FXML, set its controller with given {@code Provider}, and add it to {@code Stage}.
    */
   public void loadView() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(getFileName()));
         loader.setControllerFactory(p -> mProvider.get());
         Node view = loader.load();
         setViewInStage(view);
      }
      catch (IOException ex) {
         LOGGER.error("Failed to load FXML: " + getFileName(), ex);
      }
   }

   private void setViewInStage(Node view) {
      BorderPane pane = (BorderPane)mStage.getScene().getRoot();
      pane.setCenter(view);
   }

   private static final Logger LOGGER = Logger.getLogger(GuiceFxmlLoader.class);

   private final Stage mStage;
   private final Provider<?> mProvider;
}

下面是加载器的具体实现:

public class ConcreteViewLoader extends GuiceFxmlLoader {

   @Inject
   public ConcreteViewLoader(Stage stage, Provider<MyController> provider) {
      super(stage, provider);
   }

   @Override
   public String getFileName() {
      return "my_view.fxml";
   }
}

注意这个例子将视图加载到BoarderPane的中心,BoarderPane是Stage中Scene的根。这与示例(我的特定用例的实现细节)无关,但决定保留它,因为有些人可能会发现它有用。

其他回答

这是有效的。

记住,当你第一次打印传递的值时,你会得到null, 你可以在你的窗口加载后使用它,对你想为任何其他组件编码的所有东西都是一样的。

第一个控制器

try {
    Stage st = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/inty360/free/form/MainOnline.fxml"));

    Parent sceneMain = loader.load();

    MainOnlineController controller = loader.<MainOnlineController>getController();
    controller.initVariable(99L);

    Scene scene = new Scene(sceneMain);
    st.setScene(scene);
    st.setMaximized(true);
    st.setTitle("My App");
    st.show();
} catch (IOException ex) {
    Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);
}

另一个控制器

public void initVariable(Long id_usuario){
    this.id_usuario = id_usuario;
    label_usuario_nombre.setText(id_usuario.toString());
}

您必须创建一个上下文类。

public class Context {
    private final static Context instance = new Context();
    public static Context getInstance() {
        return instance;
    }

    private Connection con;
    public void setConnection(Connection con)
    {
        this.con=con;
    }
    public Connection getConnection() {
        return con;
    }

    private TabRoughController tabRough;
    public void setTabRough(TabRoughController tabRough) {
        this.tabRough=tabRough;
    }

    public TabRoughController getTabRough() {
        return tabRough;
    }
}

你只需要在初始化时设置controller的实例

Context.getInstance().setTabRough(this);

你可以在整个应用中使用它

TabRoughController cont=Context.getInstance().getTabRough();

现在你可以从整个应用程序中传递参数到任何控制器。

node类有一对方法 setUserData(对象) 而且 对象getUserData ()

您可以使用它将您的信息添加到Node。

因此,你可以调用page.setUserData(info);

如果设置了info,控制器可以检查。此外,如果需要,还可以使用ObjectProperty进行前后数据传输。

请看下面的文档: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html 在第一个版本中,handleButtonAction()被标记为@FXML,以允许控制器文档中定义的标记调用它。在第二个示例中,button字段被注释以允许加载器设置它的值。initialize()方法也有类似的注释。”

因此,您需要将控制器与节点关联起来,并将用户数据设置为节点。

下面是一个使用Guice注入的控制器的例子。

/**
 * Loads a FXML file and injects its controller from the given Guice {@code Provider}
 */
public abstract class GuiceFxmlLoader {

   public GuiceFxmlLoader(Stage stage, Provider<?> provider) {
      mStage = Objects.requireNonNull(stage);
      mProvider = Objects.requireNonNull(provider);
   }

   /**
    * @return the FXML file name
    */
   public abstract String getFileName();

   /**
    * Load FXML, set its controller with given {@code Provider}, and add it to {@code Stage}.
    */
   public void loadView() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(getFileName()));
         loader.setControllerFactory(p -> mProvider.get());
         Node view = loader.load();
         setViewInStage(view);
      }
      catch (IOException ex) {
         LOGGER.error("Failed to load FXML: " + getFileName(), ex);
      }
   }

   private void setViewInStage(Node view) {
      BorderPane pane = (BorderPane)mStage.getScene().getRoot();
      pane.setCenter(view);
   }

   private static final Logger LOGGER = Logger.getLogger(GuiceFxmlLoader.class);

   private final Stage mStage;
   private final Provider<?> mProvider;
}

下面是加载器的具体实现:

public class ConcreteViewLoader extends GuiceFxmlLoader {

   @Inject
   public ConcreteViewLoader(Stage stage, Provider<MyController> provider) {
      super(stage, provider);
   }

   @Override
   public String getFileName() {
      return "my_view.fxml";
   }
}

注意这个例子将视图加载到BoarderPane的中心,BoarderPane是Stage中Scene的根。这与示例(我的特定用例的实现细节)无关,但决定保留它,因为有些人可能会发现它有用。

是的,你可以。 你需要添加第一个控制器:

YourController controller = loader.getController();     
controller.setclient(client);

然后在第二个语句中声明一个客户端,然后在控制器的底部:

public void setclien(Client c) {
    this.client = c;
}