Java 图形不会删除行,即使我调用 super.paintComponent(g)
Java graphics won't delete lines, even when I call super.paintComponent(g)
首先 post 在 SO 中,希望我做对了!
我正在尝试在 Java 中制作一款游戏,其中机器人会四处行驶并在附近的墙壁上发光。问题是,这些线条会留在屏幕上,即使机器人移动时也是如此,所以它会形成一团不会擦除的线条。
在 paintComponent() 中,我尝试了 g.fillRect(),但这并没有擦除任何线条,只是在云后面绘制了一个矩形。到目前为止我看到的每一个来源似乎都在暗示我已经做过的事情,除非我误解/忽略了一些明显的事情......
'''
//from https://www.youtube.com/watch?v=p9Y-NBg8eto
/*
Other classes in this folder:
Robot.java Represents a robot, its location and angular orientation.
Obstacles.java Represents lines; the walls the robot should detect.
Sensor.java Represents the beams that shine from the robot to the walls.
//*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.lang.Math;
import java.util.ArrayList;
public class MyPanel extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
//OBSTACLES:
Obstacles obstacles=new Obstacles(0);
//ROBOT:
Robot robot = new Robot(obstacles);
//`````````````````````````````````````````````````````````
public MyPanel()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setVisible(true);
}
@Override
public void paintComponent(Graphics g)
{
g.dispose();
super.paintComponent(g);
//Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.RED);
g.fillRect(0, 0, 450, 450);
g.setColor(Color.BLACK);
//Graphics2D g2 = (Graphics2D) g;
robot.drawRobot(g);
drawBoundedBeams(g);
obstacles.drawObstacles(g);
drawSun(g);
}
@Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
@Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code==KeyEvent.VK_UP)
robot.up();
if (code==KeyEvent.VK_DOWN)
robot.down();
if (code==KeyEvent.VK_LEFT)
robot.left();
if (code==KeyEvent.VK_RIGHT)
robot.right();
robot.updateSensor();
}
@Override public void keyTyped(KeyEvent e) {}
@Override public void keyReleased(KeyEvent e) {}
//```````````````````````````````````````````````````````````
public static void main(String [] args)
{
JFrame f = new JFrame();
MyPanel panel = new MyPanel();
f.add(panel);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
}
//Dummy lines. For some reason, these delete and move with the robot, no problem.
public void drawSun(Graphics g)
{
int x = (int) robot.x;
int y = (int) robot.y;
double t = robot.angle;
double xang = Math.cos(t);
double yang = Math.sin(t);
double east = (t + Math.PI/2) % (2 * Math.PI);
double eastx = Math.cos(east);
double easty = Math.sin(east);
g.drawLine(x, y, x+100, y);
g.drawLine(x, y, x-100, y);
g.drawLine(x, y, x, y+100);
g.drawLine(x, y, x, y-100);
g.drawLine(x, y, x+100, y+100);
g.drawLine(x, y, x+100, y-100);
g.drawLine(x, y, x-100, y+100);
g.drawLine(x, y, x-100, y-100);
g.drawLine(x, y, x+(int)(xang*100), y+(int)(yang*100));
g.drawLine(x, y, x-(int)(xang*100), y-(int)(yang*100));
g.drawLine(x, y, x+(int)(eastx*100), y+(int)(easty*100));
g.drawLine(x, y, x-(int)(eastx*100), y-(int)(easty*100));
}
//This was in Sensor.java, but I moved it here to try to fix it. (Didn't work.)
//THIS is what isn't getting deleted.
public void drawBoundedBeams(Graphics g) //Graphics2D g2
{
//Graphics2D g2 = (Graphics2D) g;
for (Integer[] beam : robot.sensor.boundedBeams)
{
g.drawLine(beam[0], beam[1], beam[2], beam[3]);
}
}
}
'''
~~~~~~ EDIT: I made a Minimal ~~~~~~
~~~~~~ Reproducible Example. ~~~~~~
MyPanel.java:
'''
/*
Classes in this (reprex) folder:
MyPanel.java displays things ****PROBLEM HERE(?)
Robot.java stores location and orientation
Sensor.java Shines beams outward ****PROBLEM HERE(?)
(I tried to keep the file structure consistent,
in case that was a factor for the issue.)
//*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.lang.Math;
import java.util.ArrayList;
public class MyPanel extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
Robot robot = new Robot();
//`````````````````````````````````````````````````````````
public MyPanel()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setVisible(true);
}
//********************************************
//********************************************
//********************************************
//**** Problem seems to be HERE. *************
//**** ~~~~~~~~~~~~~~~~~~~~~~~~ *************
//**** (See also: the method in *************
//**** Sensor.java; drawBeams()) *************
//********************************************
//********************************************
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// And to smooth out the graphics, you can do the following
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillRect(0, 0, 450, 450);
g2.setColor(Color.BLACK);
robot.sensor.drawBeams(g2);
g2.dispose();
}
@Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
@Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code==KeyEvent.VK_UP)
robot.up();
if (code==KeyEvent.VK_DOWN)
robot.down();
if (code==KeyEvent.VK_LEFT)
robot.left();
if (code==KeyEvent.VK_RIGHT)
robot.right();
robot.updateSensor();
}
@Override public void keyTyped(KeyEvent e) {}
@Override public void keyReleased(KeyEvent e) {}
//```````````````````````````````````````````````````````````
public static void main(String [] args)
{
JFrame f = new JFrame();
MyPanel panel = new MyPanel();
f.add(panel);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
}
}
'''
Sensor.java:
'''
import java.lang.Math;
import java.util.ArrayList;
import java.awt.*;
class Sensor
{
private Robot robot;
public int numPieces;
public Integer range = 300;
public ArrayList<Double> offsets = new ArrayList<Double>(); //the angles of each beam
public ArrayList<Integer[]> beams = new ArrayList<Integer[]>(); //the beams that stretch out to the range public ArrayList<Integer[]> boundedBeams = new ArrayList<Integer[]>();
public Sensor(Robot robot)
{
this.robot=robot;
make12Sonars();
}
public void make12Sonars()
{
numPieces=12;
double offset = 0;
while (offset < 2*Math.PI)
{
offsets.add(offset);
offset += Math.PI / 6;
}
}
public void updateSensor()
{
makeBeams();
}
//```````````````````````````````````````````````````````
public void makeBeams() //Makes the maximum beams from the angles.
{
System.out.println("~~~MAKING BEAMS~~~");
for (Integer i=0; i<offsets.size(); i++)
{
System.out.println("\tat index "+i);
Double offset = offsets.get(i);
Double angle = (offset + robot.angle) % (2*Math.PI);
Integer[] beam = getSegment(robot.x, robot.y, angle, Double.valueOf(range));
beams.add(i, beam);
System.out.println("\t\tadded "+beam[0]+", "+beam[1]+", "+beam[2]+", "+beam[3]);
}
}
static public Integer[] getSegment(Double startX, Double startY, Double angle, Double radius)
{
Double x2 = radius * Math.cos(angle) + startX;
Double y2 = radius * Math.sin(angle) + startY;
Integer[] segment = {startX.intValue(), startY.intValue(), x2.intValue(), y2.intValue()};
return segment;
}
//********************************************
//********************************************
//********************************************
//**** Problem seems to be HERE. *************
//**** ~~~~~~~~~~~~~~~~~~~~~~~~ *************
//**** (The lines drawn here *************
//**** do not delete.) *************
//********************************************
//********************************************
public void drawBeams(Graphics g)
{
Integer x = (int) robot.x;
Integer y = (int) robot.y;
for (Integer[] beam : beams)
{
g.drawLine(beam[0], beam[1], beam[2], beam[3]);
}
}
}
'''
Robot.java:
'''
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.lang.Math;
class Robot
{
public double x=0, y=0; //center of the robot
public double velx=0, vely=0; //velocity of the robot
public double angle=0, speed=4; //radians, speed(before_direction)
public Sensor sensor;
public Robot()
{
sensor=new Sensor(this);
}
public void updateSensor() {sensor.updateSensor();}
//`````````````````````````````````````````````````````````````
//*
public void up() {x+=velx; y+=vely;}
public void down() {x-=velx; y-=vely;}
public void left()
{
angle -= 0.1;
angle = angle % (2*Math.PI);
velx = speed * Math.cos(angle);
vely = speed * Math.sin(angle);
}
public void right()
{
angle += 0.1;
angle = angle % (2*Math.PI);
velx = speed * Math.cos(angle);
vely = speed * Math.sin(angle);
} //*/
}
'''
您不应在 paintComponent()
的开头处理 default graphics context
。最好的办法是通过创建创建一个副本,然后在 paintComponent()
.
return 之前处理掉它
Try this as a your `paintComponent()` method.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// And to smooth out the graphics, you can do the following
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillRect(0, 0, 450, 450);
g2.setColor(Color.BLACK);
robot.drawRobot(g2);
drawBoundedBeams(g2);
obstacles.drawObstacles(g2);
drawSun(g2);
g2.dispose();
}
如果这不能帮助解决您的问题,请创建一个 Minimal Reproducible Example 来演示问题。它不应依赖 JDK API 之外的任何内容(即第三方 类、库等)
首先 post 在 SO 中,希望我做对了!
我正在尝试在 Java 中制作一款游戏,其中机器人会四处行驶并在附近的墙壁上发光。问题是,这些线条会留在屏幕上,即使机器人移动时也是如此,所以它会形成一团不会擦除的线条。
在 paintComponent() 中,我尝试了 g.fillRect(),但这并没有擦除任何线条,只是在云后面绘制了一个矩形。到目前为止我看到的每一个来源似乎都在暗示我已经做过的事情,除非我误解/忽略了一些明显的事情......
'''
//from https://www.youtube.com/watch?v=p9Y-NBg8eto
/*
Other classes in this folder:
Robot.java Represents a robot, its location and angular orientation.
Obstacles.java Represents lines; the walls the robot should detect.
Sensor.java Represents the beams that shine from the robot to the walls.
//*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.lang.Math;
import java.util.ArrayList;
public class MyPanel extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
//OBSTACLES:
Obstacles obstacles=new Obstacles(0);
//ROBOT:
Robot robot = new Robot(obstacles);
//`````````````````````````````````````````````````````````
public MyPanel()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setVisible(true);
}
@Override
public void paintComponent(Graphics g)
{
g.dispose();
super.paintComponent(g);
//Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.RED);
g.fillRect(0, 0, 450, 450);
g.setColor(Color.BLACK);
//Graphics2D g2 = (Graphics2D) g;
robot.drawRobot(g);
drawBoundedBeams(g);
obstacles.drawObstacles(g);
drawSun(g);
}
@Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
@Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code==KeyEvent.VK_UP)
robot.up();
if (code==KeyEvent.VK_DOWN)
robot.down();
if (code==KeyEvent.VK_LEFT)
robot.left();
if (code==KeyEvent.VK_RIGHT)
robot.right();
robot.updateSensor();
}
@Override public void keyTyped(KeyEvent e) {}
@Override public void keyReleased(KeyEvent e) {}
//```````````````````````````````````````````````````````````
public static void main(String [] args)
{
JFrame f = new JFrame();
MyPanel panel = new MyPanel();
f.add(panel);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
}
//Dummy lines. For some reason, these delete and move with the robot, no problem.
public void drawSun(Graphics g)
{
int x = (int) robot.x;
int y = (int) robot.y;
double t = robot.angle;
double xang = Math.cos(t);
double yang = Math.sin(t);
double east = (t + Math.PI/2) % (2 * Math.PI);
double eastx = Math.cos(east);
double easty = Math.sin(east);
g.drawLine(x, y, x+100, y);
g.drawLine(x, y, x-100, y);
g.drawLine(x, y, x, y+100);
g.drawLine(x, y, x, y-100);
g.drawLine(x, y, x+100, y+100);
g.drawLine(x, y, x+100, y-100);
g.drawLine(x, y, x-100, y+100);
g.drawLine(x, y, x-100, y-100);
g.drawLine(x, y, x+(int)(xang*100), y+(int)(yang*100));
g.drawLine(x, y, x-(int)(xang*100), y-(int)(yang*100));
g.drawLine(x, y, x+(int)(eastx*100), y+(int)(easty*100));
g.drawLine(x, y, x-(int)(eastx*100), y-(int)(easty*100));
}
//This was in Sensor.java, but I moved it here to try to fix it. (Didn't work.)
//THIS is what isn't getting deleted.
public void drawBoundedBeams(Graphics g) //Graphics2D g2
{
//Graphics2D g2 = (Graphics2D) g;
for (Integer[] beam : robot.sensor.boundedBeams)
{
g.drawLine(beam[0], beam[1], beam[2], beam[3]);
}
}
}
'''
~~~~~~ EDIT: I made a Minimal ~~~~~~
~~~~~~ Reproducible Example. ~~~~~~
MyPanel.java: '''
/*
Classes in this (reprex) folder:
MyPanel.java displays things ****PROBLEM HERE(?)
Robot.java stores location and orientation
Sensor.java Shines beams outward ****PROBLEM HERE(?)
(I tried to keep the file structure consistent,
in case that was a factor for the issue.)
//*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.lang.Math;
import java.util.ArrayList;
public class MyPanel extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
Robot robot = new Robot();
//`````````````````````````````````````````````````````````
public MyPanel()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setVisible(true);
}
//********************************************
//********************************************
//********************************************
//**** Problem seems to be HERE. *************
//**** ~~~~~~~~~~~~~~~~~~~~~~~~ *************
//**** (See also: the method in *************
//**** Sensor.java; drawBeams()) *************
//********************************************
//********************************************
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// And to smooth out the graphics, you can do the following
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillRect(0, 0, 450, 450);
g2.setColor(Color.BLACK);
robot.sensor.drawBeams(g2);
g2.dispose();
}
@Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
@Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code==KeyEvent.VK_UP)
robot.up();
if (code==KeyEvent.VK_DOWN)
robot.down();
if (code==KeyEvent.VK_LEFT)
robot.left();
if (code==KeyEvent.VK_RIGHT)
robot.right();
robot.updateSensor();
}
@Override public void keyTyped(KeyEvent e) {}
@Override public void keyReleased(KeyEvent e) {}
//```````````````````````````````````````````````````````````
public static void main(String [] args)
{
JFrame f = new JFrame();
MyPanel panel = new MyPanel();
f.add(panel);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.setVisible(true);
}
}
'''
Sensor.java: '''
import java.lang.Math;
import java.util.ArrayList;
import java.awt.*;
class Sensor
{
private Robot robot;
public int numPieces;
public Integer range = 300;
public ArrayList<Double> offsets = new ArrayList<Double>(); //the angles of each beam
public ArrayList<Integer[]> beams = new ArrayList<Integer[]>(); //the beams that stretch out to the range public ArrayList<Integer[]> boundedBeams = new ArrayList<Integer[]>();
public Sensor(Robot robot)
{
this.robot=robot;
make12Sonars();
}
public void make12Sonars()
{
numPieces=12;
double offset = 0;
while (offset < 2*Math.PI)
{
offsets.add(offset);
offset += Math.PI / 6;
}
}
public void updateSensor()
{
makeBeams();
}
//```````````````````````````````````````````````````````
public void makeBeams() //Makes the maximum beams from the angles.
{
System.out.println("~~~MAKING BEAMS~~~");
for (Integer i=0; i<offsets.size(); i++)
{
System.out.println("\tat index "+i);
Double offset = offsets.get(i);
Double angle = (offset + robot.angle) % (2*Math.PI);
Integer[] beam = getSegment(robot.x, robot.y, angle, Double.valueOf(range));
beams.add(i, beam);
System.out.println("\t\tadded "+beam[0]+", "+beam[1]+", "+beam[2]+", "+beam[3]);
}
}
static public Integer[] getSegment(Double startX, Double startY, Double angle, Double radius)
{
Double x2 = radius * Math.cos(angle) + startX;
Double y2 = radius * Math.sin(angle) + startY;
Integer[] segment = {startX.intValue(), startY.intValue(), x2.intValue(), y2.intValue()};
return segment;
}
//********************************************
//********************************************
//********************************************
//**** Problem seems to be HERE. *************
//**** ~~~~~~~~~~~~~~~~~~~~~~~~ *************
//**** (The lines drawn here *************
//**** do not delete.) *************
//********************************************
//********************************************
public void drawBeams(Graphics g)
{
Integer x = (int) robot.x;
Integer y = (int) robot.y;
for (Integer[] beam : beams)
{
g.drawLine(beam[0], beam[1], beam[2], beam[3]);
}
}
}
'''
Robot.java: '''
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.lang.Math;
class Robot
{
public double x=0, y=0; //center of the robot
public double velx=0, vely=0; //velocity of the robot
public double angle=0, speed=4; //radians, speed(before_direction)
public Sensor sensor;
public Robot()
{
sensor=new Sensor(this);
}
public void updateSensor() {sensor.updateSensor();}
//`````````````````````````````````````````````````````````````
//*
public void up() {x+=velx; y+=vely;}
public void down() {x-=velx; y-=vely;}
public void left()
{
angle -= 0.1;
angle = angle % (2*Math.PI);
velx = speed * Math.cos(angle);
vely = speed * Math.sin(angle);
}
public void right()
{
angle += 0.1;
angle = angle % (2*Math.PI);
velx = speed * Math.cos(angle);
vely = speed * Math.sin(angle);
} //*/
}
'''
您不应在 paintComponent()
的开头处理 default graphics context
。最好的办法是通过创建创建一个副本,然后在 paintComponent()
.
Try this as a your `paintComponent()` method.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// And to smooth out the graphics, you can do the following
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillRect(0, 0, 450, 450);
g2.setColor(Color.BLACK);
robot.drawRobot(g2);
drawBoundedBeams(g2);
obstacles.drawObstacles(g2);
drawSun(g2);
g2.dispose();
}
如果这不能帮助解决您的问题,请创建一个 Minimal Reproducible Example 来演示问题。它不应依赖 JDK API 之外的任何内容(即第三方 类、库等)