让我的JScrollPane自动更新并在动作侦听器中滚动时遇到了一些麻烦。在Thread.sleep()类型中出现一个字母动画,但是一旦滚动条需要滚动(它在动作监听器之后滚动),它就不起作用。我想知道是否有人可以帮助我发表评论//需要jsp(JScrollPane)立即更新
谢谢,真的很感激一些帮助
public class MainGUI {
public String appName = "Chat Assistant v1.3.3";
public MainGUI mainGUI;
public JPanel mainPanel;
public JScrollPane jsp;
public JFrame newFrame = new JFrame(appName);
public JButton sendMessage;
public JTextField messageBox = new JTextField(30);
public JTextArea chatBox;
String username = "Evan";
public Random rand = new Random();
public Calendar cal= Calendar.getInstance();
//public MainEngine me = new MainEngine();
public String temp = "";
public String tempL = "";
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
MainGUI mainGUI = new MainGUI();
mainGUI.display();
}
});
}
public void display() {
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JPanel southPanel = new JPanel();
southPanel.setBackground(Color.BLUE);
southPanel.setLayout(new GridBagLayout());
messageBox.requestFocusInWindow();
sendMessage = new JButton("Send Message");
sendMessage.addActionListener(new sendMessageButtonListener());
chatBox = new JTextArea();
chatBox.setEditable(false);
chatBox.setFont(new Font("Arial", Font.PLAIN, 18));
chatBox.setLineWrap(true);
jsp = new JScrollPane(chatBox);
jsp.setBorder(new LineBorder(Color.white, 7));
mainPanel.add(jsp, BorderLayout.CENTER);
GridBagConstraints left = new GridBagConstraints();
left.anchor = GridBagConstraints.LINE_START;
left.fill = GridBagConstraints.HORIZONTAL;
left.weightx = 512.0D;
left.weighty = 1.0D;
GridBagConstraints right = new GridBagConstraints();
right.insets = new Insets(0, 10, 0, 0);
right.anchor = GridBagConstraints.LINE_END;
right.fill = GridBagConstraints.NONE;
right.weightx = 1.0D;
right.weighty = 1.0D;
southPanel.add(messageBox, left);
southPanel.add(sendMessage, right);
mainPanel.add(BorderLayout.SOUTH, southPanel);
newFrame.add(mainPanel);
newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
newFrame.setSize(720, 480);
newFrame.setVisible(true);
newFrame.setResizable(false);
newFrame.setLocationRelativeTo(null);
messageBox.requestFocusInWindow();
messageBox.addKeyListener(new KeyListener());
startup();
}
public void startup() {
int h = cal.get(Calendar.HOUR_OF_DAY);
int n = rand.nextInt(2) + 1;
String message = "";
chatBox.append("AIBot: ");
if (n == 1)
message = "Welcome back sir!";
else if ( n == 2) {
if ((h > 4) && (h < 11))
message = "Good Morning sir, I hope you have a great day.";
else if ((h >= 11) && (h < 17))
message = "Good Afternoon sir";
else if ((h >= 17) && (h < 25))
message = "Good Evening sir, how was your day?";
else
message = "It's quite late, you should get some rest sir";
}
try {
Runtime.getRuntime().exec( new String[] { "say" , "" + message }) ;
} catch (IOException e) {
e.printStackTrace();
}
messageBox.paintImmediately(messageBox.getBounds());
sendMessage.paintImmediately(sendMessage.getBounds());
messageBox.requestFocusInWindow();
for (int i = 0; i < message.length(); i++) { //Appends 1 letter at a time, "animation", voice is already executed
try {Thread.sleep(35);} catch (InterruptedException e) {e.printStackTrace();}
chatBox.append(message.substring(i, i+1));
chatBox.setCaretPosition(chatBox.getDocument().getLength());
chatBox.paintImmediately(chatBox.getBounds ());
}
chatBox.append("\n\n");
messageBox.setText("");
}
public class KeyListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
sendMessage.doClick();
}
}
}
public class sendMessageButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (messageBox.getText().length() < 1) {
// do nothing
} else if (messageBox.getText().equals(".clear")) {
chatBox.setText("Cleared all messages\n");
messageBox.setText("");
} else {
chatBox.append("" + username + ": ");
chatBox.append(messageBox.getText() + "\n\n");
temp = messageBox.getText();
tempL = temp.toLowerCase();
messageBox.setText("");
chatBox.setCaretPosition(chatBox.getDocument().getLength());
chatBox.paintImmediately(chatBox.getBounds ());
}
messageBox.requestFocusInWindow();
chatBox.append("AIBot: ");
//String message = me.disperse(tempL) + " ";
String message = "TEST................";
if (message.contains("username")) {
String[] t = message.split("username");
message = t[0] + username + t[1];
}
chatBox.setCaretPosition(chatBox.getDocument().getLength());
chatBox.paintImmediately(chatBox.getBounds());
//Need jsp (JScrollPane) to instantly update
message += "";
try {
Runtime.getRuntime().exec( new String[] { "say" , "" + message }) ;
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < message.length(); i++) { //Appends 1 letter at a time, "animation", voice is already executed
try {Thread.sleep(35);} catch (InterruptedException e) {e.printStackTrace();}
chatBox.append(message.substring(i, i+1));
chatBox.paintImmediately(chatBox.getBounds());
chatBox.setCaretPosition(chatBox.getDocument().getLength());
}
chatBox.append("\n\n");
chatBox.setCaretPosition(chatBox.getDocument().getLength());
}
}
}
答案 0 :(得分:1)
请勿使用Thread.sleep(...)
。这导致事件调度线程(EDT)进入休眠状态,这意味着在所有代码完成执行之前,GUI无法重新绘制。有关详细信息,请阅读Concurrency in Swing上的Swing教程中的部分。
相反,您可以使用SwingTimer来安排动画。
或者,如果您不想使用Timer,可以使用SwingWorker
,如并发教程中所述。
此外:
不要在文本字段上使用KeyListener来处理Enter键。您只需将ActionListener添加到文本字段即可。当按下Enter键时,将自动调用监听器。
不要使用paintImmediately。一旦你摆脱了Thread.sleep(),GUI就会正常重绘。