Java: изображение, графика и панель - PullRequest
0 голосов
/ 26 августа 2018

Я пытаюсь создать анимацию на Java, но у меня возникают проблемы с пониманием DoubleBufferImage и DoubleBufferGraphics. Я понимаю о последовательностях update (), render () и paint (). Тем не менее, в методах каждого я не могу понять, как это рисуется. Вот коды.

  1. gameUpdate () // Я просто пропущу часть обновления, потому что сначала мне нужно понять фон.

  2. gameRender ()

    private void gameRender() {
        if (DoubleBufferImage == null) {
            System.out.println("The Image is null: Error occurence");
            DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
        }
    
        DoubleBufferGraphic = DoubleBufferImage.getGraphics();
    
        DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
        DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);
    
        DoubleBufferGraphic.setColor(Color.BLUE);
        DoubleBufferGraphic.setFont(font);
        DoubleBufferGraphic.drawString("Average FPS/UPS: " + 
                df.format(averageFPS) + df.format(averageUPS), 10, 10);
    }
    
  3. краска ()

    public void paintScreen() {
        Graphics g;     
        try {           
            g = this.getGraphics();
            if ((g != null) && (DoubleBufferImage != null)) {               
                g.drawImage(DoubleBufferImage, 0, 0, null);         
            }           
            Toolkit.getDefaultToolkit().sync();     
        } catch (Exception e) {         
            System.out.println("Graphics context error: " + e);     
        }   
    }
    

Существует также метод paintComponent, который переопределяется из Jpanel.

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (DoubleBufferImage != null) {
        g.drawImage(DoubleBufferImage, 0, 0, null);
    }
}

Вот мой вопрос. Запуск идет как обновление -> визуализация -> и рисование Однако, как вы можете видеть из рендера, они использовали графику для рисования. Но все ли это нарисовано в DoubleBufferImage? Экземпляр изображения похож на экземпляр панели? Я имею в виду, это просто добавляется к кадру? Поскольку это система двойного буферизации, я хочу знать, какие методы рисуют напрямую, а какой - метод, который рисует заранее. Наконец, в процессе работы нет кода, что это изображение или графика, которые мы сделали, будут добавлены на панель. Я просто хочу знать время, когда рисуется BufferedImage. Пожалуйста помоги! Я не могу загрузить весь код, поэтому я не уверен, что вы, ребята, можете понять: (

1 Ответ

0 голосов
/ 26 августа 2018

Хорошо, значит, вы, кажется, бьетесь против некоторой дезинформации и недопонимания. Возможно, вам следует начать с рассмотрения чего-то вроде paintComponent () против paint () и JPanel против Canvas в графическом интерфейсе типа кисти

В AWT / Swing есть как минимум два способа выполнения нестандартной живописи, каждый со своими плюсами и минусами.

Вы можете использовать paintComponent, который "зацепит" систему рисования, используемую Swing. Swing использует «пассивную» систему рендеринга. Это означает, что вы не можете контролировать, когда что-то раскрашивается, система рисования принимает эти решения и затем (косвенно) вызывает paintComponent вашего компонента, чтобы вы могли выполнять обновления.

Другой механизм (BufferStrategy) использует «активную» систему рендеринга, которая дает вам полный контроль над процессом рисования.

Как правило, их нельзя смешивать. Swing имеет свою собственную систему рисования и не будет хорошо работать с BufferStrategy, поэтому это означает, что если вы хотите использовать компоненты Swing в качестве выходных данных, вы не можете.

Но это не ответит на ваш вопрос, или не напрямую

Давайте попробуем сломать его

gameRender

private void gameRender() {
    if (DoubleBufferImage == null) {
        System.out.println("The Image is null: Error occurence");
        DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
    }

    DoubleBufferGraphic = DoubleBufferImage.getGraphics();

    DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
    DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);

    DoubleBufferGraphic.setColor(Color.BLUE);
    DoubleBufferGraphic.setFont(font);
    DoubleBufferGraphic.drawString("Average FPS/UPS: " + 
            df.format(averageFPS) + df.format(averageUPS), 10, 10);
}

В данный момент DoubleBufferImage кажется BufferedImage, поэтому, когда вызывается gameRender, он проверяет, существует ли буфер, и создает его по мере необходимости. Затем он берет ссылку на контекст DoubleBufferImage s Graphics и подготавливает ее для рендеринга, удаляя то, что было ранее нарисовано в нем.

Краткий обзор Graphics

Graphics - это абстрактный слой поверх базового конвейера рендеринга, который часто реализуется с использованием OpenGL или DirectX в зависимости от системы. Он обеспечивает общий уровень, на котором графические операции могут выполняться независимо от системы

paintScreen

public void paintScreen() {
    Graphics g;     
    try {           
        g = this.getGraphics();
        if ((g != null) && (DoubleBufferImage != null)) {               
            g.drawImage(DoubleBufferImage, 0, 0, null);         
        }           
        Toolkit.getDefaultToolkit().sync();     
    } catch (Exception e) {         
        System.out.println("Graphics context error: " + e);     
    }   
}

Это меня беспокоит, так как у меня нет контекста, но this.getGraphics(), кажется, берет ссылку на контекст Graphics компонента и рисует DoubleBufferImage к нему.

Это опасно и не рекомендуется. getGraphics возвращает снимок компонента с момента его последней закраски, который можно закрасить в любое время, когда компонент закрашивается снова.

Вы должны при первой же возможности избавиться от этого метода.

paintComponent

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (DoubleBufferImage != null) {
        g.drawImage(DoubleBufferImage, 0, 0, null);
    }
}

Как упомянуто выше, paintComponent является предпочтительным методом подключения системы окраски Swing. Все, что он делает, это рисует DoubleBufferImage, хотя на самом деле он должен читать g.drawImage(DoubleBufferImage, 0, 0, this);

Итак, что все это делает?

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

Однако, как вы можете видеть из рендера, они использовали графику для рисования. Но все ли это нарисовано в DoubleBufferImage? Экземпляр изображения похож на экземпляр панели?

Нет. Компонент - это объект, который имеет ряд свойств. Одна из его задач - рисовать его состояние, что выполняется с помощью различных методов рисования, которым передается контекст Graphics, который присоединяется к нативному узлу и в конечном итоге будет отображаться на экране (или принтере).

A BufferedImage - это просто изображение. Контекст Graphics - это просто простое средство рисования. Затем он может быть сохранен в файл или, как в данном случае, нарисован в контексте компонента (через Graphics).

Как я уже говорил выше, Graphics - это просто абстрактный слой, который позволяет вам выполнять операции рисования для множества различных мест назначения, экрана, принтеров, изображений и т. Д. *

Я имею в виду, это просто добавляется к кадру?

Нет. Это не компонентный класс

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

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

Дальнейшее чтение ...

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