如何在 JFrame/JPanel 中可视化控制台 java

Posted

技术标签:

【中文标题】如何在 JFrame/JPanel 中可视化控制台 java【英文标题】:how to visualize console java in JFrame/JPanel 【发布时间】:2012-04-04 07:26:19 【问题描述】:

我使用 Swing 库制作了一个 Java 程序。 现在我想将我的控制台输出重定向到 JFrame 或 JPanel。

【问题讨论】:

那么你的问题到底是什么? 也许将所有内容附加到另一个 Swing 组件(例如 JTextArea)? 【参考方案1】:

我知道我迟到了,但是对于正在寻找更好、更紧凑的答案的人,我让这个女巫结合了两个自定义类。

控制台.java

public class Console 
    final JFrame frame = new JFrame("CONSOLE");
    ColorPane textPane;
    JScrollPane scroll;

    public Console() throws Exception 
        textPane = new ColorPane();
        textPane.setPreferredSize(new Dimension(525, 600));
        textPane.setFont(new Font("Lucida Console", Font.BOLD, 12));
        scroll = new JScrollPane(textPane);
        textPane.setBackground(Color.BLACK);

        scroll.setVerticalScrollBarPolicy ( ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS );

        textPane.getDocument().addDocumentListener(new DocumentListener() 
            @Override
            public void insertUpdate(DocumentEvent e) 
                scrollToBottom(scroll);
            

            @Override
            public void removeUpdate(DocumentEvent e) 

            

            @Override
            public void changedUpdate(DocumentEvent e) 

            
        );

        //Add textPane in to middle panel
        frame.add(scroll);
        frame.setSize(100, 600);
        frame.pack();
        frame.setVisible(false);
        redirectOut();

    

    public PrintStream redirectOut() 
        OutputStream out = new OutputStream() 
            @Override
            public void write(int b) throws IOException 
                textPane.append(Color.WHITE, String.valueOf((char) b));
            
        ;
        OutputStream errOut = new OutputStream() 
            @Override
            public void write(int b) throws IOException 
                textPane.append(Color.RED, String.valueOf((char) b));
            
        ;
        PrintStream ps = new PrintStream(out);
        PrintStream err = new PrintStream(errOut);

        System.setOut(ps);
        System.setErr(err);
        scrollToBottom(scroll);

        return ps;
    

    public JFrame getFrame() 
        return frame;
    

    private void scrollToBottom(JScrollPane scrollPane) 
        JScrollBar verticalBar = scrollPane.getVerticalScrollBar();
        AdjustmentListener downScroller = new AdjustmentListener() 
            @Override
            public void adjustmentValueChanged(AdjustmentEvent e) 
                Adjustable adjustable = e.getAdjustable();
                adjustable.setValue(adjustable.getMaximum());
                verticalBar.removeAdjustmentListener(this);
            
        ;
        verticalBar.addAdjustmentListener(downScroller);
    

和 ColorPane.java

import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

public class ColorPane extends JTextPane 

    public void appendNaive(Color c, String s)  // naive implementation
        // bad: instiantiates a new AttributeSet object on each call
        SimpleAttributeSet aset = new SimpleAttributeSet();
        StyleConstants.setForeground(aset, c);

        int len = getText().length();
        setCaretPosition(len); // place caret at the end (with no selection)
        setCharacterAttributes(aset, false);
        replaceSelection(s); // there is no selection, so inserts at caret
    

    public void append(Color c, String s)  // better implementation--uses
        // StyleContext
        StyleContext sc = StyleContext.getDefaultStyleContext();
        AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
                StyleConstants.Foreground, c);

        int len = getDocument().getLength(); // same value as
        // getText().length();
        setCaretPosition(len); // place caret at the end (with no selection)
        setCharacterAttributes(aset, false);
        replaceSelection(s); // there is no selection, so inserts at caret
    

    public static boolean isPrime(int n) 
        if (n < 2)
            return false;
        double max = Math.sqrt(n);
        for (int j = 2; j <= max; j += 1)
            if (n % j == 0)
                return false; // j is a factor
        return true;
    

    public static boolean isPerfectSquare(int n) 
        int j = 1;
        while (j * j < n && j * j > 0)
            j += 1;
        return (j * j == n);
    


这是我一直在使用的解决方案,它甚至有彩色输出。 PS:顺便说一句,对不起英语不好(我只有 11 岁)

【讨论】:

【参考方案2】:

您需要创建一个将输出重定向到文本区域并实现 OutputStream 接口的所有必要方法的 OutputStream,然后在您的主程序中,将您的标准输出重定向到此流。我在我的一个程序中使用了类似的东西:

import java.io.IOException;
import java.io.OutputStream;

import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TextAreaOutputStream extends OutputStream 

   private final JTextArea textArea;
   private final StringBuilder sb = new StringBuilder();
   private String title;

   public TextAreaOutputStream(final JTextArea textArea, String title) 
      this.textArea = textArea;
      this.title = title;
      sb.append(title + "> ");
   

   @Override
   public void flush() 
   

   @Override
   public void close() 
   

   @Override
   public void write(int b) throws IOException 

      if (b == '\r')
         return;

      if (b == '\n') 
         final String text = sb.toString() + "\n";
         SwingUtilities.invokeLater(new Runnable() 
            public void run() 
               textArea.append(text);
            
         );
         sb.setLength(0);
         sb.append(title + "> ");
         return;
      

      sb.append((char) b);
   

你可以用这个来演示它:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintStream;
import javax.swing.*;

@SuppressWarnings("serial")
public class TextAreaOutputStreamTest extends JPanel 

   private JTextArea textArea = new JTextArea(15, 30);
   private TextAreaOutputStream taOutputStream = new TextAreaOutputStream(
         textArea, "Test");

   public TextAreaOutputStreamTest() 
      setLayout(new BorderLayout());
      add(new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
      System.setOut(new PrintStream(taOutputStream));

      int timerDelay = 1000;
      new Timer(timerDelay , new ActionListener() 
         int count = 0;
         @Override
         public void actionPerformed(ActionEvent arg0) 

            // though this outputs via System.out.println, it actually displays
            // in the JTextArea:
            System.out.println("Count is now: " + count + " seconds");
            count++;
         
      ).start();
   

   private static void createAndShowGui() 
      JFrame frame = new JFrame("Test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new TextAreaOutputStreamTest());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   

   public static void main(String[] args) 
      SwingUtilities.invokeLater(new Runnable() 
         public void run() 
            createAndShowGui();
         
      );
   

【讨论】:

【参考方案3】:

获得JFrameJPanel 后,向其中添加一个文本字段。

JTextArea 是一个不错的选择,因为它是多行。 添加后,您可以.append('text'); 给它,而不是写System.out.print();

JFrame jFrame = new JFrame();

JTextArea jTextArea = new JTextArea();
jTextArea.append( "Hello World." );

jFrame.add( jTextArea );

【讨论】:

好的,我读到了。我认为还有其他事情可以做到这一点。因为已经有 println 我不想添加新的 textarea 并附加它们

以上是关于如何在 JFrame/JPanel 中可视化控制台 java的主要内容,如果未能解决你的问题,请参考以下文章

JFrame / JPanel不会更新重绘或重新验证

java validate()方法无法正常工作

Java:如何在画布中绘制?

学习Java随记之swing编程

Java - Swing - 充满组件的窗口

java图形用户界面认知