我正在使用JavaFX创建一个Desktop UI.该应用程序将打开一个窗口,用户在关闭窗口之前将在其中输入一些信息.我返回数据的最初 idea 是让这个打开的窗口将信息保存到类变量中.我将使用getters从创建UI应用程序的类中检索数据.然而,在窗口关闭后,变量似乎被重置为其原始值,并且我无法检索数据.下面是我正在努力实现的伪代码.

用户界面的类.

public class MyScreen extends Application {
    private String userText;

    public void openWindow() {
        launch();
        System.out.println("3. " + userText); // Outputs empty string.
    }

    @Override
    private void start(Stage stage) {
        // Create window controls
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(final ActionEvent event) {
                // Do stuff with user data
                System.out.println("1. " + userText); // Outputs empty string
                userText = textField.getText();
                System.out.println("2. " + userText); // Outputs user inputted text.
                stage.close();
            }
        })
    }

    public getUserText() {
        return userText;
    }
}

调用类.

public class MyMainClass {
    public static void main(String args[]) {
        MyScreen screen = New MyScreen();
        screen.openWindow();
        System.out.println("4. " + screen.getUserText());
    }
}

运行我的进程的样例输出:

> 1.
> 2. sample text
> 3.
> 4.

从实例化一个JavaFX UI的类返回数据的正确方法是什么?

推荐答案

我将对Slaw,here&Amp;here的两条 comments 做出回答.

JavaFX “magic”

JavaFX是一个复杂的框架,它比您在您自己的源代码中看到的要"神奇"得多.

其中一个神奇之处在于,当您的JavaFX应用程序启动时,Application的子类将通过reflection自动实例化.

所以你的代码行MyScreen screen = New MyScreen();是多余的,应该删除.JavaFX框架已经创建了MyScreen的一个实例作为Application的子类.因此,您的应用程序有两个MyScreen Go实例,一个由JavaFX框架隐式创建,另一个由您在该行代码中创建.

这就解释了为什么您无法获得userText字段的值.您的代码调用的是MyScreenyour实例,而不是JavaFX框架的MyScreen实例.userText字段确实设置了,但设置在后者,而不是前者.

this hack

如果您really想要在您的给定方法中跟踪应用程序中的状态,我见过一个黑客攻击,其中人们对其Application子类的隐式实例化对象进行了Singleton次引用.他们在子类Application上添加static变量,这是子类类型的变量.然后,在其Application#start覆盖实现中,它们将this赋值给该变量.

public class MyScreen extends Application {
    public static MyScreen myInstanceOfMyScreen;
    private String userText;

    @Override
    private void start(Stage stage) {
        …
        this.myInstanceOfMyScreen = this ;  // A hack, not necessarily recommended. 
    }

    public getUserText() {
        return userText;
    }
        

然后其他类就可以访问这static个单例.

// Some code in some other class
String userText = MyScreen.myInstanceOfMyScreen.getUserText() ;

但这种方法很可能表明您的应用程序中存在糟糕的设计.

JavaFX生命周期

要了解有关JavaFX应用程序生命周期的更多信息,请参阅另一个问题的my lengthy Answer.

警告:我不是JavaFX方面的专家.要获得更多专业知识,请查找jewelseaSlawJames_D和其他方面的帖子.并阅读the documentation.

GUI app versus console app

您设计应用程序的方法似乎很奇怪,将基于JavaFX的图形用户界面应用程序作为更大的"外部"应用程序的子 routine 运行.

图形用户界面应用程序是独立的.图形用户界面的生命周期应该是应用程序的生命周期.如果图形用户界面的所有元素都已经关闭,没有更多的窗口和菜单栏,那么应用程序应该结束.

您将Application个子类命名为MyScreen这一事实表明,您认为JavaFX只是您应用程序的一部分.相反,您应该将JavaFX作为您的entire应用程序.

如果您的目标是构建一个从用户那里收集输入的控制台应用程序,那么可以使用与控制台相关的Java类(如Scanner)在控制台上与用户交互.试图将图形用户界面应用程序与控制台应用程序混合在一起是没有意义的,从MacOS、Windows、Linux等现代操作系统的架构设计来看是没有意义的.

唯一例外是希望在终端屏幕中运行图形用户界面的面向控制台的环境.这类应用程序被称为text-based user-interface,微软因其COW(Character-Oriented Windows)应用程序(如Microsoft Works for MS-DOS)而闻名.但这类应用程序应该在终端屏幕/窗口中运行.相反,JavaFX应用程序应该在MacOS/Windows/Linux/等图形环境中运行.仅供参考,Java生态系统确实提供了一些框架来构建基于文本的UI应用程序,例如Lanterna.

通信数据

如果您需要共享超出图形用户界面限制的用户输入,请使用外部系统.例如,将数据发布到message queue,发送邮箱,插入数据库,将文件写入存储.

Example app

以下是一个JavaFX应用程序示例:

  1. 收集来自用户的输入.
  2. 将数据报告到消息队列、发送邮箱并写入数据库.
  3. 退出/退出应用程序.

screenshot of example app soliciting the user for their favorite color, along with a button to submit that data and then exit the app

请注意,在向该队列、邮箱和数据库报告时,该图形用户界面保持可见.如果出现任何错误,您可以使用该图形用户界面来通知用户问题.

package work.basil.example.exfxgatherinput;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;

public class GatherInputApp extends Application
{
    @Override
    public void start ( Stage stage ) throws IOException
    {
        // Scene
        Scene scene = this.makeScene ( );

        // Stage
        stage.setTitle ( "Give me your input" );
        stage.setHeight ( 300 );
        stage.setWidth ( 500 );

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

    private Scene makeScene ( )
    {
        // Data input
        Label inputLabel = new Label ( "Favorite color:" );
        TextField inputTextField = new TextField ( );
        HBox inputBox = new HBox ( );
        inputBox.setAlignment ( Pos.CENTER );
        inputBox.getChildren ( ).addAll ( inputLabel , inputTextField );
        inputBox.setSpacing ( 10 );

        // Submit data
        Button button = new Button ( );
        button.setText ( "Submit input, quit app" );
        button.setOnAction ( ( event ) ->
        {
            String favoriteColor = inputTextField.getText ( );
            System.out.println ( "Reporting input to a message queue… " + favoriteColor );
            System.out.println ( "Sending input in an email… " + favoriteColor );
            System.out.println ( "Writing input to a database… " + favoriteColor );
            Platform.exit ( );  // Ends the JavaFX app, after firing hooks for app-shutdown. 
        } );

        VBox vbox = new VBox ( inputBox , button );
        vbox.setPadding ( new Insets ( 20 , 20 , 20 , 20 ) );
        vbox.setSpacing ( 10 );
        vbox.setAlignment ( Pos.CENTER );

        return new Scene ( vbox );
    }

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

运行时:

Reporting input to a message queue… purple
Sending input in an email… purple
Writing input to a database… purple

Process finished with exit code 0

顺便说一句,以编程方式退出图形用户界面应用程序被认为是粗鲁的.在图形环境中,用户负责.一般来说,应用程序应该保持打开和运行,直到user人决定退出/退出.

Java相关问答推荐

ActivityCompat.请求收件箱自动拒绝权限

在FML中删除关键帧动画

那么比较似乎不是词典学的,尽管doctor 这么说

@ EnableRouting注释在Kotlin项目中不工作

Java应用程序崩溃时试图读取联系人从电话

如何在SystemiccationRetryListenerSupport中获得类级别的spring retryable annotation中指定的标签?

使用Java Streams API比较两个不同的Java集合对象和一个公共属性

参数值[...]与预期类型java.util.Date不匹配

使用@MappdSuperClass扩展ParentClass&Won t继承ParentClass属性

滚动视图&不能在alert 对话框中工作(&Q;&Q;)

GSON期间的Java类型擦除

有没有更快的方法在N个容器中删除重复项?

Jenv-相同的Java版本,但带有前缀

Domino Designer 14中的保存代理添加了重影库

如何在Cosmos DB(Java SDK)中增加默认响应大小

使用SWIG将C++自定义单元类型转换为基本Java类型

在Oracle中调用输出参数在索引处缺少IN或OUT参数的函数

Java集合:NPE,即使没有添加空值

Java中的一个错误';s stdlib SocksSocketImpl?

如果c不为null,Arrays.sort(T[]a,Comparator<;?super T>;c)是否会引发ClassCastException?