簡體   English   中英

清除帶有基礎圖像的圖形部分

[英]Clear portion of graphics with underlying image

我正在制作一種“游戲”,玩家必須單擊在屏幕上彈跳的圖像。 問題是屏幕處於黑暗中,鼠標光標是“手電筒”,“點亮”了周圍的小圓圈。

我在一個包含以下類的類中有一個JFrame

public class GameFrame {

public static void main(String[] args) throws IOException {

    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    JFrame jf = new JFrame("Flashlight Game");
    jf.setVisible(true);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setSize(d);
    jf.setLocationRelativeTo(null);
    GamePanel gp = new GamePanel();
    jf.add(gp);
}

}

我還有另一個extends JPanel類。 以下是與我的問題有關的字段:

private Point mouse; //location set by a MouseMotionListener
private BufferedImage myImage;
private int imageX;
private int imageY;
private int imageSpeedX;
private int imageSpeedY;

我的第一個問題在於手電筒。 paint方法中,我將圖形背景顏色設置為面板背景顏色,並使用clearRect方法清除鼠標光標周圍的區域。

public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    super.paint(g2);
    checkBounce();
    move();
    g2.drawImage(myImage, imageX, imageY, null);
    g2.setColor(Color.BLACK);
    g2.fillRect(0, 0, this.getWidth(), this.getHeight());
    g2.setBackground(Color.WHITE);
    g2.clearRect((int) mouse.getX() - 25, (int) mouse.getY() - 25, 50, 50);
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    repaint();
}

實際上,這里有兩個問題。 1.)由於手電筒不呈矩形發光,我該如何創建clearOval效果;以及2.)如何使反射圖像通過手電筒光束顯示? 我知道調用g2.setBackground(Color.WHITE)會將設置的顏色用作清除區域的“背景”,但是我需要一種方法來清除所有圖形,但最后一個JFrameJPanel背景顏色除外。

我的最后一個問題很奇怪,但是有時候我更改int的值時,該窗口將顯示為空白,需要調整大小才能執行任何代碼。

基本思想是創建一個足以覆蓋組件的Rectangle ,創建一個Ellipse2D以充當“孔”或“聚光燈”,並從Rectangle減去Ellipse2D以便在其中創建一個孔,然后對其進行繪制。

  • 你應該避免overridding paint在可能的情況,而是使用paintComponentpaint往往是高在內線鏈,並配有一些並發症,其最好避免
  • 您應該避免在任何paintXxx方法中更改組件或模型的狀態。 可以出於多種原因調用Paint,其中許多您不會實例化。 這可能會使您的模型狀態進入不一致狀態。 相反,您應該使用javax.swing.Timer類的東西來調節模型的更新時間,並只需調用repaint
  • 不要在Event Dispatching Thread的上下文中調用Thread.sleepThreasd.wait或執行任何長時間運行的循環或I / O操作。 Swing是一個單線程環境。 也就是說,對UI的所有更新和事件處理都是在單個線程內完成的。 如果您執行任何阻止EDT的操作,在停止阻止之前,它將無法處理這些事件並更新UI。
  • 不要在paintXxx方法中調用repaint或任何可能從內部調用重繪的方法。 這將使您的程序陷入死機,這將消耗您的CPU ...

有關更多詳細信息,請看...

在此處輸入圖片說明

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM