Я работаю над приложением, в котором все рисую попиксельно. Во время процесса я заметил, что метод paintComponent() определенного JPanel вызывается дважды. Поэтому я создал следующий MCVE , чтобы выяснить, имеет ли он какое-то отношение к другим компонентам, выводимым на экран, или это просто отдельная проблема:

< Сильный > App.java

public class App {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame("Paint test"));
    }
}

< Сильный > MainFrame.java

public class MainFrame extends JFrame {
    private Board mBoard;

    public MainFrame(String title) {
        super(title);

        setMinimumSize(new Dimension(400, 400));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());

        mBoard = new Board();
        add(mBoard, BorderLayout.CENTER);

        setVisible(true);
    }
}

Board.java

public class Board extends JPanel {

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

        System.out.println("CALLED");
    }
}

Но в журнале консоли дважды отображается "CALLED".

Меня особенно интересует paintComponent(), поскольку это метод, в котором работает вся магия приложения, поэтому мне нужно контролировать каждый цикл отрисовки.

Каковы причины этого двойного вызова paintComponent()?

Есть ли другой способ сделать мои рисунки другим способом один раз ? (Я имею в виду, не в paintComponent(), если бы его вызывали дважды, несмотря ни на что)

2
Mohammed Aouf Zouag 30 Дек 2015 в 02:40

2 ответа

Лучший ответ

Почему метод paintComponent вызывается дважды?

Потому что он вызывается всякий раз, когда подключаемый модуль определяет, что это необходимо.

Мне нужно контролировать это поведение.

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

Однако логический подход к этой головоломке состоит в том, чтобы вместо этого отрисовать все в BufferedImage, которое отображается в (ImageIcon, которое отображается в) JLabel. Тогда независимо от того, сколько раз вызывается метод repaint() метки, приложение. по-прежнему нужно только один раз сгенерировать пиксели.

Примеры

  1. Рисование изображения внутри панели

    введите описание изображения здесь

  2. Несколько вызовов paintComponent ()

    введите описание изображения здесь

  3. Рисование кривой каннабиса

    введите описание изображения здесь

4
Community 20 Июн 2020 в 09:12

Прочитав краткое обсуждение в комментариях, у меня есть предложение. Подготовьте объект Shape и сохраните его как ресурс. Это сэкономит вычисления во время выполнения. Когда программа запускается, загрузите файл в отдельном потоке (параллельно с загрузкой графического интерфейса), а затем просто раскрасьте этот объект. Просто покраска не должна стоить дорого, поэтому даже если ее вызовут несколько раз, проблем не должно быть.

0
user1803551 30 Дек 2015 в 02:08