2017-06-01 62 views
1

我有一个JTextAreaJScrollPane,我附加邮件display.append()。我试图通过在追加文本后将滚动条的值设置为最大值来自动滚动。但是,getVerticalScrollBar().getMaximum()的值在追加行后不会立即更新。我试图强制更新revalidate(),repaint()updateUI(),但似乎无法找到正确的功能。Java Swing JScrollBar何时更新其大小?

MWE:

import java.awt.BorderLayout; 
import java.awt.Font; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JScrollBar; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 

public class MessageDisplayPane extends JScrollPane { 
    private static final long serialVersionUID = 2025745714938834689L; 

    public static final int NUM_LINES = 5; 

    private JTextArea display; 
    private JScrollBar vertical = getVerticalScrollBar(); 

    public MessageDisplayPane() { 
     display = createTextArea(); 
     setViewportView(display); 
    } 

    private JTextArea createTextArea() { 
     JTextArea ta = new JTextArea(NUM_LINES, 0); 
     ta.setEditable(false); 
     ta.setLineWrap(true); 
     ta.setWrapStyleWord(true); 
     ta.setFont(new Font("Arial", Font.PLAIN, 12)); 
     ta.setBorder(BorderFactory.createEtchedBorder()); 
     return ta; 
    } 

    class EventListener implements ActionListener { 
     public void actionPerformed(ActionEvent e) { 
      new Thread() { 
       @Override 
       public void run() { 
        System.out.println(vertical.getMaximum()); 

        display.append("test\r\n"); 
        revalidate(); 
        repaint(); 
        updateUI(); 

        System.out.println(vertical.getMaximum()); 
        System.out.println(); 

        //vertical.setValue(vertical.getMaximum()); 
       } 
      }.start(); 
      } 
     } 

    public static void main(String[] args) { 
     JFrame.setDefaultLookAndFeelDecorated(true); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       MessageDisplayPane messagePane = new MessageDisplayPane(); 
       JButton button = new JButton("Display another line"); 

       frame.setSize(800, 300); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.getContentPane().add(button, BorderLayout.CENTER); 
       frame.getContentPane().add(messagePane, BorderLayout.SOUTH); 

       button.addActionListener(messagePane.new EventListener()); 

       frame.setVisible(true); 
      } 
     }); 
    } 

} 
+1

请提供一个可运行的示例([SSCCE](http://sscce.org)),以便我们能够理解和重现您的问题。 –

+0

在制作示例的过程中,我发现默认情况下,添加文本时窗口会滚动 - 我遇到的问题是从单独的线程添加文本时不会发生这种情况。 – Dimpl

回答

1

一个可能的解决办法是设置文本插入符的位置到最后(或开头),是这样的:

textArea.setCaretPosition (textArea.getText().length()); // to scroll to the bottom 
textArea.setCaretPosition (0); // to scroll to the top 

我用了一个类似的指令将插入位置设置为0,并且滚动条自动滚动到顶部,所以它应该适合您。

+0

我想我以前见过这个解决方案。我认为这是行不通的,因为我已经将可编辑设置为假,但它似乎有诀窍! – Dimpl