Вещи, нарисованные paintComponent () исчезают после вызова repaint () - PullRequest
0 голосов
/ 06 февраля 2020

On Head First Java В книге мы видим небольшую анимацию, и я пытаюсь нарисовать анимацию, которая очерчивает диагональную линию. Я делаю это, используя метод paintComponent () и рисуя овал в точке x, y (значения, которые обновляются каждый раз через l oop). Почему я теряю ранее нарисованные овалы? Согласно книге, я должен получить мазок на экране, где ранее нарисованные овалы не потеряны. Это нужно исправить, добавив в метод paintComponent () белый фон каждый раз, когда вызывается repaint (), но вместо этого я не получаю «ошибку». Почему это так и как мне сохранить ранее нарисованные овалы на панели?
Используя JDK 13.0.2 и Ma c OSX Catalina

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

public class SimpleAnimation {

    int x = 70;
    int y = 70;

    public static void main(String[] args) {
        SimpleAnimation gui = new SimpleAnimation();
        gui.go();
    }

    public void go() {
        JFrame frame = new JFrame();
        MyDrawPanel drawPanel = new MyDrawPanel();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(drawPanel);
        frame.setSize(300,300);
        frame.setVisible(true);

        for (int i = 0; i < 130; i++) {
            x++;
            y++;
            drawPanel.repaint();
            try {
                Thread.sleep(25);
            } catch (Exception ex){};

        }
    }
    class MyDrawPanel extends JPanel {

        public void paintComponent(Graphics g) {
            g.setColor(Color.orange);
            g.fillOval(x,y,50,50);
        }
    } // close inner class
} // close outer class

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Это то, что предотвращает мазок овалов?

class MyDrawPanel extends JPanel {
    public void paintComponent(Graphics g) {
        g.setColor(Color.orange);
        g.fillOval(x,y,50,50);
    }

Код должен быть:

class MyDrawPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // added
        g.setColor(Color.orange);
        g.fillOval(x,y,50,50);
    }

Вам нужно super.paintComponent(g), чтобы очистить фон панели перед выполнением заказной покраски.

Да, отличная книга. Вывод, который я получаю с кодом как есть, является «исправленной версией»

Редактировать:

Книга верна. Вы должны понимать, как работает EDT. При запуске приложения код, вызываемый в методе main (), выполняется в отдельном потоке. События свинга и рисование выполняются в потоке рассылки событий (EDT). Так что вызов sleep () в методе go () НЕ должен влиять на рисование круга, и вы должны увидеть мазок. Если после завершения l oop вы видите только один овал, то это означает, что ваша IDE или платформа запускают код в методе main () EDT, что не является нормальным.

Вы можете проверьте мое вышеупомянутое утверждение, добавив:

System.out.println( SwingUtilities.isEventDispatchThread() );

к вашему l oop, чтобы увидеть, выполняется ли оно на EDT или нет.

0 голосов
/ 06 февраля 2020

Эй, я вижу, вы тоже читали книгу "Первая в голове" Java, хорошая книга, не так ли?

У меня была такая же проблема, когда я изучал главу 12 в той же книге .

Узнав о потоках в главе 15, я понял, почему овалы не «размазываются» по экрану.

Итак, прежде всего, о методе repaint().

Вызов метода repaint() не вызывает мгновенно paintComponent(Graphics g) в JPanel. Вместо этого он планирует вызов в поток рассылки событий для последующего использования.

Я не уверен, какой вывод вы получаете, поскольку вы не сообщили нам об этом.

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

Если это так, то программа работает так. Вы запускаете l oop 150 раз, поэтому вы звонили repaint() 150 раз. Однако, как я уже говорил, repaint() вызывает только расписание в потоке диспетчеризации событий, вместо того, чтобы мгновенно запускать paintComponent(Graphics g).

Это означает, что for l oop завершается до того, как paintComponent(Graphics g) фактически получил вызов. Скорее всего, почему вы не получаете «Ошибка» в книге.

Как вы получаете «Ошибка»?

Попробуйте оставить нить спать дольше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...