如何实现JavaFX和非JavaFX的交互? [英] How to achieve JavaFX and non-JavaFX interaction?

查看:51
本文介绍了如何实现JavaFX和非JavaFX的交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始使用JavaFX创建用于用户交互的窗口,以便在另一个非JavaFX程序中使用.

I have started using JavaFX to create a window for user interaction, to be used in another, non-JavaFX, program.

我的主程序称为Abc类,具有一个main方法.这是一个非JavaFX程序,但却是普通的Java.该程序运行一些活动,然后要求用户从可能的Strings列表中选择String.用户交互是通过名为MenuSelector的JavaFX程序完成的.用户选择一个String,然后将其返回到Abc进行进一步处理.

My main program is called the Abc class, having a main method. This is a non-JavaFX program, but plain vanilla Java. This program runs some activities, then asks the user to select a String from a list of possible Strings. This user interaction is done with a JavaFX program called MenuSelector. The user selects one String, which will then be returned to Abc for further processing.

MenuSelector是使用Netbeans和Scene Builder制作的,它使用三个文件:FXMLDocument.fxmlFXMLDocumentController.javaMenuSelector.java.选择过程的处理在FXMLDocumentController.java中完成. MenuSelector.java类仅定义StageScene.

MenuSelector is made with Netbeans and Scene Builder, which uses three files: FXMLDocument.fxml, FXMLDocumentController.java, and MenuSelector.java. Handling of the selection process is done in FXMLDocumentController.java. The MenuSelector.java class only defines the Stage and Scene.

我在网上找不到的内容是Abc如何启动MenuSelector的说明.并且找不到说明如何将FXMLDocumentController中的结果String传递回Abc.我应该采取什么步骤来启动并运行它?

What I can not find online is instructions for how Abc would start MenuSelector. And can not find instructions how the resulting String in FXMLDocumentController can be passed back to Abc. What steps should I take to get this up and running?

有人问我这样做的原因.有人建议我遇到设计问题.

I was asked about the reason for having things this way. It was suggested that I am having a design problem.

我目前对MenuSelector的实现是使用javax.swing.这是在一个称为MenuSelector的java类中进行手工编码的,具有一个可以从其他程序(例如AbcDef,..)调用的顶级方法.此MenuSelector是支持软件,可以由多个程序使用.每个程序都可以向菜单提交一个字符串列表,用户可以从中选择一个String,然后将其返回到名为此MenuSelector的程序.

My current implementation of the MenuSelector is with using javax.swing. This is hand-coded in one java class called MenuSelector, having a top level method which can be called from other programs (e.g. Abc, Def, ..). This MenuSelector is a supporting piece of software which can be used by multiple programs. Each program can submit a list of Strings to the menu, out of which the user can select one String, which will then be returned to the program which called this MenuSelector.

MenuSelector因此没有main方法,只有一个可以被其他人调用的顶级方法. MenuSelector是支持程序,不应被认为是最高级别.

The MenuSelector therefore does not have a main method, only a top-level method which can be called by others. MenuSelector is a supporting program, and is not supposed to be the highest level.

我的尝试是用JavaFX版本替换MenuSelector的手工编码javax.swing版本.但是,只有在可以输入字符串列表作为菜单输入并返回单个字符串作为结果的情况下,我才能执行此操作.

My attempt is to replace the hand-coded javax.swing version of MenuSelector by a JavaFX version. But I can only do this if I can input a list of Strings as input to the menu, and return a single String as result.

编辑,以解释由Netbeans生成的JavaFX结构:

Edit, to explain the JavaFX structure as generated by Netbeans:

生成新的Netbeans JavaFX项目时,它带有三个文件:FXMLDocument.fxmlFXMLDocumentController.javaMenuSelectorFX.java.用Scene Builder构建GUI并创建控制软件后,这三个的内容为:

When generating a new Netbeans JavaFX project it comes with three files: FXMLDocument.fxml, FXMLDocumentController.java, and MenuSelectorFX.java. After building the GUI with Scene Builder and creating the control software the contents of these three are:

FXMLDocument.fxml(不是我手动修改的):

FXMLDocument.fxml (not manually modified by me):

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171" fx:controller="menuselector.FXMLDocumentController">
   <children>
      <VBox alignment="CENTER" prefHeight="200.0" prefWidth="320.0" spacing="20.0">
         <children>
            <ChoiceBox fx:id="InstrumentChoiceBox" prefWidth="150.0" />
            <Button mnemonicParsing="false" onAction="#onChoiceMade" text="This One" />
            <Label fx:id="SelectionLabel" text="Label" />
         </children>
      </VBox>
   </children>
</AnchorPane>

FXMLDocumentController.java(由我添加的代码):

FXMLDocumentController.java (code added by me):

package menuselector;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;

public class FXMLDocumentController implements Initializable {

    @FXML private ChoiceBox InstrumentChoiceBox;
    @FXML private Label SelectionLabel;
    private String SelectedInstrument;

    public String getSelectedInstrument(){
        return SelectedInstrument;
    }

    public void onChoiceMade(){
        SelectedInstrument = InstrumentChoiceBox.getSelectionModel().getSelectedItem().toString();
        SelectionLabel.setText("Instrument selected: "+SelectedInstrument);
    }

    private String[] determineCandidates(){
        //method to determine the list of candidates, abbreviated
        //Reads in a number of Strings from file and converts to String[]
        return Result;
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        String[] Candidates = determineCandidates();
        SelectedInstrument = "";
        for(int i = 0; i < Candidates.length;i++) InstrumentChoiceBox.getItems().add(Candidates[i]);
        InstrumentChoiceBox.setValue(Candidates[0]);
    }
}

,最后是MenuSelectorFX(我没有手动修改):

and finally MenuSelectorFX (not manually modified by me):

package menuselector;

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

public class MenuSelectorFX extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
   }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

直到现在,我可以使用以下行从非JavaFX类Abc(或Def)调用MenuSelector:

Until now have I been able to call the MenuSelector from my non-JavaFX class Abc (or Def) by using the lines:

        MenuSelectorFX msfx = new MenuSelectorFX();
        msfx.main(new String[0]);

这将通过选择框启动GUI,并且当我选择一个选项时,所选的选项会显示在GUI中.我还无法实现的是将FXMLDocumentController中的参数SelectedInstrument返回到Abc.

This starts the GUI with the choice box, and when I select an option the chosen option is displayed in the GUI. What I have not yet been able to achieve is the return of parameter SelectedInstrument in FXMLDocumentController to Abc.

推荐答案

我制作了一个小程序来构建我了解您正在尝试做的事情. Abc类启动,并从用户那里得到一些输入.使用该输入,我们将在组合框中启动带有某些选项的JavaFX窗口.从组合框中选取的值返回到Abc,我们可以使用它.

I made a small program to build what I understood you are trying to do. The Abc class starts and get some input from the user. With that input we start the JavaFX Window with some options in a combobox. The picked value from the combobox is returned to Abc and we can use it.

Abc类:

package application;

import java.util.Scanner;

public class Abc {

    public static void main(String[] args) {
        System.out.println("Some activitives...");
        System.out.println("Press 1 to start JAVAFX");

        try(Scanner input = new Scanner(System.in)){
            int one = input.nextInt();
            if(one == 1) {
                String[] inputedValue = new String[] {String.valueOf(one)};
                MainJavaFX.main(inputedValue);
                System.out.println("The user picked " + FXMLDocumentController.selectedValue);
                System.out.println("Go on and use it...");
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

MainJavaFX应用程序.注意我做了一个MyStrings类来填充组合框:

The MainJavaFX application. Note I made a MyStrings class to populate the combobox:

package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;


public class MainJavaFX extends Application {
@Override
public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("Document.fxml"));
    AnchorPane root = loader.load();
    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
   }

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
}

控制器:

package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;

public class FXMLDocumentController implements Initializable {

    @FXML private ChoiceBox InstrumentChoiceBox;
    @FXML private Label SelectionLabel;
    @FXML private Button selectionButton;
    static String SelectedInstrument;

    public String getSelectedInstrument(){
        return SelectedInstrument;
    }

    public void onChoiceMade(){
        SelectedInstrument = InstrumentChoiceBox.getSelectionModel().getSelectedItem().toString();
        SelectionLabel.setText("Instrument selected: "+SelectedInstrument);
        selectionButton.getScene().getWindow().hide();
    }

    private String[] determineCandidates(){
        //method to determine the list of candidates, abbreviated
        //Reads in a number of Strings from file and converts to String[]
        return new String[] {"a","b","c"};
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        String[] Candidates = determineCandidates();
        SelectedInstrument = "";
        for(int i = 0; i < Candidates.length;i++) InstrumentChoiceBox.getItems().add(Candidates[i]);
        InstrumentChoiceBox.setValue(Candidates[0]);
    }
}

Document.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171" fx:controller="application.FXMLDocumentController">
   <children>
      <VBox alignment="CENTER" prefHeight="200.0" prefWidth="320.0" spacing="20.0">
         <children>
            <ChoiceBox fx:id="InstrumentChoiceBox" prefWidth="150.0" />
            <Button fx:id="selectionButton" mnemonicParsing="false" onAction="#onChoiceMade" text="This One" />
            <Label fx:id="SelectionLabel" text="Label" />
         </children>
      </VBox>
   </children>
</AnchorPane>

运行时的输出:

Some activitives...
Press 1 to start JAVAFX
-- The JavaFX Window pops up --
The user picked b
Go on and use it...

我添加了一个控制器类,因此您具有相同的结构.请注意,该按钮现在具有一个ID,因此在用户从组合框中选择一个值之后,我可以使用它来关闭JavaFX.我还将选定的String值设为静态,因此可以从打印的Abc类中调用它.

I added a controller class so you have the same structure. Note that the button has now an Id so I can use it to close the JavaFX after the user picked a value from the combobox. I also made the selected String value static so I can just call it from the Abcclass in my print.

这篇关于如何实现JavaFX和非JavaFX的交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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