2014-01-12 61 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