简体   繁体   English

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

[英]How do I redraw symbols on the panel after some time?

I started making a small app on swing and ran into problems.我开始在 Swing 上制作一个小应用程序并遇到了问题。 I do not know how to draw a character (string) in a "for" loop on the panel, AFTER a CERTAIN AMOUNT of TIME(5 seconds), and so that the characters do not overlap each other on the panel, but so that the program does not stop working, but stops!我不知道如何在面板上的“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);
    }
}

If you solve these problems, there is another one.如果你解决了这些问题,还有另一个问题。 In the loop, I will have to re-create the JPanel object each time and draw on it.在循环中,我每次都必须重新创建 JPanel 对象并在其上绘制。 And that's not good.这不好。

Thanks)谢谢)

(I am not Swing guru so below answer may not be optimal, any improvements are welcome) (我不是 Swing 大师,所以下面的答案可能不是最佳答案,欢迎任何改进)

From what I remember Swing has its own dedicated thread which is responsible for drawing components and handling events .我记得 Swing 有自己的专用线程,负责绘制组件处理事件 So if you place too much logic (loops, etc) in paintComponent method it will make that thread unresponsive until it will finish handling that logic which will make it look like your application stopped working.因此,如果您在paintComponent方法中放置太多逻辑(循环等),它将使该线程无响应,直到它完成处理该逻辑,这将使您的应用程序看起来像停止工作。

To solve that kind of problem make paintComponent print single character (that is simple logic which swing should be able to handle quickly) but at the same time create separate thread which will periodically update variable which holds that character (and after updating character will suggest frame or panel to repaint itself again).为了解决这种问题,使paintComponent打印单个字符(这是swing应该能够快速处理的简单逻辑),但同时创建单独的线程,该线程将定期更新保存该字符的变量(并且在更新字符后将建议帧或面板再次重新粉刷)。

So your code can look something like:所以你的代码看起来像:

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

Here's my take on a solution.这是我对解决方案的看法。 You have to create some sort of thread to count down the time for you.您必须创建某种线程来为您倒计时。 I used the one in javax.swing:我在 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);
    }
}

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

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