Java 清除带有基础图像的图形部分
我正在做一个“游戏”,玩家必须点击屏幕上跳动的图像。问题是,屏幕处于黑暗中,鼠标光标是一个“手电筒”,它“照亮”周围的一个小圆圈 我有一个Java 清除带有基础图像的图形部分,java,colors,jpanel,bufferedimage,graphics2d,Java,Colors,Jpanel,Bufferedimage,Graphics2d,我正在做一个“游戏”,玩家必须点击屏幕上跳动的图像。问题是,屏幕处于黑暗中,鼠标光标是一个“手电筒”,它“照亮”周围的一个小圆圈 我有一个JFrame在一个类中,包括: public class GameFrame { public static void main(String[] args) throws IOException { Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); JFrame jf =
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);
}
}
我还有一个类扩展了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)
将使用设置的颜色作为清除区域的“背景”,但我需要一种方法来清除除最后面的JFrame
或JPanel
背景色之外的所有图形
我的最后一个问题有点奇怪,但偶尔当我更改int
的值时,窗口会显示为空白,需要调整大小才能执行任何代码。基本思想是创建一个足够大的矩形来覆盖组件,创建一个椭圆2d
来充当“孔”或“聚光灯”然后从矩形
中减去椭圆E2D
,以便在其上创建一个孔,然后绘制它
- 如果可能,应避免覆盖
绘制
,而应使用绘制组件
,绘制
往往在绘制链中处于较高位置,并伴随着许多复杂情况,最好避免
- 应避免在任何
paintXxx
方法中更改组件或模型的状态。可以出于多种原因调用Paint,其中许多原因您不会实例化。这可能会使您的模型状态处于不一致的状态。相反,您应该使用类似于javax.swing.Timer的东西来调节模型何时更新,只需调用repaint
- 永远不要调用
Thread.sleep
,Threasd.wait
,也不要在事件调度线程的上下文中执行任何长时间运行的循环或I/O操作。Swing是一个单线程环境。也就是说,对UI和事件处理的所有更新都是在单个线程中完成的。如果您执行任何阻止EDT的操作,它将无法处理这些事件并更新UI,直到您停止阻止
- 不要调用
repait
或任何可能从paintXxx
方法中调用重新绘制的方法。这将使你的程序陷入死亡的漩涡,它将消耗你的CPU
有关更多详细信息,请查看
为了更快地获得更好的帮助,请发布一个。对于JPanel
覆盖paintComponent()
而不是paint()
。1-不要使用paint,使用paintComponent,2-不要从paint方法中更改程序状态,3-不要在EDT中睡眠,4-不要调用repaint或任何可能从任何paint方法中调用repaint的方法。您可以通过从背景矩形中减去椭圆并绘制结果来“伪造”此效果
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();
}
}
}
}