Добавление вывода консоли в графический интерфейс Swing, который может поддерживать специальные символы

В моем приложении есть консоль, на которую перенаправляется весь контент системного потока печати.

Мое приложение также будет выводить специальные символы, особенно другие языки (азиатские языки, русский, арабский и т. д.).

Я использую JTextArea в качестве консоли:

    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);

И этот класс для перенаправления потока печати:

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 ) );
    }
}

Это работает, и поток печати печатает в эту jtextarea. Однако у меня проблемы с кодировкой. Специальные символы, такие как ▒, █, .نت, 览, etc, отображаются неправильно. Некоторые могут быть жестко закодированы в исходные файлы (я использую UTF-8), но некоторые могут быть извлечены из Интернета с помощью selenium webdriver.


person Andrio    schedule 01.10.2015    source источник
comment
Символы Юникода имеют длину более 1 байта. В UTF-8 каждый символ может быть представлен от 1 до 6 байтов. Так что ваш метод write не сработает. Возможно, вы захотите изучить UTF-8 и разработать лучший метод.   -  person RealSkeptic    schedule 01.10.2015
comment
Font font = new Font("Consolas", Font.PLAIN, 12); Поддерживает ли этот шрифт соответствующие наборы символов?   -  person Andrew Thompson    schedule 01.10.2015
comment
@AndrewThompson Вы правы, шрифт, похоже, не поддерживает специальные символы, но другая проблема заключается в том, что метод записи не работает правильно с UTF-8, согласно другому комментарию.   -  person Andrio    schedule 01.10.2015
comment
@RealSkeptic Я вижу, имеет смысл, что этот метод записи не будет правильно работать с UTF-8.   -  person Andrio    schedule 01.10.2015
comment
..но другая проблема.. Чтобы быстрее получить помощь, опубликуйте минимально воспроизводимый пример или Короткий, автономный, правильный пример.   -  person Andrew Thompson    schedule 03.10.2015


Ответы (1)


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);
  }
}
person aterai    schedule 02.10.2015