我的Java程序中有一个带有JPanel的ScrollPane,可以附加很多文本。每次添加后我都需要ScrollPane滚动到最底部。以下代码的问题在于它滚动了几乎"到底但不是一路走来。关于我做错了什么想法?
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)
基本上,您可能在组件层次结构有时间更新之前尝试更新视口。有时候,你只需要等待。
此示例基本上使用SwingUtilities.invokeLater
将请求发送到事件队列,以便在不久的将来某些时间执行某些工作&#34;。这允许当前待处理的更新处理时间......
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偏移量,这将允许最后一个元素可见......