2016-09-02 81 views
2

我正在製作一個文本冒險遊戲,並遇到了一個問題,我無法以我想要的方式獲取一些文本顯示。當輸入一些單詞時,玩家可以開始引入新房間。我想要這個介紹有「打字機」的效果。此事件需要在我的程序ActionPerformed方法中進行。例如,當用戶鍵入「移動」然後點擊輸入時,我想讓結果文本一次打印一個字符。使用計時器在JTextArea中實現打字機效果?

這是當前的方法我用的actionPerformed之外實現這樣的效果:我怎樣才能得到類似的方法與使用Timer類的工作,所以它不會阻止我的線程

public void slowPrint(String message, long millisPerChar) 
{ 
    //makes it so that the player cannot input while the text is being displayed 
    userinput.setEditable(false); 
    String o; 
     for (int i = 0; i < message.length(); i++) 
     { 
      //adds each letter one-by-one 
      o = "" + message.charAt(i); 
      output.append(o); 

      //moves the JTextArea to the bottom 
      output.setCaretPosition (output.getDocument().getLength()); 

      //delay so that you can see each letter being added 
      try { 
       Thread.sleep(millisPerChar);; 
       } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); } 
     } 
    //after the text is displayed allow the user to input again 
    userinput.setEditable(true); 
    } 

從更新GUI。

這就是我的行動進行貌似相關的方法:

public void actionPerformed(ActionEvent e) 
{ 
     s = userinput.getText(); 
     output.append("\n"); 
     userinput.setText(""); 

     for (int i = 0; i<whatRoom.length; i++) 
     { 
      if (whatRoom[i]) 
      { 
       switch(i) 
       { 
        case 0: 
         controlOne(s); 
         break; 
        case 1: 
         break; 
        case 2: 
         break; 
        case 3: 
         break; 
        case 4: 
         break; 
        case 5: 
         break; 
       } 
      } 
     } 

    } 

與「controlOne()」方法:

private void controlOne(String s) 
{ 
    if(one.getHasLight() == true) 
    { 
     if(!one.getPushYes()) 
     { 
      output.append(one.dealWithLight(s, output)); 
     } 

     else output.append(one.commands(s)); 
    } 
    else output.append(one.commands(s)); 
} 

相反,附加的一切我都希望使用時間類似於我的「slowPrint」方法。

希望這有一些道理,任何幫助將不勝感激。

回答

5

兩個A Timer的基本價值觀是

  1. 延遲
  2. ActionListener

如果您創建slowPrint方法內的計時器,它的引用保留到這一點很重要,所以你可以稍後停下來。因此,您必須稍後添加ActionListener。在ActionListener裏面,你可以通過一個額外的變量跟蹤當前的文本位置(忘記for循環)。然後,您只需手動檢查是否所有文本都已打印完畢,並相應停止計時器。

如果您想延遲也發生在最初,請致電timer.setInitialDelay(delay)

GIF


slowPrint方法實施例修改:

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.IOException; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 
import javax.swing.Timer; 

public class Foo { 

    private JTextField input; 
    private JTextArea output; 

    public static void main(String[] args) throws IOException { 
     EventQueue.invokeLater(() -> new Foo().createAndShowGUI()); 
    } 

    public void createAndShowGUI() { 
     output = new JTextArea(); 
     output.setEditable(false); 

     input = new JTextField(); 
     input.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       slowPrint("This is a test answer.\n", 100); 
      } 
     }); 

     JPanel contentPane = new JPanel(new BorderLayout(5, 5)); 
     contentPane.add(input, BorderLayout.NORTH); 
     contentPane.add(output); 

     JFrame frame = new JFrame("Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setContentPane(contentPane); 
     frame.setSize(800, 600); 
     frame.setVisible(true); 
    } 

    public void slowPrint(String message, int millisPerChar) { 
     input.setEditable(false); 
     input.setFocusable(false); 

     Timer timer = new Timer(millisPerChar, null); 
     timer.addActionListener(new ActionListener() { 
      int counter = 0; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       output.append(String.valueOf(message.charAt(counter++))); 
       output.setCaretPosition(output.getDocument().getLength()); 
       if (counter >= message.length()) { 
        timer.stop(); 
        input.setEditable(true); 
        input.setFocusable(true); 
        input.requestFocusInWindow(); 
       } 
      } 
     }); 
     timer.start(); 
    } 

}