我正在JavaFX中编写一个应用程序,并希望创建一个等待用户在我的TextField
中输入文本并在返回(继续)之前点击Enter
的函数。
private void setupEventHandlers() {
inputWindow.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent e) {
if (e.getCode().equals(KeyCode.ENTER)) {
inputWindow.clear();
}
}
});
}
当用户点击Enter键时,我清除了TextField
中的文字。
有什么想法吗?
编辑:我会澄清我正在寻找的内容:
private void getInput() {
do {
waitForEventToFire();
}
while (!eventFired);
}
显然这只是伪代码,但这正是我正在寻找的。 p>
答案 0 :(得分:6)
示例解决方案
也许您要做的是显示一个提示对话框,并在继续之前使用showAndWait等待来自提示对话框的响应。与JavaFX2: Can I pause a background Task / Service?
类似可能您的情况比后台任务服务更简单(除非您涉及长时间运行的任务),您可以在JavaFX应用程序线程上执行所有操作。我创建了一个简单的示例解决方案,它只运行JavaFX应用程序线程上的所有内容
以下是示例程序的输出:
每次遇到丢失的数据时,都会显示一个提示对话框,等待用户输入以填写缺失的数据(用户提供的响应在上面的屏幕截图中以绿色突出显示)。
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
public class MissingDataDemo extends Application {
private static final String[] SAMPLE_TEXT =
"Lorem ipsum MISSING dolor sit amet MISSING consectetur adipisicing elit sed do eiusmod tempor incididunt MISSING ut labore et dolore magna aliqua"
.split(" ");
@Override public void start(Stage primaryStage) {
VBox textContainer = new VBox(10);
textContainer.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
primaryStage.setScene(new Scene(textContainer, 300, 600));
primaryStage.show();
TextLoader textLoader = new TextLoader(SAMPLE_TEXT, textContainer);
textLoader.loadText();
}
public static void main(String[] args) { launch(args); }
}
class TextLoader {
private final String[] lines;
private final Pane container;
TextLoader(final String[] lines, final Pane container) {
this.lines = lines;
this.container = container;
}
public void loadText() {
for (String nextText: lines) {
final Label nextLabel = new Label();
if ("MISSING".equals(nextText)) {
nextLabel.setStyle("-fx-background-color: palegreen;");
MissingTextPrompt prompt = new MissingTextPrompt(
container.getScene().getWindow()
);
nextText = prompt.getResult();
}
nextLabel.setText(nextText);
container.getChildren().add(nextLabel);
}
}
class MissingTextPrompt {
private final String result;
MissingTextPrompt(Window owner) {
final Stage dialog = new Stage();
dialog.setTitle("Enter Missing Text");
dialog.initOwner(owner);
dialog.initStyle(StageStyle.UTILITY);
dialog.initModality(Modality.WINDOW_MODAL);
dialog.setX(owner.getX() + owner.getWidth());
dialog.setY(owner.getY());
final TextField textField = new TextField();
final Button submitButton = new Button("Submit");
submitButton.setDefaultButton(true);
submitButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent t) {
dialog.close();
}
});
textField.setMinHeight(TextField.USE_PREF_SIZE);
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER_RIGHT);
layout.setStyle("-fx-background-color: azure; -fx-padding: 10;");
layout.getChildren().setAll(
textField,
submitButton
);
dialog.setScene(new Scene(layout));
dialog.showAndWait();
result = textField.getText();
}
private String getResult() {
return result;
}
}
}
现有提示对话库
ControlsFX library中有一个预先写好的提示对话框,可以为您处理提示对话框。
澄清事件处理程序处理和忙碌等待
你想:
等待用户在我的TextField中输入文本并点击“输入”的函数。
根据定义,这就是EventHandler。 当发生此处理程序的类型的特定事件发生时,“调用EventHandler”。
当事件发生时,您的事件处理程序将触发,您可以在事件处理程序中执行任何操作 - 您不需要并且永远不应该该事件的忙等待循环。
创建TextField操作事件处理程序
不要像在问题中那样在窗口上放置事件处理程序,最好使用textField.setOnAction在文本字段上使用特定的操作事件处理程序:
textField.setOnAction(
new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
// enter has been pressed in the text field.
// take whatever action has been required here.
}
);
如果将文本字段放在带有为对话框设置的默认按钮的对话框中,则不需要为文本字段设置事件处理程序,因为对话框的默认按钮将拾取并适当地处理输入键事件。
答案 1 :(得分:0)
我本来想使用ControlsFx,但我无法升级到Java 1.8运行时,因此必须从头开始构建对话框组件。这就是我想出的:
private static Response buttonSelected = Response.CANCEL;
/**
* Creates a traditional modal dialog box
*
* @param owner the calling Stage that is initiating the dialog.
* @param windowTitle text that will be displayed in the titlebar
* @param greeting text next to icon that provides generally what to do (i.e. "Please enter the data below")
* @param labelText label text for the input box (i.e. "Number of widgets:")
* @return If user clicks OK, the text entered by the user; otherwise if cancel, NULL.
*/
public static String prompt(final Stage owner, final String windowTitle, final String greeting, final String labelText) {
//overall layout pane
BorderPane root = new BorderPane();
root.setPadding(PADDING);
Scene scene = new Scene(root);
final Dialog dial = new Dialog(windowTitle, owner, scene, MessageType.CONFIRM);
final Button okButton = new Button("OK");
okButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
dial.close();
buttonSelected = Response.YES;
}
});
Button cancelButton = new Button("Cancel");
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
dial.close();
buttonSelected = Response.NO;
}
});
HBox headerGreeting = new HBox();
headerGreeting.setSpacing(SPACING_SMALL);
Text messageText = new Text(greeting);
messageText.setFont(new Font(messageText.getFont().getName(), 14));
headerGreeting.getChildren().addAll(icon, messageText);
root.setTop(headerGreeting);
//setup input controls
HBox textHBox = new HBox(10);
TextField input = new TextField();
Label label = new Label();
label.setText(labelText);
label.setLabelFor(input);
textHBox.getChildren().addAll(label, input);
//create buttons
HBox buttons = new HBox();
buttons.setAlignment(Pos.CENTER);
buttons.setSpacing(SPACING);
buttons.getChildren().addAll(okButton, cancelButton);
root.setCenter(buttons);
//put controls and buttons in a vertical container, add to root component
VBox container = new VBox(20);
container.setPadding(new Insets(15, 12, 15, 12));
container.getChildren().addAll(textHBox, buttons);
root.setCenter(container);
//handle enter key
root.setOnKeyReleased(new EventHandler<KeyEvent>() {
final KeyCombination combo = new KeyCodeCombination(KeyCode.ENTER);
public void handle(KeyEvent t) {
if (combo.match(t)) {
okButton.fire();
}
}
});
input.requestFocus(); //set focus to the input box.
dial.showDialog();
if (buttonSelected.equals(Response.YES)) {
return input.getText();
}
else { //cancel
return null;
}
}
我的测试工具看起来像这样,所以你可以很快地运行上面的代码:
import javafx.application.Application;
import javafx.stage.Stage;
public class FXOptionsPaneTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
String response = FXOptionsPane.prompt(primaryStage, "Create a new Study...", "Please enter the below information.", "Study Name:");
System.out.println(response);
}
public static void main(String[] args) {
launch(args);
}
}