好吧,所以我有两个JFrame,每个JFrame都有不同的JPanel实现。当我在JPanels上调用repaint()
时,在一个JPanel上绘制的内容也会在另一个JPanel上绘制。
我知道我可以通过调用类似g.clearRect()
之类的东西来处理这个问题,但是每次重绘都有太多的组件。
知道为什么会这样吗?
//This makes the two JFrames and JPanels, sets everything up
public void makeSpaceSimulation() {
int dimen = 10000;
int scale = 20;
int numOfClusters = 30;
int planPerCluster = 2000;
SpaceShip s = new SpaceShip(dimen, scale);
QuadTree t = new QuadTree(dimen, 20);
new PlanetCreationTest(t, dimen, scale, numOfClusters, planPerCluster);
makeMap(dimen, scale, s, t);
makePOV(s, t, scale, dimen);
}
public void makeMap(int dimen, int scale, SpaceShip s, QuadTree t) {
final JFrame f = new JFrame();
f.setSize(dimen / scale, dimen / scale);
f.setLocation(0, 0);
f.setTitle("Map Panel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mapP = new MapPanel(scale, s, dimen);
mapP.setLayout(new BorderLayout());
mapP.addTree(t);
f.add(mapP);
f.setVisible(true);
Insets i = f.getInsets();
f.setSize(dimen / scale + (i.left + i.right) + 2, dimen / scale
+ (i.top + i.bottom) + 2);
Thread th = new Thread() {
public void run() {
while (true) {
mapP.repaint();
}
}
};
th.start();
}
public void makePOV(final SpaceShip s, QuadTree t, int scale, int dimen) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
JFrame f = new JFrame();
f.setSize(500, 500);
f.setLocation(screenSize.width - 500, 0);
f.setTitle("POV Panel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
povP = new POVPanel(s, scale, dimen);
povP.setLayout(new BorderLayout());
povP.addTree(t);
povP.setFocusable(true);
povP.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent arg0) {
final int i = arg0.getKeyCode();
Thread th = new Thread() {
public void run() {
if (i == 39) {
s.moveRight();
} else if (i == 37) {
s.moveLeft();
} else if (i == 40) {
s.moveDown();
} else if (i == 38) {
s.moveUp();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
th.start();
}
@Override
public void keyReleased(KeyEvent arg0) {
}
@Override
public void keyTyped(KeyEvent arg0) {
}
});
f.add(povP);
f.setVisible(true);
Insets i = f.getInsets();
f.setSize(dimen / 20 + (i.left + i.right) + 2, dimen / 20
+ (i.top + i.bottom) + 2);
Thread th = new Thread() {
public void run() {
while (true) {
povP.repaint();
}
}
};
th.start();
}
//here's the MapPanel
public class MapPanel extends JPanel {
private QuadTree q;
private int scale;
private int dimen;
private SpaceShip s;
private boolean firstDraw;
public MapPanel(int scale, SpaceShip s, int dimen) {
this.dimen = dimen;
q = new QuadTree(0, 0);
this.scale = scale;
this.s = s;
firstDraw = true;
}
public void addTree(QuadTree q) {
this.q = q;
}
public void paintComponent(Graphics g) {
if (firstDraw) {
q.draw(g, scale, new Point(0, 0));
s.drawScaledGeometry(g);
System.out.println("Totally drew that");
firstDraw = false;
} else {
g.clearRect(s.viewDistance.x/scale, s.viewDistance.y/scale,
s.viewDistance.width/scale, s.viewDistance.height/scale);
q.quadDraw(g, scale, s.viewDistance, new Point(0, 0));
s.drawScaledGeometry(g);
}
}
}
//and this is the POVPanel
public POVPanel(SpaceShip s, int scale, int dimen) {
super();
this.s = s;
// this.scale = scale;
this.dimen = dimen;
}
public void addTree(QuadTree q) {
this.q = q;
}
public void paintComponent(Graphics g) {
g.clearRect(0, 0, dimen / 20, dimen / 20);
q.quadDraw(g, 1, s.viewDistance, s.getMoved());
s.drawGeometry(g);
}
答案 0 :(得分:2)
这是(一)你的问题......
public void paintComponent(Graphics g) {
if (firstDraw) {
q.draw(g, scale, new Point(0, 0));
s.drawScaledGeometry(g);
System.out.println("Totally drew that");
firstDraw = false;
} else {
g.clearRect(s.viewDistance.x/scale, s.viewDistance.y/scale,
s.viewDistance.width/scale, s.viewDistance.height/scale);
q.quadDraw(g, scale, s.viewDistance, new Point(0, 0));
s.drawScaledGeometry(g);
}
}
Graphics
上下文在绘制周期中共享,这意味着当你得到它时,你将获得用于绘制屏幕上所有其他组件的相同上下文。
你必须调用super.paintComponent(g)
,它将负责为这个组件准备图形上下文以开始绘画。
更新#1
...再次
public void paintComponent(Graphics g) {
super.paintComponent(g); // <-- Call me instead...
//g.clearRect(0, 0, dimen / 20, dimen / 20);
q.quadDraw(g, 1, s.viewDistance, s.getMoved());
s.drawGeometry(g);
}
更新#2
我也非常关注这个
while (true) {
mapP.repaint();
}
这可能会严重影响您的应用程序的性能。你不要控制油漆循环,这是重绘经理的责任。重绘经理将决定何时需要重新绘制。像这样重复调用repaint
实际上可能导致重绘管理器延迟实际调度绘制周期。
使用javax.swing.Timer
要好得多,它更简单,更安全......
Timer timer = new Timer(25, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
mapP.repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
你可能会发现阅读
有用的
更新#3
避免KeyListener
,它只会让你哭泣。相反,请使用key bindings API