Search code examples
javaswingcharacter-encodingjtextareaprintstream

Adding a console output to Swing gui that can support special characters


My application has a console where all the system's printstream content is rerouted to.

My application will also output special characters, specifically other languages (asian languages, Russian, Arabic, etc)

I'm using a JTextArea as the console out:

    consoleOutput = new JTextArea(1, 50);

    DefaultCaret caret = (DefaultCaret) consoleOutput.getCaret();
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

    Font font = new Font("Consolas", Font.PLAIN, 12);
    consoleOutput.setFont(font);

    JScrollPane scrollPane = new JScrollPane(consoleOutput);
    this.add(scrollPane, BorderLayout.CENTER);


    //CHANGE OUTPUT TO THIS CONSOLE
    PrintStream out = new PrintStream(new TextAreaOutput(consoleOutput));

    System.setOut(out);
    System.setErr(out);

And this class to rerout the printstream:

public class TextAreaOutput extends OutputStream {
    JTextArea outputConsole;

    public TextAreaOutput(JTextArea outputConsole) {
        this.outputConsole = outputConsole;
    }

    @Override
    public void write(int b) throws IOException {
        outputConsole.append( String.valueOf( ( char )b ) );
    }
}

This works and the printstream prints to this jtextarea. However, I have encoding issues. Special characters like ▒, █, .نت, 览, etc do not render correctly. Some might be hardcoded into source files (I'm using UTF-8), but some might be extracted from the web with selenium webdriver.


Solution

  • import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.util.Date;
    import javax.swing.*;
    
    public class TextAreaOutputStreamTest {
      private final JTextArea consoleOutput = new JTextArea();
      private final JTextField textField = new JTextField();
    
      public JComponent makeUI() {
        try {
          OutputStream os = new TextAreaOutputStream(consoleOutput);
          System.setOut(new PrintStream(os, true, "UTF-8"));
        } catch (IOException ex) {
          ex.printStackTrace();
        }
        Box box = Box.createHorizontalBox();
        box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        box.add(Box.createHorizontalGlue());
        box.add(textField);
        box.add(Box.createHorizontalStrut(5));
        box.add(new JButton(new AbstractAction("Enter") {
          @Override public void actionPerformed(ActionEvent e) {
            String s = new Date().toString();
            System.out.println(s + "\n    " + textField.getText());
          }
        }));
        consoleOutput.setEditable(false);
    
        JPanel p = new JPanel(new BorderLayout());
        p.add(new JScrollPane(consoleOutput));
        p.add(box, BorderLayout.SOUTH);
        return p;
      }
      public static void main(String... args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new TextAreaOutputStreamTest().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    }
    
    class TextAreaOutputStream extends OutputStream {
      private final ByteArrayOutputStream buf = new ByteArrayOutputStream();
      private final JTextArea consoleOutput;
      public TextAreaOutputStream(JTextArea consoleOutput) {
        super();
        this.consoleOutput = consoleOutput;
      }
      @Override public void flush() throws IOException {
        consoleOutput.append(buf.toString("UTF-8"));
        buf.reset();
      }
      @Override public void write(int b) throws IOException {
        buf.write(b);
      }
    }