- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个简单的 javafx 应用程序,在 stage.show() 之后,我调用了登录对话框。当我运行测试时,直到登录对话框被填充并手动确认后,它们才会开始工作。出于测试目的,我尝试在舞台上单击一个按钮后显示另一个对话框,并且通过 testFx 操作它没有问题。唯一的问题是初始登录对话框。有没有办法解决此问题,还是我做错了什么?
测试场景:
主程序.java
package cz.mono.monofx;
import cz.mono.monofx.fxml.LoginDialog;
import cz.mono.monofx.fxml.ScreensController;
import java.util.Optional;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.util.Pair;
public class MainApp extends Application {
public static final String SCREEN1 = "scene";
private final String screen1fxml = "/fxml/Scene.fxml";
public static final String SCREEN2 = "scene2";
private final String screen2fxml = "/fxml/Scene2.fxml";
@Override
public void start(Stage stage) throws Exception {
ScreensController mainContainer = new ScreensController();
mainContainer.loadScreen(SCREEN1, screen1fxml);
mainContainer.loadScreen(SCREEN2, screen2fxml);
mainContainer.setScreen(SCREEN1);
Group root = new Group();
root.getChildren().addAll(mainContainer);
Scene scene = new Scene(root);
scene.getStylesheets().add("/styles/Styles.css");
stage.setTitle("Aplipikacka");
stage.setScene(scene);
stage.show();
LoginDialog login = new LoginDialog();
Optional <Pair<String, String>> result = login.getResult();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
TestFxBase.java
package cz.mono.monofx.test;
import cz.mono.monofx.MainApp;
import java.util.concurrent.TimeoutException;
import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;
import org.junit.After;
import org.junit.Before;
import org.testfx.api.FxToolkit;
import org.testfx.framework.junit.ApplicationTest;
public class TestFxBase extends ApplicationTest {
@Before
public void setUpClass() throws Exception {
ApplicationTest.launch(MainApp.class);
}
@After
public void afterEachTest() throws TimeoutException {
FxToolkit.hideStage();
release(new KeyCode[]{});
release(new MouseButton[]{});
}
//Helper method to retrieve javafx components
public <T extends Node> T find(String query) {
return (T) lookup(query).queryAll().iterator().next();
}
@Override
public void start(Stage stage) {
stage.show();
}
}
简单测试.java
package cz.mono.monofx.test;
import static javafx.scene.input.KeyCode.TAB;
import org.junit.Test;
public class ValidationTest extends TestFxBase {
@Test
public void verifyLogin() {
clickOn("#dialogButton");
sleep(1000);
type(TAB);
sleep(1000);
type(TAB);
sleep(1000);
}
}
登录对话框.java
package cz.mono.monofx.fxml;
import java.util.Optional;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.util.Pair;
public class LoginDialog {
private Dialog<Pair<String, String>> dialog;
private TextField username;
private PasswordField password;
private Optional<Pair<String, String>> result;
public LoginDialog() {
dialog = new Dialog<>();
dialog.setTitle("Login");
dialog.setHeaderText("Provide correct login informations.");
username = new TextField();
username.setPrefSize(150, 30);
username.setPromptText("username");
username.setId("username");
//Request focus on username by default
Platform.runLater(()-> username.requestFocus());
password = new PasswordField();
password.setPrefSize(150, 30);
password.setPromptText("password");
password.setId("password");
ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
loginButton.setId("loginButton");
BooleanBinding bb = Bindings.createBooleanBinding(()-> username.getText().isEmpty() || password.getText().isEmpty(), username.textProperty(), password.textProperty());
loginButton.disableProperty().bind(bb);
GridPane grid = new GridPane();
grid.setVgap(10);
grid.setHgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
grid.add(new Label("Username: "), 0, 0);
grid.add(username, 0, 1);
grid.add(new Label("Password"), 1, 0);
grid.add(password, 1, 1);
dialog.getDialogPane().setContent(grid);
// Convert the result to a username-password-pair when the login button is clicked.
dialog.setResultConverter(dialogButton -> {
if (dialogButton == loginButtonType) {
return new Pair<>(username.getText(), password.getText());
}
return null;
});
result = dialog.showAndWait();
result.ifPresent(usernamePassword -> {
System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
});
if (!result.isPresent()) {
System.exit(0);
};
}
/**
* @return the result
*/
public Optional<Pair<String, String>> getResult() {
return result;
}
}
最佳答案
让我展示一种可行的解决方案。我在我的项目中成功地使用了它。
主要思想是让 start
应用程序方法尽可能少:
public class MainApp extends Application {
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new MainPane(stage)));
stage.show();
}
所有的逻辑都移到了MainPane
类:
class MainPane extends BorderPane {
MainPane(final Stage stage) {
stage.setTitle("Aplipikacka");
// open the login dialog only when the stage is opened too.
stage.setOnShown(event -> Platform.runLater(this::showLoginDialog));
}
private void showLoginDialog() {
LoginDialog login = new LoginDialog();
Optional<Pair<String, String>> result = login.getResult();
// TODO finish here
}
}
因为 textFx 提供了自己的 stage
,您应该在其中手动注入(inject)场景,然后执行下一步:
public class TestFxBase extends ApplicationTest {
@Override
public void start(Stage stage) {
stage.setScene(new Scene(new MainPane(stage)));
stage.show();
}
}
最后改进一下测试:
public class MainAppFIT extends TestFxBase {
@Test
public void verifyLogin() {
// given started application and opened login dialog
sleep(500);
// when
write("HelloWorld");
type(TAB);
write("password");
clickOn("#loginButton");
// then
// TODO finish here with verification of actual result
}
}
因此,我能够看到 textfx 机器人如何按照测试步骤中的定义点击/键入。
顺便说一句,`MainAppFIT' - FIT 表示功能集成测试。
关于java - TestFx - 无法访问登录对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45458068/
我通过 spring ioc 编写了一些 Rest 应用程序。但我无法解决这个问题。这是我的异常(exception): org.springframework.beans.factory.BeanC
我对 TestNG、Spring 框架等完全陌生,我正在尝试使用注释 @Value通过 @Configuration 访问配置文件注释。 我在这里想要实现的目标是让控制台从配置文件中写出“hi”,通过
为此工作了几个小时。我完全被难住了。 这是 CS113 的实验室。 如果用户在程序(二进制计算器)结束时选择继续,我们需要使用 goto 语句来到达程序的顶部。 但是,我们还需要释放所有分配的内存。
我正在尝试使用 ffmpeg 库构建一个小的 C 程序。但是我什至无法使用 avformat_open_input() 打开音频文件设置检查错误代码的函数后,我得到以下输出: Error code:
使用 Spring Initializer 创建一个简单的 Spring boot。我只在可用选项下选择 DevTools。 创建项目后,无需对其进行任何更改,即可正常运行程序。 现在,当我尝试在项目
所以我只是在 Mac OS X 中通过 brew 安装了 qt。但是它无法链接它。当我尝试运行 brew link qt 或 brew link --overwrite qt 我得到以下信息: ton
我在提交和 pull 时遇到了问题:在提交的 IDE 中,我看到: warning not all local changes may be shown due to an error: unable
我跑 man gcc | grep "-L" 我明白了 Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more inf
我有一段代码,旨在接收任何 URL 并将其从网络上撕下来。到目前为止,它运行良好,直到有人给了它这个 URL: http://www.aspensurgical.com/static/images/a
在过去的 5 个小时里,我一直在尝试在我的服务器上设置 WireGuard,但在完成所有设置后,我无法 ping IP 或解析域。 下面是服务器配置 [Interface] Address = 10.
我正在尝试在 GitLab 中 fork 我的一个私有(private)项目,但是当我按下 fork 按钮时,我会收到以下信息: No available namespaces to fork the
我这里遇到了一些问题。我是 node.js 和 Rest API 的新手,但我正在尝试自学。我制作了 REST API,使用 MongoDB 与我的数据库进行通信,我使用 Postman 来测试我的路
下面的代码在控制台中给出以下消息: Uncaught DOMException: Failed to execute 'appendChild' on 'Node': The new child el
我正在尝试调用一个新端点来显示数据,我意识到在上一组有效的数据中,它在数据周围用一对额外的“[]”括号进行控制台,我认为这就是问题是,而新端点不会以我使用数据的方式产生它! 这是 NgFor 失败的原
我正在尝试将我的 Symfony2 应用程序部署到我的 Azure Web 应用程序,但遇到了一些麻烦。 推送到远程时,我在终端中收到以下消息 remote: Updating branch 'mas
Minikube已启动并正在运行,没有任何错误,但是我无法 curl IP。我在这里遵循:https://docs.traefik.io/user-guide/kubernetes/,似乎没有提到关闭
每当我尝试docker组成任何项目时,都会出现以下错误。 我尝试过有和没有sudo 我在这台机器上只有这个问题。我可以在Mac和Amazon WorkSpace上运行相同的容器。 (myslabs)
我正在尝试 pip install stanza 并收到此消息: ERROR: No matching distribution found for torch>=1.3.0 (from stanza
DNS 解析看起来不错,但我无法 ping 我的服务。可能是什么原因? 来自集群中的另一个 Pod: $ ping backend PING backend.default.svc.cluster.l
我正在使用Hibernate 4 + Spring MVC 4当我开始 Apache Tomcat Server 8我收到此错误: Error creating bean with name 'wel
我是一名优秀的程序员,十分优秀!