【发布时间】:2022-10-16 00:09:26
【问题描述】:
找到解决方案
此代码适用于 fxml.files 和我使用的其余代码来自 Slaws 的回答。
主.java:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
final static ExecutorService threadPool = Executors.newFixedThreadPool(3, r -> {
var t = new Thread(r);
t.setDaemon(true);
return t;
});
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("mainScreen.fxml"));
String css = this.getClass().getResource("style.css").toExternalForm();
Scene scene = new Scene(root);
scene.getStylesheets().add(css);
stage.setMinHeight(800);
stage.setMinWidth(1200);
stage.setScene(scene);
stage.show();
}
@Override
public void stop() {
threadPool.shutdownNow();
}
}
控制器.java
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.text.Font;
import javafx.application.Platform;
public class Controller {
@FXML
private TextArea console;
@FXML
private TextField inputPane;
public void initialize() throws IOException{
wireInputAndOutput(inputPane, console);
startConsoleTask();
}
static void wireInputAndOutput(TextField input, TextArea output) throws IOException {
var inputConsumer = StreamWriter.redirectStandardIn(Main.threadPool);
StreamReader.redirectStandardOut(new BufferedTextAreaAppender(output), Main.threadPool);
input.setOnAction(e -> {
e.consume();
var text = input.textProperty().getValueSafe() + "\n";
output.appendText(text);
inputConsumer.accept(text);
input.clear();
});
}
private void startConsoleTask() {
Main.threadPool.execute(new ConsoleTask(Platform::exit));
}
}
编辑 2
现在的问题是当我将 ConsoleTask 放在 controller.java 中时它没有运行(这是问题 atm。)。 当我复制/粘贴 Slaw 的 main.java 时它起作用了,但我想使用 fxml 文件,所以我尝试了这个,但它不再起作用了。
测试.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="800.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<children>
<TextArea fx:id="console" editable="false" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="20.0" />
</VBox.margin>
</TextArea>
<TextField fx:id="inputPane" prefHeight="40.0" VBox.vgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
ConsoleTask.java:
import java.util.NoSuchElementException;
import java.util.Scanner;
class ConsoleTask implements Runnable {
private final static Scanner scanner = new Scanner(System.in);
private final Runnable onExit;
ConsoleTask(Runnable onExit) {
this.onExit = onExit;
}
@Override
public void run() {
System.out.println("WELCOME TO CONSOLE APP!");
boolean running = true;
while (running && !Thread.interrupted()) {
printOptions();
int choice = readInt("Choose option: ", 1, 20);
switch (choice) {
case 1 -> doCheckIfLeapYear();
case 2 -> doCheckIfPrime();
case 3 -> doPrintStringBackwards();
case 20 -> running = false;
default -> System.out.println("Unknown option!");
}
System.out.println("\nPlease wait...");
wait(6000);
}
onExit.run();
}
private void printOptions() {
System.out.println();
System.out.println("Options");
System.out.println("-------");
System.out.println(" 1) Test Leap Year");
System.out.println(" 2) Test Prime");
System.out.println(" 3) Print String backwards");
System.out.println(" 20) Exit");
System.out.println();
}
private int readInt(String prompt, int min, int max) {
while (true) {
System.out.print(prompt);
try {
int i = Integer.parseInt(scanner.nextLine());
if (i >= min && i <= max) {
return i;
}
} catch (NumberFormatException | NoSuchElementException ignored) {
}
System.out.printf("Please enter an integer between [%,d, %,d]%n", min, max);
}
}
private void doCheckIfLeapYear() {
System.out.println();
int year = readInt("Enter year: ", 0, 1_000_000);
if (year % 4 == 0 || (year % 100 == 0 && year % 400 != 0)) {
System.out.printf("The year %d is a leap year.%n", year);
} else {
System.out.printf("The year %d is NOT a leap year.%n", year);
}
}
private void doCheckIfPrime() {
System.out.println();
int limit = readInt("Enter an Integer: ", 1, Integer.MAX_VALUE);
while (limit <= 1){
System.out.print("Wrong number! the number should be higher or equal to 2: ");
limit = scanner.nextInt();
}
if(isPrime(limit)){
System.out.println(limit+" is a prime number.");
}else{
System.out.println(limit+" is not a prime number.");
}
}
private static boolean isPrime(int n){
if(n <= 1){
return false;
}
for(int i = 2; i <= Math.sqrt(n); i++){
if(n % i == 0){
return false;
}
}
return true;
}
private static void doPrintStringBackwards(){
System.out.println();
System.out.print("\nEnter a word or a sentence: ");
String answer = scanner.nextLine();
//StackOverflow version: (simple)
System.out.println("\n"+new StringBuilder(answer).reverse().toString());
//Lecture version:
/*for (int i = answer.length()-1;i>=0;i--){
System.out.print(answer.charAt(i));
}*/
}
private static void wait(int ms){
try {
Thread.sleep(ms);
}
catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
编辑 1
我想用这个实现的结果是:
使用 gui 中的文本字段作为 java 控制台程序的输入,但我不知道如何实现该结果。
原来的
我是 java/javaFX 的新手,我正在尝试制作一个控制台 gui 应用程序。问题是我找不到将 system.in 重定向到 JavaFX 文本字段的方法。
我已经尝试过这些解决方案,但我没有让它们工作:
部分代码图片:
【问题讨论】:
-
也许我错过了,但是您将标准输入重定向到
TextField的尝试在哪里?那次尝试出了什么问题?请提供minimal reproducible example。 -
@Slaw 它在“问题开始的地方”是什么,但这是我最近的尝试,因为我试图将输入直接发送到方法而不是重定向它,你可能会猜到它不起作用。我也研究了输入流,但我对如何使用它感到困惑。所以现在我希望我能在这个问题上得到帮助,因为我不知道。
-
请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。
-
但是在“问题开始”和“问题结束”之间的代码中,cmets 没有做任何类似于将标准输入重定向到文本字段的操作。您所做的是从文本字段中读取文本并将其转换为 int,然后将其传递给方法调用,这都是完全正常的 JavaFX 工作。
-
但实际上你想在这里做什么?通常,标准输入是用户在键盘上键入控制台/终端的文本流。在这种情况下将标准输入通过管道传输到文本字段是多余的;您也可以让用户在文本字段中输入。如果您将一个程序的输出传送到您的 Java 程序(标准输入的另一个上下文),您可以从标准输入读取值并使用它(文本字段没有明显的需要)。您所说的尝试做的实际用例是什么?