Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 21

Thema: Java Console in SWT Text Widget

  1. #1
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12

    Java Console in SWT Text Widget

    Hallo,
    ich brauche eine SWT Klasse, die nicht blockierend ist (Grund folgt).
    Der Output von System.out und System.err soll in ein Text Widget in dieser Klasse angezeigt werden. Die Klasse darf nicht blockieren, weil das Hauptprogramm weiterlaufen und die Outputs per SWT ausgeben soll.

    D.h. mit

    OutputWindow owindow = new OutputWindow(); soll eine SWT Shell mit Text Widget erzeugt werden, was dann den Output anzeigt.

    Mit googlen habe ich bisher keine Lösungen finden können.
    http://www.comweb.nl/java/Console/Console.html benutzt Swing, aber ich habe es nicht auf SWT ändern können. Kennt jemand eine schöne Lösung mit SWT Widgets?

    Wenn ich

    Display display = new Display ();
    Shell shell = new Shell(display);
    shell.open ();
    while (!shell.isDisposed ()) {
    if (!display.readAndDispatch ()) display.sleep ();
    }
    display.dispose ();

    in einen Thread packe (wegen nicht blockieren der Shell), funktioniert es auch nicht.

    Vielleicht hat jemand einen kleinen Hinweis.

    Danke
    Jens

  2. #2
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Also du willst ein externes Programm ausführen und dessen Output in SWT ausgeben, hab ich das richtig verstanden?

    In dem Fall Packst du einfach alles was das externe Programm betrifft in einen eigenen Thread. Wenn du aus diesem Thread dann etwas an der Gui ändern musst (z.B. Text im Widget anfügen) dann benutzt du dazu Display.asyncExec() bzw. Display.syncExec(), aufgerufen von deinem Thread aus.
    Deren Funktion hab ich schon ein paar mal anderen Leuten hier im Forum zu erklären versucht.

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  3. #3
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    also, ich habe z.b. eine main Funktion


    public static void main()
    {
    ...hier läuft viel ab
    ... noch mehr Code

    OutputWindow owindow = new OutputWindow();

    System.out.println("Beispielausgabe"); <- erscheint im OutputWindow
    .. mehr Code
    }


    es soll quasi die gesamte Standardausgabe umgelenkt werden.

  4. #4
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Also die Ausgabe deines eigenen Programms? Wieso benutzt du dann System.out.println und schreibst das Zeugs nicht einfach direkt in das outputwindow? Was genau darf nicht blockieren?

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  5. #5
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Jetzt habe ich es gefunden. Ich denke, ich habe schon mal so etwas geschrieben, was du suchst.

    Es ist ein sehr einfacher StatusMessenger, aus meinem SWTUtils-Projekt. Es ist nicht sehr ausgereift, und nicht gut Konfigurierbar. Aber mit wenigen Anpassungen im Code, läßt sich einiges daraus machen. Er verwendet die von pischmae genannte Methode asyncExec().

    Code:
    package at.sterzl.swt;
    
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Label;
    
    public class StatusMessenger extends Thread {
    
    	private static String MESSAGE = "";
    
    	private static Label _statusLabel = null;
    
    	private static StatusMessenger _messenger = null;
    
    	private static int _counter = 0;
    
    	private static Display _display = null;
    
    	private static boolean messageChanged = false;
    
    	private StatusMessenger() {
    		super();
    	}
    
    	public static void instantiate(Label statusLabel, Display display) {
    		setLabel(statusLabel);
    		setDisplay(display);
    	}
    
    	private static void setLabel(Label statusLabel) {
    		_statusLabel = statusLabel;
    	}
    
    	private static void setDisplay(Display display) {
    		_display = display;
    	}
    
    	public static StatusMessenger getInstance() {
    		if (_messenger == null) {
    			_messenger = new StatusMessenger();
    		}
    		return _messenger;
    	}
    
    	public static void setMessage(String msg) {
    		if (_statusLabel != null) {
    			MESSAGE = msg;
    		}
    		_counter = 0;
    		messageChanged = true;
    	}
    
    	public void run() {
    		while (true) {
    			if (messageChanged) {
    				if (!_display.isDisposed()) {
    					_display.asyncExec(new TextSetter(MESSAGE));
    					messageChanged = false;
    				}
    			}
    			if (_counter == 10) {
    				setMessage("");
    			}
    			try {
    				Thread.sleep(500);
    			} catch (InterruptedException ex) {
    				setMessage(ex.getMessage());
    			}
    			_counter++;
    		}
    	}
    
    	private class TextSetter extends Thread {
    
    		private String message = "";
    
    		TextSetter(String msg) {
    			message = msg;
    		}
    
    		public void run() {
    			if (!_statusLabel.isDisposed()) {
    				synchronized (_statusLabel) {
    					_statusLabel.setText(message);
    				}
    			}
    		}
    	}
    }
    Du kannst den StatusMessenger in ein Label einbinden mit folgendem Code:

    Code:
    StatusMessenger.instantiate(_statusLabel, SWTUtil.getDisplay());
    _statusMessenger = StatusMessenger.getInstance();
    _statusMessenger.setDaemon(true);
    _statusMessenger.start();
    _statusLabel ist org.eclipse.swt.widgets.Label;
    Dazu musst du noch das display übergeben.

    Statt eines Labels kannst du jedes andere Widget nehmen und statt der Methode setText kannst du auch Text appenden. Dann musst du allerdings schauen, dass der Text nicht wieder verschwindet nach 5 Sekunden.

    Ich hab unter dem Link unten mein Projekt aus Eclipse in ein Zip exportiert.
    Da siehst du das mal in Action, wenn du die Klasse GUIMain startest.


    http://sterzl.dyndns.org/SWTUtil.zip


    Es steht dir frei den Code zu verändern.

    mfg, Christian
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  6. #6
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    @peschmae
    Das Programm habe ich nicht selbst geschrieben. Ich soll es nur erweitern. Alle Ausgaben kommen bisher per System.out.println() auf die Console. Zusätzlich soll eine grafische Ausgabe möglich sein.

    Die Oberfläche soll nicht blockieren, weil das eigentliche Programm ja weiterarbeiten soll.

    @Waxolunist
    Vielen Dank für deine Antwort. Ich werde es morgen testen.

    gruß
    jens

  7. #7
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12

    erfolglos

    Hallo,
    ich habe es bisher noch nicht hinbekommen. Hier etwas konkreten Code um es etwas klarer zu machen.

    Hauptthread:

    public class Programm {
    public static void main(String[] args) {
    .....
    .....
    new Thread(new OutputWindow()).start();
    ...
    ...
    System.out.println("Dieser Text soll ins OutputFenster kommen!");
    ...
    }
    }

    OutputWindow:

    import java.io.PrintStream;

    import org.eclipse.swt.SWT;
    import org.eclipse.swt.graphics.Point;
    import org.eclipse.swt.layout.FillLayout;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Text;

    public class OutputWindow implements Runnable {
    private Display display;

    private Shell shell;

    private Text textArea;

    public void run() {
    display = new Display();
    shell = new Shell(display, SWT.DIALOG_TRIM);
    // System.out.println("Constructor");
    shell.setText("U2Q Output");
    shell.setSize(new Point(872, 486));
    shell.setLayout(new FillLayout());
    textArea = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
    shell.open();

    PrintStream backupSystemOutStream = System.out;
    System.setOut(new PrintStream(backupSystemOutStream) {
    public void println(final String s) {
    display.asyncExec(new Runnable() {
    public void run() {
    textArea.append(s);
    textArea.append("\n");
    }
    });
    }
    });

    while (!shell.isDisposed()) {
    if (!display.readAndDispatch())
    display.sleep();
    }
    display.dispose();
    }
    }


    Was kann ich machen ? Gibt es eine ähnliche Methode ?
    gruß
    Jens

  8. #8
    Registrierter Benutzer
    Registriert seit
    16.09.2001
    Beiträge
    1.182
    was genau machts denn (nicht) ?
    wie testest du ob es funktioniert oder nicht?

  9. #9
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    Alle System.out.println("") sollen in der Textarea erscheinen. Ich möchte die normale Java Console in dem SWT Fenster stehen haben. Aber er schreibt nichts in das Fenster rein. Aber das Fenster geht auf und ist per Hand auch editierbar.

    Wie kann ich nebenläufig den Text von System.out in die Textarea zeichnen lassen?

    gruß
    Jens

  10. #10
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Kommt es dir nicht ein bisschen seltsam vor, dass du den System.out verwendest um einen neuen System.out zu erzeugen?

    PrintStream backupSystemOutStream = System.out;
    System.setOut(new PrintStream(backupSystemOutStream) {
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  11. #11
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Aber wieso machst du das so kompliziert mit Threads?

    Code:
    	private void initOutputWindow() {
    		FormToolkit toolkit = new FormToolkit(SWTUtil.getDisplay());
    		_text = toolkit.createText(this, "", SWT.MULTI|SWT.WRAP);
    		_text.setEditable(false);
    		_text.setLayoutData(new GridData(GridData.FILL_BOTH));
    		_text.setBackground(SWTUtil.getDisplay().getSystemColor(
    				SWT.COLOR_WIDGET_BACKGROUND));
    		PrintStream p = new PrintStream( 
    				  new OutputStream() { 
    				    public void write( int b ) { 
    				    	_text.append("" + (char)b ); 
    				    } 
    				  } 
    				);
    		System.setOut(p);
    	}
    mfg, christian
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  12. #12
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    hmm, das sieht ja sehr gut aus. Welche Library muss ich für FormToolkit importen? Die SWT Lib reicht anscheinend nicht. Das Programm ist keine Rich-Client Anwendung. Ich möchte so wenig Libs wie möglich verwenden. Wenn der Code nicht blockierend ist, wäre mir sehr geholfen.

    Danke
    Jens

  13. #13
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Das FormToolKit brauchst du ja nicht unbedingt für deine PrintStream-Lösung. Ich habe einfach nur die Methode in mein SWTUtil-Projekt hineingeschrieben.

    Aber ich verwende es gerne, da es die Arbeit mit den Widgets vereinfacht.
    Es ist in der ui.forms-Lib dabei.

    Anstatt createText könntest du auch ein gewöhnliches new Text nehmen. Kommt auf das gleiche raus.

    Mfg, Christian
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  14. #14
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    Hallo nochmal,
    ich habe jetzt in meinem Hauptprogramm den folgenden Code eingefügt:

    Shell peter = new Shell(SWT.DIALOG_TRIM);
    final Text _text = new Text(peter, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);

    _text.setEditable(false);
    _text.setLayoutData(new GridData(GridData.FILL_BOTH));
    PrintStream p = new PrintStream(
    new OutputStream() {
    public void write( int b ) {
    _text.append("" + (char)b );
    }
    }
    );
    System.setOut(p);
    System.setErr(p);
    peter.setVisible(true);

    Das Fenster geht auch auf und die CPU Last steigt auf 100%. Leider wird der Inhalt im Fenster aber nicht gerefreshed. Wie kann ich erreichen, dass der Text angezeigt wird ? Geht das auch ressourcenschonender ?

    gruß
    jens

  15. #15
    Registrierter Benutzer
    Registriert seit
    22.06.2006
    Beiträge
    12
    Hi nochmal,
    ich bin bisher noch erfolglos.

    Hat keiner eine einfache Lösung der Form....

    OutputWindow owindow = new OutputWindow();

    dass ein SWT Fenster erzeugt (eigener Thread) und sich um das Umlenken der OutputStröme kümmert?

    gruß
    jens

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •