我正在尝试创建一个Java程序,以使字母在JLabel中一次出现一个

时间:2018-08-07 14:51:33

标签: java

我试图在Java中创建一个程序,使一个字符串的字母一次出现在JLabel中,但是文本一次只出现一次。 Thread.Sleep();上的延迟越长,显示时间就越长。我认为正在发生的事情是先将其全部写出,然后将其打印到Label中,但是我仍然不知道该如何解决。代码在这里:

package uiTesting;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class ScrollingText extends JFrame {

private JPanel contentPane;

        //Variables and values

public static String ThingToBePrinted = "You look down the gigantic hallway, the cold breath of spirits breathing down your neck. "
        + "Its nothing you haven't felt before. The spirits of those long past were always closer here, where many of them met"
        + " their end. Maybe you would be one of them, someday. But not today. Today, there was still too much to be done to rest.";

public static String ThingPrinted = "";

public static int Mili = 100;

public String html1 = "<html><body style='width: ";

public String html2 = "px'>";
/**
 * Launch the application.
 */
public static void main(String[] args) {
    System.out.println(ThingToBePrinted.length());
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                ScrollingText frame = new ScrollingText();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}


/**
 * Create the frame.
 */
public ScrollingText() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 719, 504);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);
        //The only Label
    JLabel Scrolling_L1 = new JLabel("");
    Scrolling_L1.setFont(new Font("Tahoma", Font.PLAIN, 15));
    Scrolling_L1.setVerticalAlignment(SwingConstants.TOP);
    Scrolling_L1.setBounds(10, 11, 693, 354);
    contentPane.add(Scrolling_L1);

        //The only Button
    JButton Master_B1 = new JButton("Print Text");
    Master_B1.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try {
                //scrolling function
                for (int i = 0; i < ThingToBePrinted.length(); i++) {
                    String x = String.valueOf(ThingToBePrinted.charAt(i));
                    ThingPrinted = ThingPrinted + x;
                    Scrolling_L1.setText(html1 + "500" + html2 + ThingPrinted); //Html for wrapping text
                    Thread.sleep(Mili); //Delay between letters
                }
            }catch (Exception e){
                JOptionPane.showMessageDialog(null, "Error");
            }
        }
    });
    Master_B1.setFont(new Font("Tahoma", Font.PLAIN, 25));
    Master_B1.setBounds(164, 385, 375, 70);
    contentPane.add(Master_B1);

}
}

在此,我非常感谢任何解决方案,我已经排查了好几个小时了

2 个答案:

答案 0 :(得分:1)

您的问题与Swing中的并发工作方式有关。一种(不完善的)解决方案是使用SwingWorker。您可以将动作监听器更改为此:

Master_B1.addActionListener(event -> {
    SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
        @Override
        protected String doInBackground() throws InterruptedException {

            for (int i = 0; i < ThingToBePrinted.length(); i++) {
                ThingPrinted += ThingToBePrinted.charAt(i);
                Scrolling_L1.setText(html1 + "500" + html2 + ThingPrinted); // Html for wrapping text
                Thread.sleep(Mili); //Delay between letters
            }

            return null;
        }
    };

    worker.execute();

});

阅读本教程:Lesson: Concurrency in Swing以更好地理解该主题。 (您可能还希望大致了解Java中的并发性,例如,参见this tutorial。)

答案 1 :(得分:1)

这是因为您正在从事件处理程序更新UI线程本身中的JLabel。更好的方法是在事件处理程序中启动新线程,然后从该新线程更新JLabel。以下是您需要在代码中使用的部分。我已经测试过了,它可以正常工作。

Master_B1.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try { // Start new thread here for updating JLabel.
                new Thread() {
                    public void run() {
                         //scrolling function
                        for (int i = 0; i < ThingToBePrinted.length(); i++) {
                            String x = String.valueOf(ThingToBePrinted.charAt(i));
                            ThingPrinted = ThingPrinted + x;
                            Scrolling_L1.setText(html1 + "500" + html2 + ThingPrinted); //Html for wrapping text
                            try {
                                Thread.sleep(Mili); // Delay between letters
                            } catch (Exception e) {
                            }
                        }
                    }
                }.start();
            }catch (Exception e){
                JOptionPane.showMessageDialog(null, "Error");
            }
        }
});