Having issues with displays

淺唱寂寞╮ 提交于 2019-12-12 03:53:53

问题


I have a custom image of a sunset as my background in a Java program. It is a JFrame with a JPanel and the JPanel houses the sunset background. Is there no way I can draw or paint the images of my sprite sheet on top of the background? Will I have to use basic colors in which I can pick inside the program such as background(Color.BLACK);? I wanted to use the custom image as my background and draw on top o the background as if it was the Canvas or Panel I am planning to use. I want my game to run on top of that. Adding another JPanel just covers everything.


回答1:


You could...

Make a JPanel which paints the sprites, make it transparent and add it to the background panel...

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();
        }

    }
}

But, the problem is, you're not really achieving any efficiency, when you update the SpritePane, it needs to paint the BackgroundPane (because of the way the painting and transparent containers work)

You could...

Simply paint your sprites directly over the background at the same time...

This will generate the same result as above...

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();
        }

    }
}

Now, with a little bit of clever work, this could actually be more efficient, assuming you only repaint the areas which have changed ;)

AWT vs Swing

Okay, so you keep talking about Canvas/Panel and JPanel, you need to know that these components operate significantly differently from each other.

AWT components (Canvas/Panel) are known as heavy weight components, they have their own native peer onto which they paint. They can't be transparent and don't have a concept of z-ordering (which is a problem when mixed with Swing components).

AWT components do allow you to take control of the painting process (AKA active painting), but that precludes the possibility of ever using ANY Swing components with them (as Swing has it's own painting process)

Swing components are known as light weight components, they share the native peer of the parent window which they reside. They are also double buffered by default (which is one of the reasons for using a BufferStrategy with a Canvas) and can be transparent. Swing uses what's known as a passive rendering algorithm, meaning that the repaint manager will be making decisions about what and when something will be painted, you can make requests for something to be updated, but you can't guarantee when it might be carried out.

The answer to your question is, it depends. You need to decide which features you must have and the type of work you're willing to do (active painting can take some work to get setup) and the trade offs between the two systems.

You might one to take a look at Painting in AWT and Swing, Performing Custom Painting and BufferStrategy and BufferStrategy and BufferCapabilities for more details



来源:https://stackoverflow.com/questions/35402007/having-issues-with-displays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!