繁体   English   中英

使用Timer实现JTextArea中的打字机效果?

[英]Using Timer to achieve typewriter Effect in JTextArea?

我正在制作一款文字冒险游戏,遇到了一个问题,无法以我想要的方式显示部分文字。 输入一些单词时,玩家可以启动新房间的介绍。 我希望此介绍具有“打字机”效果。 此事件将需要在我的程序ActionPerformed方法中发生。 例如,当用户键入“ Move”然后按Enter时,我希望结果文本一次打印一个字符。

这是我在ActionPerformed之外使用的当前方法来实现此效果:

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);
  }

我如何获得与Timer类一起使用的类似方法,以免妨碍我的线程更新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”方法的内容。

希望这是有道理的,任何帮助将不胜感激。

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();
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM