2014-01-12 57 views
3

我想建立一个动态的日志窗口(基本上是一个自动滚动的jtext区域)。使用ScrollPane自动滚动JTextArea?

我遇到的问题是,虽然我打印的文本区域500线,它显示如下:

enter image description here

下面你有我的代码:

import java.awt.Dimension; 

import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.text.DefaultCaret; 


public class Main { 

    private static JFrame mainFrame; 

    public static void main(String args[]) { 
     mainFrame = new JFrame(); 
     mainFrame.setSize(500, 500); 

     mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     ControlPanel cp = new ControlPanel(); 
     mainFrame.add(cp); 
     mainFrame.setVisible(true); 
    } 
} 

class ControlPanel extends JPanel { 

private JButton resetButton = new JButton("Reset"); 

private JPanel logPanel = new JPanel(); 

private JLabel actionLogsLabel = new JLabel("Action Log"); 

private JLabel pointsLogsLabel = new JLabel("Points Log"); 

private JTextArea actionLog = new JTextArea(); 

private JTextArea pointsLog = new JTextArea(); 

private JScrollPane actionScroll; 

private JScrollPane pointsScroll; 

public ControlPanel() { 
    init(); 

    this.add(resetButton); 
    this.add(logPanel); 
} 

private void init() { 
    this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 
    this.setAlignmentX(LEFT_ALIGNMENT); 
    this.logPanel.setLayout(new BoxLayout(logPanel, BoxLayout.Y_AXIS)); 
    this.logPanel.setAlignmentX(LEFT_ALIGNMENT); 

    actionLog.setPreferredSize(new Dimension(500, 300)); 
    actionLog.setMaximumSize(actionLog.getPreferredSize()); 
    actionLog.setEditable(false); 
    actionLog.setWrapStyleWord(true); 
    DefaultCaret caret = (DefaultCaret) actionLog.getCaret(); 
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); 

    pointsLog.setPreferredSize(new Dimension(500, 300)); 
    pointsLog.setMaximumSize(pointsLog.getPreferredSize()); 
    pointsLog.setEditable(false); 
    pointsLog.setWrapStyleWord(true); 

    pointsScroll = new JScrollPane(pointsLog, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
    actionScroll = new JScrollPane(actionLog, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

    logPanel.add(actionLogsLabel); 
    logPanel.add(actionScroll); 

    for(int i = 0; i < 500; i++) { 
     actionLog.setText(actionLog.getText() + "Line: " + i + "\n"); 
    } 

    logPanel.add(pointsLogsLabel); 
    logPanel.add(pointsScroll); 
} 
} 

希望有更多Swing经验的人可以花时间用这种方式指出正确的方式。

回答

4

永远不要这样做:

actionLog.setPreferredSize(new Dimension(500, 300)); 

由于通过这样做,你人为地限制造成当前伤脑筋你的效果JTextArea中的大小。还要注意,避免在任何事物上设置首选尺寸通常是一个好主意。

而是设置JTextARea的列和行计数。这可以通过setter方法或通过简单的构造函数调用来完成:JTextArea myTextArea = new JTextArea(rows, columns);

顺便说一句:我不知道JList是否会更适合您。


MCVE例子:

import javax.swing.*; 
import javax.swing.text.DefaultCaret; 

public class Main2 { 

    private static void createAndShowGUI() { 
     JPanel mainPanel = new ControlPanel(); 

     JFrame frame = new JFrame("Main2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

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

class ControlPanel extends JPanel { 
    private static final int LOG_ROWS = 15; 
    private static final int LOG_COLS = 40; 
    private JButton resetButton = new JButton("Reset"); 
    private JPanel logPanel = new JPanel(); 
    private JLabel actionLogsLabel = new JLabel("Action Log"); 
    private JLabel pointsLogsLabel = new JLabel("Points Log"); 
    private JTextArea actionLog = new JTextArea(); 
    private JTextArea pointsLog = new JTextArea(); 
    private JScrollPane actionScroll; 
    private JScrollPane pointsScroll; 

    public ControlPanel() { 
     init(); 
     this.add(resetButton); 
     this.add(logPanel); 
    } 

    private void init() { 
     this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 
     this.setAlignmentX(LEFT_ALIGNMENT); 
     this.logPanel.setLayout(new BoxLayout(logPanel, BoxLayout.Y_AXIS)); 
     this.logPanel.setAlignmentX(LEFT_ALIGNMENT); 
     // !! actionLog.setPreferredSize(new Dimension(500, 300)); 
     // !! actionLog.setMaximumSize(actionLog.getPreferredSize()); 
     actionLog.setRows(LOG_ROWS); // !! 
     actionLog.setColumns(LOG_COLS); // !! 

     actionLog.setEditable(false); 
     actionLog.setWrapStyleWord(true); 
     DefaultCaret caret = (DefaultCaret) actionLog.getCaret(); 
     caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); 
     // !! pointsLog.setPreferredSize(new Dimension(500, 300)); 
     // !! pointsLog.setMaximumSize(pointsLog.getPreferredSize()); 
     pointsLog.setRows(LOG_ROWS); // !! 
     pointsLog.setColumns(LOG_COLS); // !! 

     pointsLog.setEditable(false); 
     pointsLog.setWrapStyleWord(true); 
     pointsScroll = new JScrollPane(pointsLog, 
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     actionScroll = new JScrollPane(actionLog, 
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     logPanel.add(actionLogsLabel); 
     logPanel.add(actionScroll); 
     for (int i = 0; i < 500; i++) { 
     actionLog.setText(actionLog.getText() + "Line: " + i + "\n"); 
     } 
     logPanel.add(pointsLogsLabel); 
     logPanel.add(pointsScroll); 
    } 
} 

编辑
实例嵌套布局和JList的:

import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 

import javax.swing.*; 

public class Main2B { 

    private static void createAndShowGUI() { 
     ControlPanel2B controlPanel = new ControlPanel2B(); 
     controlPanel.setBorder(BorderFactory.createEtchedBorder()); 

     JPanel mainPanel = new JPanel(new GridBagLayout()); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     mainPanel.add(controlPanel, gbc); 

     JFrame frame = new JFrame("Main2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

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

@SuppressWarnings("serial") 
class ControlPanel2B extends JPanel { 
    private static final int LOG_ROWS = 15; 
    private static final int LIST_WIDTH = 500; 
    private JButton resetButton = new JButton("Reset"); 
    private JPanel logPanel = new JPanel(); 
    private JLabel actionLogsLabel = new JLabel("Action Log"); 
    private JLabel pointsLogsLabel = new JLabel("Points Log"); 

    private DefaultListModel<String> actionLogListModel = new DefaultListModel<>(); 
    private JList<String> actionLogList = new JList<String>(actionLogListModel); 
    private DefaultListModel<String> pointsLogListModel = new DefaultListModel<>(); 
    private JList<String> pointsLogList = new JList<String>(pointsLogListModel); 
    private JScrollPane actionScroll; 
    private JScrollPane pointsScroll; 

    public ControlPanel2B() { 
     init(); 
     this.add(resetButton); 
     this.add(logPanel); 
    } 

    private void init() { 
     actionLogList.setVisibleRowCount(LOG_ROWS); 
     pointsLogList.setVisibleRowCount(LOG_ROWS); 
     actionLogList.setFixedCellWidth(LIST_WIDTH); 

     this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 
     this.setAlignmentX(LEFT_ALIGNMENT); 
     this.logPanel.setLayout(new BoxLayout(logPanel, BoxLayout.Y_AXIS)); 
     this.logPanel.setAlignmentX(LEFT_ALIGNMENT); 
     pointsScroll = new JScrollPane(pointsLogList, 
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     actionScroll = new JScrollPane(actionLogList, 
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
     logPanel.add(actionLogsLabel); 
     logPanel.add(actionScroll); 
     for (int i = 0; i < 500; i++) { 
     actionLogListModel.addElement("Line: " + i); 
     } 
     logPanel.add(pointsLogsLabel); 
     logPanel.add(pointsScroll); 
    } 
} 
+0

我现在遇到的问题是,我不能保持一个固定的大小。 JText区域向下扩展太多(甚至在设置了maxSize(new Dimension(X,Y))之后);另外,我现在想保留一个文本区域,它适合我更好地从应用程序中收到的那种日志。 – Eugen

+0

@Eugen:你有更多的问题,然后原来的问题引导我们,听起来好像你错误地使用布局。我敦促你创建并发布一个[最小,完整,有效的例子](http:///stackoverflow.com/help/mcve),所以我们可以亲身体验你的问题。 –

+0

我将编辑上面的代码,并立即添加完整的JPanel。 – Eugen