2016-02-15 2 views
0

У меня есть пользовательский образ заката в качестве фона в программе Java. Это JFrame с JPanel, а JPanel - фон захода солнца. Невозможно ли рисовать или рисовать изображения моего листа спрайтов поверх фона? Должен ли я использовать основные цвета, в которых я могу выбрать внутри программы, например, background (Color.BLACK) ;? Я хотел использовать пользовательское изображение в качестве фона и рисовать поверх фона, как если бы это был холст или панель, которую я планирую использовать. Я хочу, чтобы моя игра работала поверх этого. Добавление другого JPanel просто охватывает все.Проблемы с дисплеями

+0

Есть несколько. Вы можете просто нарисовать поверх фона через метод paintComponent панели или использовать другую панель и «BorderLayout», покрасить спрайты на второй панели и добавить вторую к первой. Помните, что «Canvas» и «Panel» были компонентами на основе AWT, которые не прозрачны (они непрозрачны, всегда) – MadProgrammer

ответ

2

Вы могли бы ...

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

Background

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       BackgroundPane backgroundPane = new BackgroundPane(); 
       backgroundPane.setLayout(new BorderLayout()); 
       backgroundPane.add(new SpitePane()); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(backgroundPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class BackgroundPane extends JPanel { 

     private BufferedImage bgImg; 

     public BackgroundPane() { 
      try { 
       bgImg = ImageIO.read(...); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return bgImg == null ? new Dimension(200, 200) : new Dimension(bgImg.getWidth(), bgImg.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int x = (getWidth() - bgImg.getWidth())/2; 
      int y = (getHeight() - bgImg.getHeight())/2; 
      g2d.drawImage(bgImg, x, y, this); 
      g2d.dispose(); 
     } 

    } 

    public class SpitePane extends JPanel { 

     private BufferedImage sprite; 

     public SpitePane() { 
      try { 
       sprite = ImageIO.read(...); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
      setOpaque(false); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int x = (getWidth() - sprite.getWidth())/2; 
      int y = (getHeight() - sprite.getHeight())/2; 
      g2d.drawImage(sprite, x, y, this); 
      g2d.dispose(); 
     } 

    } 
} 

Но проблема есть, вы на самом деле не достигаете какой-либо эффективности, когда вы обновляете SpritePane, ему необходимо нарисовать BackgroundPane (из-за того, как работают краска и прозрачные контейнеры)

Вы могли бы ...

Просто покрасить спрайты непосредственно над фоном, в то же время ...

Это произведет тот же результат, как и выше ...

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       GamePane backgroundPane = new GamePane(); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(backgroundPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class GamePane extends JPanel { 

     private BufferedImage bgImg; 
     private BufferedImage sprite; 

     public GamePane() { 
      try { 
       bgImg = ImageIO.read(...); 
       sprite = ImageIO.read(...); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return bgImg == null ? new Dimension(200, 200) : new Dimension(bgImg.getWidth(), bgImg.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int x = (getWidth() - bgImg.getWidth())/2; 
      int y = (getHeight() - bgImg.getHeight())/2; 
      g2d.drawImage(bgImg, x, y, this); 

      x = (getWidth() - sprite.getWidth())/2; 
      y = (getHeight() - sprite.getHeight())/2; 
      g2d.drawImage(sprite, x, y, this); 
      g2d.dispose(); 
     } 

    } 
} 

сейчас , с небольшим количеством умной работы, это может быть фактически более эффективным, если вы только перекрасите области, которые изменились;)

AWT против Swing

Итак, вы продолжаете говорить о Canvas/Panel и JPanel, вам необходимо знать, что эти компоненты работают значительно по-другому друг от друга.

Компоненты AWT (Canvas/Panel) известны как тяжелые весовые компоненты, у них есть собственный нативный аналог, на который они рисуют. Они не могут быть прозрачными и не имеют понятия z-упорядочения (что является проблемой при смешивании с компонентами Swing).

компоненты AWT позволяют вам взять под контроль картины процесса (AKA активная живопись), но исключает возможность когда-либо с помощью каких-либо компонентов Swing, с ними (как свинг имеет собственный процесс окраски)

компоненты Swing, известны как легкие весовые компоненты, они совместно используют собственный родительский окно, в котором они находятся. Они также дважды буферизованы по умолчанию (что является одной из причин использования BufferStrategy с Canvas) и может быть прозрачным. Swing использует так называемый алгоритм пассивного рендеринга, что означает, что диспетчер repaint будет принимать решения о том, что и когда что-то будет нарисовано, вы можете делать запросы о том, чтобы что-то обновлялось, но вы не можете гарантировать, когда это может быть выполнено ,

Ответ на ваш вопрос, это зависит. Вам нужно решить, какие функции у вас есть, и тип работы, которую вы готовы сделать (активная живопись может потребовать некоторую работу для настройки) и компромисс между двумя системами.

Вы могли бы один взглянуть на Painting in AWT and Swing, Performing Custom Painting и BufferStrategy и BufferStrategy and BufferCapabilities для более подробной информации

Смежные вопросы