swing Java repaint()在侦听器中的行为与在其余代码中的行为不同
当我启动程序时,一个面板中的所有内容都在帧边缘以0,0呈现,但是当我在侦听器中重新绘制时(代码中的其他地方不起作用),它将0,0放置在面板边缘。如果我从移动的面板中删除所有内容,那么它会渲染第一个面板两次。这是一个问题,因为第一次执行侦听器时,所有内容都向下移动
我会贴一张照片,但我没有足够的声誉,所以我会尝试用文字制作一张图表
1=面板1
2=面板1克隆
0=面板2 0,0
3=面板2
x=空白
单击之前:
0111111
3333333
3333333
使用panel2单击后:
1111111
0333333
3333333
单击后不带面板2:
1111111
0222222
XXXXXXX
面板损坏的类是TestPanel 这是调用TestPanel的类:
package main;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Paint;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class Drawer {
Images i;
protected JPanel p = new JPanel();
protected JPanel map = new JPanel();
protected JPanel test = new JPanel();
protected JPanel test2 = new JPanel();
protected World world;
protected TestPanel test3;
public Drawer(Images i, Keying k, Main main){
world = new World();
test3 = new TestPanel(i, main);
this.i = i;
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
BoxLayout mapLayout = new BoxLayout(map, BoxLayout.LINE_AXIS);
map.setLayout(mapLayout);
map.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.GRAY));
map.add(Box.createHorizontalGlue());
MapComp mc1 = new MapComp(2);
mc1.setType(1);
MapButton mb1 = new MapButton(new Level(), 2);
MapComp mc2 = new MapComp(2);
MapButton mb2 = new MapButton(new Level(), 2);
MapComp mc3 = new MapComp(2);
map.add(mc1);
for(Level l:world.levels){
if(l.getStatus()!=Level.STATUS_UNPLAYED){
map.add(l.mapButton);
if(l.getStatus()!=Level.STATUS_NEXT){
MapComp m = new MapComp(2);
m.setType(0);
map.add(m);
}
}
}
// map.add(mb1);
// map.add(mc2);
// map.add(mb2);
// map.add(mc3);
map.add(Box.createHorizontalGlue());
GridLayout testLayout = new GridLayout(8,8);
test.setLayout(testLayout);
test.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.GRAY));
test.add(Box.createVerticalStrut(30));
GridLayout test2Layout = new GridLayout(8,8);
test2.setLayout(test2Layout);
test2.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.GRAY));
test2.add(Box.createVerticalStrut(30));
test2.setBackground(Color.GREEN);
test3.setLayout(new GridLayout(8,8));
test3.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.GRAY));
p.add(map);
p.add(test3);
System.out.println(mb1.getLevel().printStatus());
Saver.createFilleStructure();
//world.l1.save();
//switchComponant(test, test2);
}
public int getIndex(JComponent comp){
return p.getComponentZOrder(comp);
}
public void switchComponant(JComponent oldComp, JComponent newComp){
int i = p.getComponentZOrder(oldComp);
p.remove(i);
p.add(newComp, i);
}
}
此类具有paintcomponent方法
package main;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.Random;
import javax.swing.*;
public class TestPanel extends JPanel {
Images i;
//Dimension size = new Dimension(32, 32);
// Point[][] points = new Point[(int) size.getWidth()][(int) size.getHeight()];
World w = new World();
Tiles tiles = new Tiles();
int scale = 1;
Point offset = new Point(0, 0);
public boolean smooth;
Dimension levelSize = new Dimension();
public TestPanel(Images i, Main m){
this.i = i;
w.setCurrentLevel(w.levels.get(0));
repaint();
//Random ranGen = new Random();
// for(int x=0;x<(int) size.getWidth();x++){
// for(int y=0;y<(int) size.getHeight();y++){
// points[x][y] = new Point(7 - (((y+((int) x/8))^2) % 8), 7 - (((x+((int) y/8))^2) % 8));
// System.out.println(points[x][y].x + ", " + points[x][y].y);
// }
// }
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e){
requestFocusInWindow();
}
});
requestFocusInWindow();
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e){
requestFocusInWindow();
if(e.getKeyCode()==KeyEvent.VK_W){
if(offset.getY()<0){
offset.y+=1;
repaint();
}
else{
System.out.println("can not move");
}
}
if(e.getKeyCode()==KeyEvent.VK_S){
if(offset.getY()<levelSize.getWidth()*32){
offset.y-=1;
repaint();
}
else{
System.out.println("can not move");
}
}
if(e.getKeyCode()==KeyEvent.VK_A){
if(offset.getX()<0){
offset.x+=1;
repaint();
}
else{
System.out.println("can not move");
}
}
if(e.getKeyCode()==KeyEvent.VK_D){
if(offset.getX()<levelSize.getHeight()*32){
offset.x-=1;
repaint();
}
else{
System.out.println("can not move");
}
}
}
});
}
@Override
public void paintComponent(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
Level l = w.getCurrentLevel();
levelSize.setSize(l.width, l.height);
scale = 1;
while(l.width*32*scale<getWidth() || l.height*32*scale<getHeight()){
scale+=1;
}
for(int x=0;x<(int) l.width;x++){
for(int y=0;y<(int) l.height;y++){
if((x*32+((int)offset.getX())+32)*scale>=0 && (x*32+32+((int)offset.getX())-32)*scale<=getWidth() && (y*32+((int)offset.getY())+32)*scale>=0 && (y*32+((int)offset.getY())-32)*scale<=getHeight()){
Tile t = tiles.getTileById(l.levelData[x][y].getId());
AffineTransform af = new AffineTransform();
af.rotate((Math.PI/2)*l.levelData[x][y].getRotation(), (x*32+16+((int)offset.getX()))*scale, (y*32+16+((int)offset.getY()))*scale);
g2D.setTransform(af);
g2D.drawImage(t.getImage(), (x*32+((int)offset.getX()))*scale, (y*32+((int)offset.getY()))*scale, (x*32+32+((int)offset.getX()))*scale, (y*32+32+((int)offset.getY()))*scale, 0, 0, 32, 32, null);
g2D.setTransform(new AffineTransform());
for(OverlayData overlay:l.levelData[x][y].getOverlayData()){
Tile t2= tiles.getTileById(overlay.getId());
int corner = overlay.isCorner()? 1 : 0;
if(t2.hasImage){
g2D.drawImage(t2.getOverlayImage(), (x*32+((int)offset.getX()))*scale, (y*32+((int)offset.getY()))*scale, (x*32+32+((int)offset.getX()))*scale, (y*32+32+((int)offset.getY()))*scale, overlay.getMod()*32, corner*32, overlay.getMod()*32+32, corner*32+32, null);
}
}
}
}
}
}
}
# 1 楼答案
虽然不可能根据发布的代码轻松测试这一点,但这很可能是由对
Graphics2D#setTransform
的调用引起的引用JavaDoc:
覆盖Graphics2D上下文中的转换。警告:此方法不应用于在现有变换的基础上应用新的坐标变换,因为图形2D可能已经具有用于其他目的的变换,例如渲染Swing组件或应用缩放变换以调整打印机的分辨率
要添加坐标变换,请使用变换、旋转、缩放或剪切方法。setTransform方法仅用于在渲染后恢复原始Graphics2D变换,如本例所示:
编辑:尝试将此模式应用于for循环(在该循环中调用了
setTransform
),可能大致如下所示:不过,可能还有更优雅的解决方案