Clear portion of graphics with underlying image

后端 未结 1 1330
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-22 01:09

I\'m making a \'game\' of sorts where the player has to click on an image bouncing around the screen. The catch is that the screen is in darkness and the mouse cursor is a \

相关标签:
1条回答
  • 2020-12-22 01:53

    The basic idea is to create a Rectangle big enough to cover the component, create a Ellipse2D to act as the "hole" or "spot light" and subtract the Ellipse2D from Rectangle so as to create a hole in it, then paint it.

    • You should avoid overridding paint where possible and instead, use paintComponent, paint tends to be to high in the paint chain and comes with a number of complications which are best avoided
    • You should avoid changing the state the state of your component or model within any paintXxx method. Paint can be called for any number of reasons, many of which you won't instantiate. This could be putting your models state into a inconsistent state. Instead, you should using something like a javax.swing.Timer to regulate when the model is updated and simply call repaint
    • Don't ever call Thread.sleep, Threasd.wait or perform any kind of long running loop or I/O operation within the context of the Event Dispatching Thread. Swing is a single threaded environment. That is, all the updates to the UI and event processing are done from within a single thread. If you do anything that blocks the EDT, it will be unable to process these events and update the UI until you stop blocking...
    • Don't call repaint or any method that might invoke a repaint from within in paintXxx method. This will place your program into a spiral of death that will see it consume your CPU...

    For more details, take a look at...

    • Performing Custom Painting
    • Concurrency in Swing

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.RenderingHints;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Area;
    import java.awt.geom.Ellipse2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Spotlight {
    
        public static void main(String[] args) {
            new Spotlight();
        }
    
        public Spotlight() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public static final int RADIUS = 80;
    
            private BufferedImage img;
            private Point mousePoint;
    
            public TestPane() {
                try {
                    img = ImageIO.read(new File("C:\\hold\\thumbnails\\Rampage_Small.png"));
                } catch (IOException ex) {
                    Logger.getLogger(Spotlight.class.getName()).log(Level.SEVERE, null, ex);
                }
    
                addMouseMotionListener(new MouseAdapter() {
                    @Override
                    public void mouseMoved(MouseEvent e) {
                        mousePoint = e.getPoint();
                        repaint();
                    }
                });
            }
    
            @Override
            public Dimension getPreferredSize() {
                return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (img != null) {
                    Graphics2D g2d = (Graphics2D) g.create();
                    g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                    g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                    g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    
                    int x = (getWidth() - img.getWidth()) / 2;
                    int y = (getHeight() - img.getHeight()) / 2;
    
                    g2d.drawImage(img, x, y, this);
    
                    x = mousePoint == null ? getWidth() / 2 : mousePoint.x;
                    y = mousePoint == null ? getHeight() / 2 : mousePoint.y;
    
                    Rectangle rect = new Rectangle(0, 0, getWidth(), getHeight());
                    Ellipse2D spot = new Ellipse2D.Float(
                            (float) x - (RADIUS / 2f),
                            (float) y - (RADIUS / 2f),
                            (float) RADIUS,
                            (float) RADIUS);
    
                    Area area = new Area(rect);
                    area.subtract(new Area(spot));
    
                    g2d.setColor(Color.BLACK);
                    g2d.fill(area);
    
                    g2d.dispose();
                }
            }
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题