Java рисование графики JPanel, с использованием массива байтов, мигает белым

#java

#java

Вопрос:

Итак, я пытаюсь обновить JPanel, используя массив байтов с указанным байтом / цветом, это очень простая версия. Когда я запускаю программу, она становится белой на полсекунды, затем становится правильного цвета, а затем через 1 секунду она снова становится белой, я пытался распечатать текущий цвет, и иногда он меняется на ‘0’. Что я делаю не так?

 import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {
public static Random ran = new Random();
public static byte[] buffer;
public static int num = 0;
public static JFrame frame = new JFrame();
public static JPanel panel = new JPanel() {
    private static final long serialVersionUID = 1L;

    @Override
    public void paint(Graphics g) {
        num = 0;
        byte[] current_buffer = buffer.clone();

        for (int y = 0; y < panel.getHeight(); y  ) {
            for (int x = 0; x < panel.getWidth(); x  ) {
                g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
                g.fillRect(x, y, 1, 1);
                num  ;
            }
        }

    }
};

public static void main(String[] args) {
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(1200, 800);
    frame.setLocationRelativeTo(null);
    frame.setContentPane(panel);
    frame.setResizable(false);
    frame.setVisible(true);
    engine.run();
}

public static boolean running = true;
public static Thread engine = new Thread() {
    @Override
    public void run() {
        buffer = new byte[panel.getWidth() * panel.getHeight()];
        for (int i = 0; i < buffer.length; i  ) {
            buffer[i] = (byte) 34;
        }
        while (running) {
            panel.repaint(10L);
        }
    }
};
 

}

Комментарии:

1. Используйте paintComponent вместо paint

2. Он по-прежнему не работает: (мигает на секунду, а затем становится белым

3. Используйте SwingWorker вместо потока или используйте SwingUtilities.invokeLater() для вызова repaint в очереди событий Swing. Вы также можете использовать таймер swing для обновления каждые 30 или 60 изображений в секунду

4. Это тоже не работает.

Ответ №1:

Не совсем понимаю вашу логику:

     for (int i = 0; i < buffer.length; i  ) {
        buffer[i] = (byte) 34;
    }
 

Вы присваиваете буферу то же значение.

Затем вы создаете цветной объект, используя то же значение.

  g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
 

Таким образом, каждый пиксель будет одного цвета.

И поскольку буфер всегда создается с одинаковыми значениями, цвет не изменится.

Кроме того, зачем вам использовать

 byte[] current_buffer = buffer.clone();
 

Вы просто используете значения в буфере, а не обновляете значения в буфере, поэтому я не вижу причин для клонирования.

Не используйте поток с циклом while. Для анимации вы должны использовать Swing Timer . При срабатывании таймера вы обновляете значения в буфере, а затем вызываете repaint().

Когда я запускаю программу, она становится белой на полсекунды, затем становится правильного цвета, а затем через 1 секунду она снова становится белой,

Я не вижу такого поведения.

  1. он мигает светлым цветом
  2. он остается окрашенным в более темный цвет

Вышесказанное имеет смысл, потому что:

  1. Ваш метод paintCompnent() не вызывает super.paintComponent(…), чтобы убедиться, что фон очищен
  2. Массив не инициализируется никакими значениями при его создании, поэтому значение по умолчанию будет равно 0.
  3. После того, как поток возьмет верх, массив всегда будет содержать одно и то же значение, поэтому будет окрашен в тот же цвет.

Что вы ожидаете от этого?

Комментарии:

1. как я уже сказал, это всего лишь небольшая версия; Я знаю, что все цвета будут одинаковыми; я просто создал эту маленькую версию движка, чтобы попытаться заставить ее работать; Я не буду делать анимацию на этом движке, только обновляю и делаю несколько других математических вещей в этой теме,а затем создайте другой поток с полуфиксированной частотой обновления для анимации

2. Анимация должна выполняться с помощью таймера Swing, а не потока! Обновления состояния компонента должны выполняться в EDT, поэтому вам нужен таймер, а не поток. См. Редактирование.