//将控制台数据重定向到控件上
//原理:控制台OutputStream -> InputStream -> 控件
//PipedStreams类用于将OutputStream数据实时写到InputStream里面
//ConsoleRedirector类用于将InputStream实时写到控件里面
public class ConsoleRedirector {
@SneakyThrows
public static void main(String... args) {
//显示Swing窗口
System.setProperty("java.awt.headless", "false");
SwingUtil.bindSkin();
JLabel label = new JLabel("智 能 警 示 系 统 后 台");
label.setPreferredSize(new Dimension(200, 30));
label.setOpaque(false);
label.setForeground(ColorUtil.RED);
label.setFont(FontUtil.ARIAL_15);
label.setHorizontalTextPosition(JLabel.CENTER);
HorizontalViewBundle b1 = CentralViewBundle.packVerticalViews(10, label);
JTextArea edit = new JTextArea();
edit.setBorder(null);
edit.setBackground(ColorUtil.EMPTY);
edit.setForeground(ColorUtil.PURPLE);
JScrollPane s = new JScrollPane(edit);
s.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
s.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel root = new JPanel();
root.setLayout(new BorderLayout());
root.add(b1, BorderLayout.NORTH);
root.add(s, BorderLayout.CENTER);
JFrame window = new JFrame("智能警示系统后台");
window.setContentPane(root);
window.setSize(400, 400);
window.setResizable(false);
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
SwingUtil.icon(window, "/resource/icon_wechat.png");
SwingUtil.center(window);
window.setVisible(true);
//将控制台数据重定向到控件中
redirectTo(edit);
//模拟打印,不停向控制台打印数据
new Thread(ConsoleRedirector::printLines).start();
}
//模拟打印,不停向控制台打印数据
@SneakyThrows
private static void printLines() {
while (true) {
System.out.println(TextUtil.random());
Thread.sleep(500);
}
}
//将控制台数据重定向到控件中
@SneakyThrows
public static void redirectTo(JTextArea textArea) {
//将控制台重定位到PipedStreams中的输出流
PipedStreams pipedStreams = new PipedStreams();
BufferedReader reader = new BufferedReader(new InputStreamReader(pipedStreams.getInputStream()));
PrintStream printer = new PrintStream(pipedStreams.getOutputStream());
System.setOut(printer);
System.setErr(printer);
//从PipedStreams中的输入流读取数据,写入到控件中
new Thread(() -> readLines(textArea, reader)).start();
}
//从PipedStreams中的输入流读取数据,写入到控件中
@SneakyThrows
private static void readLines(JTextArea textArea, BufferedReader reader) {
while (true) {
String line = reader.readLine();
if (line != null) {
textArea.insert(line + "\n", textArea.getDocument().getLength());
textArea.setCaretPosition(textArea.getDocument().getLength());
Thread.sleep(500);
}
}
}
}
//这个类自动将OutputStream收到的数据写到InputStream里面
public class PipedStreams {
private PipedInputStream is;
private PipedOutputStream os;
private ByteArrayOutputStream bos;
private boolean alive;
@SneakyThrows
public PipedStreams() {
alive = true;
is = new PipedInputStream() {
@SneakyThrows
public void close() {
alive = false;
super.close();
}
};
os = new PipedOutputStream();
bos = new ByteArrayOutputStream() {
@SneakyThrows
public void close() {
alive = false;
super.close();
os.close();
}
};
os.connect(is);
//将输出流数据写到输入流
new Thread(() -> startRead()).start();
}
//将输出流数据写到输入流
@SneakyThrows
private void startRead() {
while (alive) {
if (bos.size() > 0) {
byte[] buffer = null;
synchronized (bos) {
buffer = bos.toByteArray();
bos.reset();
}
os.write(buffer, 0, buffer.length);
} else
Thread.sleep(500);
}
}
public InputStream getInputStream() {
return is;
}
public OutputStream getOutputStream() {
return bos;
}
}