一段时间后如何在面板上重新绘制符号?

时间:2020-09-17 17:11:09

标签: java swing

我开始制作一个小型应用程序,但遇到了问题。我不知道如何在面板上的“ for”循环中,在确定的时间(5秒)后绘制一个字符(字符串),以使字符在面板上不会相互重叠,但是该程序不会停止工作,但是会停止!

import javax.swing.*;
import java.awt.*;

public class TestClass {

    private static JFrame frame;
    private static JPanel panel;

    public static void main(String[] args) {

        frame = new JFrame();

        panel = new JPanel() {

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);

                g.setColor(Color.GREEN);
                g.setFont(new Font("ms mincho", Font.ROMAN_BASELINE, 20));

                for (char c = '\u30A0'; c <= '\u30FF'; c++)
  //Here the program should stop for a while, and the next character should not overlap the previous one.
  // I tried using Thread.sleep() and IT DOESN't WORK AS it SHOULD, because the program is interrupted and the panel disappears.
                g.drawString(String.valueOf(c), 0, 20);
            }
        };
        panel.setBackground(Color.BLACK);

        frame.add(panel);

        frame.setSize(600, 800);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

如果您解决了这些问题,则还有另一个问题。在循环中,我每次都必须重新创建JPanel对象并在其上进行绘制。那就不好了。

谢谢)

2 个答案:

答案 0 :(得分:0)

(我不是Swing专家,因此以下答案可能不是最佳选择,欢迎进行任何改进)

据我所知,Swing拥有自己的专用线程,该线程负责绘图组件处理事件。因此,如果您在paintComponent方法中放置过多的逻辑(循环等),它将使该线程无响应,直到完成处理该逻辑为止,这将使它看起来像您的应用程序停止工作了。

要解决此类问题,请使paintComponent打印单个字符(这是简单的逻辑,摆动应该可以快速处理),但同时创建单独的线程,该线程将定期更新保存该字符的变量(并且更新后的角色会建议框架或面板再次重新粉刷自身。)

因此您的代码可能类似于:

class TestClass {

    private static JFrame frame;
    private static JPanel panel;

    private static volatile char charToPrint = '\u30A0';

    public static void main(String[] args) {
        frame = new JFrame();
        panel = new JPanel() {
            Font ms_mincho = new Font("ms mincho", Font.ROMAN_BASELINE, 20);

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.GREEN);
                g.setFont(ms_mincho);
                g.drawString(String.valueOf(charToPrint), 0, 20);
            }
        };
        panel.setBackground(Color.BLACK);
        frame.add(panel);
        frame.setSize(600, 800);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);

        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            if (charToPrint == '\u30FF')//if last character in range
                charToPrint = '\u30A0'; //start over from first
            else
                charToPrint++;          //else set next character

            frame.repaint();            //suggest frame to repaint its component
                                        //probably can be change to panel.repaint()
        }, 0, 100, TimeUnit.MILLISECONDS);
    }
}

答案 1 :(得分:-1)

这是我的解决方案。您必须创建某种线程来 为您倒数时间。我在javax.swing中使用了一个:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.ArrayList;
import javax.swing.Timer;

public class TestClass {

    private static JFrame frame;
    private static JPanel panel;
    private static List<Character> chars = new ArrayList<>();
    private static int currentIndex = 0;

    public static void main(String[] args) {

      // create an array of characters up front...
      for (char c = '\u30A0'; c <= '\u30FF'; c++) {
        chars.add(Character.valueOf(c));
      }

      // delayedPaint() called when timer fires. Updates the index
      // into the character array; resets when necessary. Calls
      // repaint() to redraw the screen...
      ActionListener delayedPaint = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          currentIndex++;
          if (currentIndex == 95) {
            currentIndex = 0;
          }
          panel.repaint();
        }
      };

      // Timer setup...
      Timer timer = new Timer(500, delayedPaint);
      timer.setInitialDelay(1000);
      timer.setDelay(500);
      timer.start();

        frame = new JFrame();

        panel = new JPanel() {

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);

                g.setColor(Color.GREEN);
                g.setFont(new Font("ms mincho", Font.ROMAN_BASELINE, 20));

                // did you want these in a row? I wasn't sure...
                int x = 10;
                int y = 20;
                for (int i = 0; i < currentIndex; i++) {
                  g.drawString(String.valueOf(chars.get(i)), x, y);
                  x += 20;
                  // bumps y to the next row...
                  if (x > panel.getWidth()) {
                    x = 0;
                    y += 20;
                  }
                }
            }
        };
        panel.setBackground(Color.BLACK);

        frame.add(panel);

        frame.setSize(600, 800);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
相关问题