2015-02-23 132 views
0

我在我的Java程序中有一個帶有JPanel的ScrollPane,它可以獲得大量的文本。我需要ScrollPane在每次添加後滾動到最底部。我的問題與下面的代碼是它幾乎「滾動」到底部,但不是所有的方式。任何關於我在做什麼的想法都是錯誤的?Java JScrollPane滾動到底...幾乎

import javax.swing.*; 
import javax.swing.border.*; 
import java.awt.*; 
import java.awt.event.*; 

public class Sample extends JFrame{ 
    JTextField input = new JTextField(); 
    JPanel log = new JPanel(); 
    JScrollPane scrollPane = new JScrollPane(log); 
    JScrollBar scrollBar = scrollPane.getVerticalScrollBar(); 

    public Sample(){ 

     input.setBorder(new TitledBorder("Message")); 
     input.setToolTipText("Type a message here."); 

     log.setBorder(new TitledBorder("Log")); 
     log.setLayout(new BoxLayout(log, BoxLayout.Y_AXIS)); 
     log.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 

     // Add the panels to the frame 
     setLayout(new BorderLayout(10, 10)); 
     add(input, BorderLayout.NORTH); 
     add(scrollPane, BorderLayout.CENTER); 

     setTitle("Chat Window"); 
     setSize(400, 300); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 

     // Register Key listener 
     input.addKeyListener(new KeyAdapter() { 
      @Override 
      public void keyReleased(KeyEvent e) { 
       if (e.getKeyCode() == KeyEvent.VK_ENTER) { 
        log.add(new ServerBubble(input.getText())); 
        log.add(Box.createRigidArea(new Dimension(0, 10))); 
        input.setText(null); 
        scrollPane.revalidate(); 
        scrollBar.setValue(scrollBar.getMaximum()); 
       } 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     JFrame frame = new Exercise33_9Server(); 

    } 

    private class ServerBubble extends JLabel{ 

     private final Color LIGHT_GREEN = new Color(204, 255, 229); 
     private final Color DARK_GREEN = new Color(0, 102, 51); 
     String message; 

     public ServerBubble(String label){ 
      message = processText(label); 
      setOpaque(true); 
      setForeground(DARK_GREEN); 
      setBackground(LIGHT_GREEN); 
      setHorizontalAlignment(LEFT); 
      setBorder(new LineBorder(DARK_GREEN, 3, true)); 
      setText(label); 
      setBorder(BorderFactory.createCompoundBorder(getBorder(), BorderFactory.createEmptyBorder(5, 5, 5, 5))); 
     } 

     private String processText(String message){ 
      message = "<HTML>" + message; 
      return message; 
     } 
    } 
} 
+0

1-在KeyListener上使用鍵綁定API;在嘗試移動到滾動窗格的末尾之前,重新驗證視圖('log') – MadProgrammer 2015-02-23 03:52:06

+0

我必須使用keyListener,因爲它是學校作業目標的一部分。 – 2015-02-23 04:09:31

+0

然後你的學校就是時代的背後...... – MadProgrammer 2015-02-23 04:11:24

回答

0

基本上,您可能試圖在組件層次結構有時間更新之前更新視口。有時候,你只是在等待。

本示例基本上使用SwingUtilities.invokeLater向「事件隊列」發出請求,要求「在不久的將來某個時間」執行某些工作。這使當前的等待更新時間要處理......

if (e.getKeyCode() == KeyEvent.VK_ENTER) { 

    log.add(new ServerBubble(input.getText())); 
    log.add(Box.createRigidArea(new Dimension(0, 10))); 
    input.setText(null); 
    log.revalidate(); 

    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      Dimension vpSize = scrollPane.getViewport().getExtentSize(); 
      Dimension logSize = log.getSize(); 

      int height = logSize.height - vpSize.height; 
      scrollPane.getViewport().setViewPosition(new Point(0, height)); 
     } 
    }); 
} 

而此時,我搶鑑於當前的大小,並將其與日誌面板的電流的大小,然後我用的是不同的計算面板底部的y偏移量,這將允許最後一個元素可見...

+0

是的!這解決了這個問題。我拉着我的頭髮試圖讓這個工作。非常感謝你。 – 2015-02-23 15:00:40