首先,您应该避免覆盖顶级容器的paint,而是使用从JComponent 扩展的东西(如JPanel)并覆盖它的paintComponent。
有很多原因,但在您的情况下,框架包含位于可视区域内的装饰。
基本过程是检查边缘情况...
if (box.x + box.width > getWidth() - 1) {
// The boxes right edge is beyond the right edge of it's container
} else if (box.x < 0) {
// The boxes left edge is beyond the left edge of it's container
}
这会检查box 的右边缘是否超出容器右边缘以及box 的左边缘是否超出容器的左边缘。
将垂直检查也包括在内是一个简单的过程。
更新示例
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.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Move {
public static void main(String[] args) {
new Move();
}
public Move() {
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 {
private Rectangle box;
private int xDelta;
public TestPane() {
box = new Rectangle(0, 75, 50, 50);
xDelta = 4;
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
box.x += xDelta;
if (box.x + box.width > getWidth() - 1) {
box.x = getWidth() - box.width;
xDelta *= -1;
} else if (box.x < 0) {
box.x = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.fill(box);
g2d.dispose();
}
}
}
从 OP 的示例代码更新
马上,很多事情让我担心......
- 覆盖
paint
- 在
paint方法中调用Thread.sleep
- 从
paint 方法中调用repaint
- 在
paint 方法中创建一个新的Rectangle
- 对
place变量的依赖
查看Performing Custom Painting 了解有关在 Swing 中绘画的更多详细信息
您不应阻塞或执行长时间运行的事件调度线程处理,这将阻止 EDT 处理(除其他外)绘制请求和新事件。通过在 paint 方法中调用 Thread.sleep,您可以阻止 Swing 更新屏幕。
查看Concurrency in Swing了解更多详情。
在paint 方法中调用repaint(或任何可能调用repaint 的方法)肯定会消耗您的CPU 周期。
您可能需要查看Painting in AWT and Swing 以了解有关 Swing 中绘制过程的更多详细信息
通过在paint 方法中创建新的Rectangle,您将丢弃Timer 所做的任何更改,从而有效地阻止您的矩形有效移动...
place 方法不是必需的。动画是随时间变化的幻觉,因此使用了Timer 和xDelta。
根据您的代码示例更新
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.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Move {
public static void main(String[] args) {
new Move();
}
public Move() {
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 Main());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Main extends JPanel {
public static int place = -350;
public Rectangle rect;
public int xDelta;
public Main() {
rect = new Rectangle(0, 75, 50, 50);
xDelta = 4;
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rect.x += xDelta;
if (rect.x + rect.width > getWidth() - 1) {
rect.x = getWidth() - rect.width;
xDelta *= -1;
} else if (rect.x < 0) {
rect.x = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Random r = new Random();
int r1;
r1 = r.nextInt(5);
if (r1 == 0) {
g2d.setColor(Color.WHITE);
} else if (r1 == 1) {
g2d.setColor(Color.BLUE);
} else if (r1 == 2) {
g2d.setColor(Color.RED);
} else if (r1 == 3) {
g2d.setColor(Color.GREEN);
} else if (r1 == 4) {
g2d.setColor(Color.PINK);
} else {
g2d.setColor(Color.CYAN);
}
// place += 50;
// rect = new Rectangle(place, 100, 300, 200);
g2d.draw(rect);
g2d.fill(rect);
g2d.dispose();
}
}
}