JavaFX System.out.println in TextArea

Tooltime

Mitglied
In einem Spiel, welches zur Zeit auf der Konsole läuft, möchte ich alle System.out.println in die GUI umleiten. Ich habe dafür eine TextArea erstellt und eine Methode "void print text (String text)" sowie einen PrintStream erstellt.

Hier der Quelltext für die GUI:

Java:
import java.io.PrintStream;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class Gui extends Application {

    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 800);

        // Buttons:
        Button n = new Button("Norden");
        n.setLayoutX(600);
        n.setLayoutY(450); // Position des Buttons
        root.getChildren().add(n);
        Button o = new Button("Osten");
        o.setLayoutX(660);
        o.setLayoutY(500);
        root.getChildren().add(o);
        Button s = new Button("Süden");
        s.setLayoutX(600);
        s.setLayoutY(550);
        root.getChildren().add(s);
        Button w = new Button("Westen");
        w.setLayoutX(540);
        w.setLayoutY(500);
        root.getChildren().add(w);
        Label labelText = new Label("Code hier eingeben"); // ein Label wurde
                                                            // erzeugt für den
                                                            // TextField
        labelText.setLayoutX(10);
        labelText.setLayoutY(475);
        root.getChildren().add(labelText); // setze die Position der label ein
        final TextArea textOut = new TextArea();
        textOut.setPrefSize(300, 100);
        textOut.setLayoutX(50);
        textOut.setLayoutY(500);
        root.getChildren().add(textOut);

        Image img1 = new Image(Game.class.getResource("Schulflur 1.jpg")
                .toExternalForm()); // erzeugt ein neues Bild in gleiches
                                    // verzeichnis wie die Klasse Game
        Image img2 = new Image(Game.class.getResource("Spielplan.png")
                .toExternalForm());
        ImageView imgV1 = new ImageView(img1); // Node für das dimensionierung
                                                // des Bildes würde erzeugt
        ImageView imgV2 = new ImageView(img2);
        imgV1.setLayoutX(0);
        imgV1.setLayoutY(0);
        imgV1.setFitWidth(400);
        imgV1.setFitHeight(400); // setze ein die Position des Bildes und seine
                                    // Höhe und Breite
        imgV2.setLayoutX(425);
        imgV2.setLayoutY(0);
        imgV2.setFitWidth(375);
        imgV2.setFitHeight(400);
        root.getChildren().add(imgV1); // Bild auf des Parent Group hinzufügen
                                        // um das Bild zu zeigen
        root.getChildren().add(imgV2);
     
     
        PrintStream stream = new PrintStream(System.out) {
         
            @Override
            public void print(String text) {
                textOut.setText(text + "\n"); 
                }
        };
        System.setOut(stream);
     
     


        stage.setTitle("World of Zuul"); // Fenstertitel
        stage.setScene(scene);
        stage.show();
    }

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

        Game game = new Game();
        game.play();
     
     

    }

Bisher hab ich im Internet nur Beispiele für "JTextArea" gefunden. Dafür müsste ich aber die gesamte GUI umschreiben + hab ich noch nie mit "JFrame" gearbeitet.

Meine Frage: Ist der Ansatz für eine Ausgabe in die GUI soweit richtig?
Was muss ich jetzt noch machen, damit in allen anderen Klasse die syous in die TextArea angezeigt werden?
 
Zuletzt bearbeitet von einem Moderator:
Dein Ansatz ist richtig, folgendes Programm benutzt quasi deine Methode und es funktioniert, vielleicht liegt der Fehler an anderer Stelle.

Java:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class MainApp extends Application {

    private TextArea textArea = new TextArea();

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

    @Override
    public void start(Stage stage) throws Exception {
        initStage(stage);
    
        System.out.println("Hello World in Console");
        PrintToTextArea.create(textArea);
        System.out.println("Hello World in TextArea");
    }

    public void initStage(Stage stage) {
        HBox hbox = new HBox();
        hbox.getChildren().add(textArea);
        Scene scene = new Scene(hbox);
        stage.setScene(scene);
        stage.show();
    }
}

Java:
import java.io.PrintStream;

import javafx.scene.control.TextArea;

public abstract class PrintToTextArea {

    public static void create(TextArea textarea) {
        PrintStream stream = new PrintStream(System.out) {
            @Override
            public void print(String text) {
                textarea.setText(text + "\n");
            }
        };
        System.setOut(stream);
    }
}

P.S: Dein Ansatz gefällt mir, nicht alles völlig neu schreiben zu müssen, sondern zu versuchen das Alte irgendwie zu nutzten 🙂
 
Zuletzt bearbeitet:
Danke für deine Antwort.
Hab gestern und heute getüftelt. Es hilft mir aber nichts. Sobald ich jetzt eine dritte Klasse hinzuziehe und die Methode aufrufen will, wird immer eine textArea verlangt.

Da ich aber nicht aufgeben will, hab ich mir noch was überlegt, und zwar diesmal ohne Stream:

Java:
public abstract class PrintToTextArea extends MainApp {
    public void print(String text) {
        textOut.setText(text + "\n");
    }
}

Java:
public class Test {

    private PrintToTextArea printToTextArea;

    public void Welcome() {
        System.out.println("Hallo Console");
        printToTextArea.print("Hallo GUI");
    }
}

Java:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;

public class MainApp extends Application {
    public TextArea textOut = new TextArea();

    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 800);

        textOut.setPrefSize(300, 100);
        textOut.setLayoutX(50);
        textOut.setLayoutY(500);
        root.getChildren().add(textOut);
        stage.setTitle("World of Zuul"); // Fenstertitel
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);   
        Test test = new Test();
        test.Welcome();
    }
}

Bei dem Aufruf von der Methode kommt eine Fehlermeldung, mit der ich nichts anfangen kann:

Code:
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.NullPointerException
    at Test.Welcome(Test.java:9)
    at MainApp.main(MainApp.java:32)
    ... 11 more
Exception running application MainApp

Wenn diese Ausgabe funktioniert, bin ich einen großen Schritt weiter
 
Zuletzt bearbeitet von einem Moderator:
Moin,

habe es jetzt nur schnell überfliegen können, aber PrintToTextArea ist eine eigene KLASSE, also solltest davon auch ein Objekt erzeugen und nicht nur eine Variable !!

Java:
// also statt
private PrintToTextArea printToTextArea;

// sowas
PrintToTextArea printToTextArea = new PrintToTextArea();

Gruß Klaus
 
Hab gestern und heute getüftelt. Es hilft mir aber nichts. Sobald ich jetzt eine dritte Klasse hinzuziehe und die Methode aufrufen will, wird immer eine textArea verlangt.
Also ich hatte das eigentlich auch getestet, und meine Meldungen wurden alle nach dem static Aufruf der PrintToTextArea Klasse ausschließlich in das hinterlegte TextArea gepostet. Ich schau mir das vielleicht später nochmal an 🙂 Bis dahin, frohes schaffen ^^
 
🙁 Klappt bis jetzt immer noch nicht. Ich habe mal ein neues Objekt erzeugt, also

Code:
PrintToTextArea printToTextArea = new PrintToTextArea();

Jetzt kommt zwar keine Fehlermeldung mehr, aber die TextArea ist immer noch leer 🙁

Aber warum macht der Aufruf
Code:
printToTextArea.print("Hallo GUI");
einfach nichts?
 
Wieso extended dein PrintToTextArea eigentlich von MainApp?
Guck dir nochmal mein Beispiel an, was dort abstract und was static und was wo wie initialisiert wird.
Dann müsstest du feststellen das du nur eine TextArea brauchst und auch niemals dein print Aufruf.

Wieso deine Zeile nicht funktioniert muss man anhand des kompletten Codes analysieren.
 
Ich habs jetzt mit deinem Code nochmal probiert.
Also, neben deinen beiden Klassen nehme ich jetzt eine dritte Klasse hinzu.
In dieser dritten Klasse definiere ich irgendeine Methode.
In dieser Methode erfolgt ein Sysou. Jetzt möchte ich, dass diese Ausgabe in die Area erfolgen soll. Also rufe ich die definierte Methode auf
Code:
PrintToTextArea.create();
Jetzt wird nur noch verlangt, dass als Argument eine TextArea eingesetzt werden soll. Also nehm ich ja die TextArea, welche in der Klasse MainApp erstellt wurde. Auf die erstellte TextArea erhalte ich aber kein Zugriff. Objektaufruf funktioniert nicht. Ich kann konnte nur auf die Area zugreifen, sobald ich meine dritte erstellte Klasse von der Klasse MainApp erben lasse. Mein Aufruf erscheint aber nicht auf der Area.

Da erben für mein Projekt keine sinnvolle Lösung ist, bleibt ja nur noch
Code:
PrintToTextArea.create(new TextArea("Hallo GUI"))
Hier ergeben sich wiederum zwei Probleme:
1. Ich hätte am Ende dutzende von TextAreas.
2. Ich müsste diese TextArea wieder in die GUI einfügen...selbst dass klappte nicht mehr.

Der Sinn von meiner Idee war, dass ich durch diese Methode alle Sysous nur umschreiben muss, also statt "System.out.println()" nur "printToTextArea.print".

Ich kann mir vorstellen, dass ich bei den jetzigen Überlegungen einiges falsch verstanden habe.
Sagt mir bitte, wo der Denkfehler ist.
 
Der statische Aufruf PrintToTextArea.create (...); muss nur ein einziges mal erfolgen. Ganz am Anfang deines Programm, ab da wird dann dein Standardoutput in das übergebene TextArea umgeleitet. 🙂

Vllt sollte man die Klasse umnennen in StandartOutputToTextArea 😉
 
Also im Prinzip, alle Methodenaufrufe unter PrintToTextArea.create(...) setzen (hast du aber bestimmt nicht gemeint 😎)? Ok, dabei wird mein Text jetzt übergeben, jdeoch die zuvor definierten Methoden überschrieben, sprich, wenn ich zwei Methoden habe, wird nur noch der Aufruf von der zweiten Methode angezeigt.
Edit: Statt textarea.setText() muss textarea.appendText() folgen
 
Schön, jetzt kalppt es wenigstens bei dem kleinen Programm.
Bei meinem Hauptprogramm öffnet sich jetzt das GUI Fenster mit einem leeren Inhalt. Am Fensterrand steht "Keine Rückmeldung". Ich bekomm jetzt Schnappatmung. 😕
Danke für eure Hilfe, hatte ja wenigstens einen Teilerfolg. 🙂
 
Habe eine Lösung gefunden und wollte die einfach mal mitteilen:

Java:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;

public class MainApp extends Application {
    public TextArea textOut = new TextArea();

    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 800, 800);

        textOut.setPrefSize(300, 100);
        textOut.setLayoutX(50);
        textOut.setLayoutY(500);
        root.getChildren().add(textOut);
        stage.setTitle("World of Zuul"); // Fenstertitel
        stage.setScene(scene);
        Test test = new Test(this);
        test.welcome();
        stage.show();
    }
    public void print(String text){
        textOut.setText(text);
    }

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


Java:
public class Test {
private MainApp ma;

public Test(MainApp ma){
    this.ma=ma;
}

    public void welcome() {
        System.out.println("Hallo Console");
        ma.print("Hallo GUI");
    }
}
 
Doch, genau so wollte ich es.
Das Hauptprogramm stürzt zwar immer noch ab. Dies hängt aber wahrscheinlich damit zusammen, dass es dort einen InputStream für Eingaben gibt. Ich muss also noch irgendwie die Eingaben, welche in der Konsole getätigt wurden, in eine andere TextArea umleiten.
Jetzt muss ich mich ersteinmal in der API einlesen, was ein BuffReader ist und was ein StringTonkenizer so macht 🙂.
 

Zurück
Oben