在TextField中以编程方式fireEvent - JavaFX

时间:2016-03-17 18:39:15

标签: java javafx

假设有一个TextField

TextField tf = new TextField();

我想模拟用户按一个键。

KeyEvent ke = new KeyEvent(KeyEvent.KEY_RELEASED, 
    KeyCode.A.toString(), KeyCode.A.toString(), 
    KeyCode.A, false, false, false, false);
tf.fireEvent(ke);

如果我检查tf的文本内容,我会看到这个状态为true

tf.getText() == ""

我的KeyEvent发生了什么,为什么文本不等于“a”?我用KEY_RELEASED,KEY_PRESSED和KEY_TYPED

尝试过这个

包含示例:

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;

import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

import java.util.concurrent.CountDownLatch;

import javax.swing.SwingUtilities;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class TextFieldExample {

    @Rule public JavaFXThreadingRule javafxRule = new JavaFXThreadingRule();
    @Test
    public void onlyAcceptValidInputs() {
        TextField tf = new TextField();
        KeyEvent ke = new KeyEvent(KeyEvent.KEY_RELEASED, 
                KeyCode.A.toString(), KeyCode.A.toString(), 
                KeyCode.A, false, false, false, false);
        tf.fireEvent(ke);
        Assert.assertEquals("A", tf.getText());
    }
}

class JavaFXThreadingRule implements TestRule {    
    /**
     * Flag for setting up the JavaFX, we only need to do this once for all tests.
     */
    private static boolean jfxIsSetup;

    @Override
    public Statement apply(Statement statement, Description description) {

        return new OnJFXThreadStatement(statement);
    }

    private static class OnJFXThreadStatement extends Statement {

        private final Statement statement;

        private OnJFXThreadStatement(Statement aStatement) {
            statement = aStatement;
        }

        private Throwable rethrownException = null;

        @Override
        public void evaluate() throws Throwable {

            if(!jfxIsSetup) {
                setupJavaFX();

                jfxIsSetup = true;
            }

            final CountDownLatch countDownLatch = new CountDownLatch(1);

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        statement.evaluate();
                    } catch (Throwable e) {
                        rethrownException = e;
                    }
                    countDownLatch.countDown();
                }});

            countDownLatch.await();

            // if an exception was thrown by the statement during evaluation,
            // then re-throw it to fail the test
            if(rethrownException != null) {
                throw rethrownException;
            }
        }

        protected void setupJavaFX() throws InterruptedException {
            final CountDownLatch latch = new CountDownLatch(1);            
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // initializes JavaFX environment
                    new JFXPanel();                    
                    latch.countDown();
                }
            });

            latch.await();
        }

    }
}

1 个答案:

答案 0 :(得分:2)

似乎文本字段正在侦听KEY_TYPED个事件。请注意,对于KEY_TYPED个事件,text应为空字符串,code应为KeyCode.UNDEFINED

另请注意,在测试用例中,文本字段永远不会添加到实时场景中。因此,它不会安装其皮肤,其中包含实际处理事件的逻辑。所以你需要通过调用setSkin(...)强制安装皮肤,传入 protected 方法createDefaultSkin()的结果:

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TextFieldFireEvent extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextField tf = new TextField() {
            {
                setSkin(createDefaultSkin());
            }
        };

        Button button = new Button("A");
        button.setOnAction(e -> {
            KeyEvent ke = new KeyEvent(KeyEvent.KEY_TYPED, 
                    "a", "", 
                    KeyCode.UNDEFINED, false, false, false, false);
                tf.fireEvent(ke);
                System.out.println(tf.getText());
        });
        VBox root =new VBox(10, /*tf,*/ button);

        root.setAlignment(Pos.CENTER);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

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