2015-10-07 2 views
-1

У меня возникли проблемы с добавлением анимации в программу чата. Он отлично работает, пока JScrollPane не начнет прокрутку, и в этот момент ScrollPane не обновляется до тех пор, пока «runnable» не пройдет через следующий цикл (анимация работает, и нет, Thread.sleep здесь не проблема). У кого-нибудь есть совет? Я пробовал такие вещи, как вызов revalidate, но без каких-либо различий. Строка ~ 188 с комментарием «// Необходимость jsp (JScrollPane) для мгновенного обновления» - это то, где мне понадобится JScrollPane, чтобы обновить его представление. Благодаря! упаковка com.AI;JScrollPane не обновляется мгновенно

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.io.IOException; 
import java.sql.Date; 
import java.util.Calendar; 
import java.util.Random; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollBar; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.border.LineBorder; 
import javax.swing.text.DefaultCaret; 

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

Как и в большинстве вопросов типа «Swing GUI is frozen», вы топаете в потоке событий Swing, здесь, вызывая 'Thread.sleep (...)' в этом потоке. Решение: не делайте этого. Если вам нужна задержка, используйте таймер Swing (учебник Google), или если вам нужно запустить длинный код, используйте Swing Worker (снова Google, учебник). –

+0

Судно на воздушной подушке, это не проблема. Задержка работает отлично, и анимация работает. Единственное, что мне нужно, это код, необходимый для мгновенного обновления JScrollPane, независимо от любого таймера/сна. – EcstaticException

+0

.......................... .Здравствуйте? Пожалуйста, см. Изменения кода в моем ответе, что в значительной степени доказывает, что это проблема Thread.sleep. –

ответ

0

на воздушной подушке, что это не проблема. Задержка работает отлично, и анимация работает. Единственное, что мне нужна помощь в код, необходимый, чтобы немедленно обновить JScrollPane, независимо от таймера/Sleep

Да ваше использование Thread.sleep(...)является вопрос. Например, если вы используете Swing, Таймер, как рекомендовано выше для отсроченной печати, ScrollPane обновления сразу:

import java.awt.BorderLayout; 
import java.awt.Font; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class MainGui2 extends JPanel { 
    private static final Font TEXT_AREA_FONT = new Font("Arial", Font.PLAIN, 18); 
    private static final String TEST_MESSAGE = "TEST................"; 
    private static final String TIMER = "Timer"; 
    private static final String THREAD_SLEEP = "Thread.sleep"; 
    private static final String[] RADIOS = { TIMER, THREAD_SLEEP }; 
    public static final int TIMER_DELAY = 80; 
    private JTextArea textArea = new JTextArea(20, 40); 
    private JTextField textField = new JTextField(10); 
    private Action sendMsgAxn = new SendMessageAction("Send Message"); 
    private JButton sendMsgButton = new JButton(sendMsgAxn); 
    private ButtonGroup buttonGroup = new ButtonGroup(); 

    public MainGui2() { 
     textArea.setFont(TEXT_AREA_FONT); 
     textArea.setWrapStyleWord(true); 
     textArea.setLineWrap(true); 
     textArea.setFocusable(false); 
     JScrollPane scrollPane = new JScrollPane(textArea); 
     scrollPane 
       .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 

     textField.setAction(sendMsgAxn); 

     JPanel radioPanel = new JPanel(new GridLayout(1, 0)); 
     for (String radioText : RADIOS) { 
      JRadioButton rBtn = new JRadioButton(radioText); 
      rBtn.setActionCommand(radioText); 
      buttonGroup.add(rBtn); 
      radioPanel.add(rBtn); 
     } 

     JPanel southPanel = new JPanel(); 
     southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.LINE_AXIS)); 
     southPanel.add(textField); 
     southPanel.add(radioPanel); 
     southPanel.add(sendMsgButton); 

     setLayout(new BorderLayout()); 
     add(scrollPane, BorderLayout.CENTER); 
     add(southPanel, BorderLayout.PAGE_END); 
    } 

    class SendMessageAction extends AbstractAction { 
     private Timer timer; 

     public SendMessageAction(String name) { 
      super(name); 
      int mnemnoic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemnoic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (timer != null && timer.isRunning()) { 
       return; 
      } 

      ButtonModel model = buttonGroup.getSelection(); 
      if (model == null) { 
       return; 
      } 

      String text = textField.getText(); 
      textField.selectAll(); // so text can easily be changed 
      textArea.append("\nUser > " + text + "\n"); 
      // TODO: in a background thread -- send text to outside process 

      String command = model.getActionCommand(); 
      if (command.equals(TIMER)) { 
       timerAction(TEST_MESSAGE); 
      } else if (command.equals(THREAD_SLEEP)) { 
       threadSleepAction(TEST_MESSAGE); 
      } 

     } 

     private void threadSleepAction(String text) { 
      for (int i = 0; i < text.length(); i++) { 
       textArea.append("" + text.charAt(i)); 
       textArea.setCaretPosition(textArea.getDocument().getLength()); 
       textArea.paintImmediately(textArea.getBounds()); 
       try { 
        Thread.sleep(TIMER_DELAY); 
       } catch (InterruptedException e) { 
       } 
      } 
     } 

     private void timerAction(String text) { 
      timer = new Timer(TIMER_DELAY, new TimerListener(text)); 
      timer.start(); 
     } 
    } 

    private class TimerListener implements ActionListener { 
     private String message; 
     private int index = 0; 

     public TimerListener(String message) { 
      this.message = message; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (message.length() == index) { 
       ((Timer) e.getSource()).stop(); // stop the timer 
      } else { 
       textArea.append("" + message.charAt(index)); 
       index++; 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("MainGui2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new MainGui2()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

И не используйте KeyListener с JTextField когда-либо. Вместо этого вы хотите использовать ActionListener или Action, и на самом деле можете использовать одно и то же действие для вашего JButton, как и для вашего JTextField.

Смежные вопросы