在 jlabel 中制作打字机效果

Make a typewriter effect in a jlabel

这是我在 JFrame 中添加的 JPanel,但是每个字母写一个字母的代码在执行时冻结,稍后出现文本,文本不是以这种效果书写的,但我认为它应该可以工作,为什么?

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package vista;

import java.awt.Image;
import javax.swing.ImageIcon;
import static paladins.nut.and.crush.panelver.PaladinsNutAndCrushPanelVer.mainPanel;

public class sceneKonami extends javax.swing.JPanel {

    String ruta = "src/backgrounds/soniabelmont.png";
    String ruta1 = "src/backgrounds/legends.png";
    ImageIcon fondo = new ImageIcon(new ImageIcon(ruta).getImage().getScaledInstance(1280, 720, Image.SCALE_DEFAULT));
    ImageIcon fondo1 = new ImageIcon(new ImageIcon(ruta1).getImage().getScaledInstance(730, 250, Image.SCALE_DEFAULT));
   
    public sceneKonami() {
        initComponents();
        loader();

        

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jButton1 = new javax.swing.JButton();
        texter = new javax.swing.JLabel();
        castlevania = new javax.swing.JLabel();
        background = new javax.swing.JLabel();

        setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jButton1.setText("jButton1");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        add(jButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(240, 370, -1, -1));
        add(texter, new org.netbeans.lib.awtextra.AbsoluteConstraints(184, 77, 1050, 510));
        add(castlevania, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 30, 730, 250));
        add(background, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 0, 1280, 720));
    }// </editor-fold>                        

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
      String message = "Sonia Belmont is waiting, \nShe will appear soon. \nIn a great adventure";
      slowPrint(message);
                                
    }                                        

    public static void slowPrint(String message) {
        
        char[] chars = message.toCharArray();
        for (int i = 0; i < chars.length; i++) {

            texter.setText(texter.getText() + String.valueOf(message.charAt(i)));
            mainPanel.repaint();
            mainPanel.revalidate();
            System.out.println(message.charAt(i));

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel background;
    private javax.swing.JLabel castlevania;
    private javax.swing.JButton jButton1;
    private static javax.swing.JLabel texter;
    // End of variables declaration                   

    private void loader() {
        background.setIcon(fondo);
        castlevania.setIcon(fondo1);
    }
}

当程序 运行 和我按下按钮 运行 类型 writter eefect 时,程序冻结,稍后文本出现

以下是 mre (1) 您想要实现的目标,使用秋千 Timer:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;

public class SwingMain {

    SwingMain() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(new SceneKonami());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new SwingMain();
    }
}

class SceneKonami extends javax.swing.JPanel {

    private int index = 0;
    private javax.swing.Timer timer;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel texter;

    public SceneKonami() {
        initComponents();
    }

    private void initComponents() {

        jButton1 = new javax.swing.JButton();
        texter = new javax.swing.JLabel();
        setLayout(new BorderLayout(5,5));
        jButton1.setText("Type Message");
        jButton1.addActionListener(evt -> jButton1ActionPerformed(evt));
        add(jButton1, BorderLayout.SOUTH);
        add(texter, BorderLayout.NORTH);
        setPreferredSize(new Dimension(400,150));
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        String message = "Sonia Belmont is waiting, \nShe will appear soon. \nIn a great adventure";
        slowPrint(message);
    }

    public void slowPrint(String message) {

        if(timer != null && timer.isRunning()) return;
        index   = 0;
        texter.setText("");

        timer = new javax.swing.Timer(100,new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                texter.setText(texter.getText() + String.valueOf(message.charAt(index)));
                index++;
                if (index >= message.length()) {
                    timer.stop();
                }
            }
        });
        timer.start();
    }
}

(1) 在提问和回答时总是考虑发布 MRE。