有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    虽然不可能根据发布的代码轻松测试这一点,但这很可能是由对Graphics2D#setTransform的调用引起的

    引用JavaDoc:

    覆盖Graphics2D上下文中的转换。警告:此方法不应用于在现有变换的基础上应用新的坐标变换,因为图形2D可能已经具有用于其他目的的变换,例如渲染Swing组件或应用缩放变换以调整打印机的分辨率

    要添加坐标变换,请使用变换、旋转、缩放或剪切方法。setTransform方法仅用于在渲染后恢复原始Graphics2D变换,如本例所示:

    // Get the current transform 
    AffineTransform saveAT = g2.getTransform(); 
    // Perform transformation 
    g2d.transform(...); 
    // Render 
    g2d.draw(...); 
    // Restore original transform 
    g2d.setTransform(saveAT); 
    

    编辑:尝试将此模式应用于for循环(在该循环中调用了setTransform),可能大致如下所示:

    // Store the original transform
    AffineTransform oldAT = g2D.getTransform();
    
    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());
    
                // Apply the rotation to the g2D directly
                g2D.rotate((Math.PI/2)*l.levelData[x][y].getRotation(), (x*32+16+((int)offset.getX()))*scale, (y*32+16+((int)offset.getY()))*scale);
                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);
    
                // "Undo" the rotation by restoring the original transform
                g2D.setTransform(oldAT);
                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);
                    }
                }
            }
        }
    }
    
    // Finally, restore the original transform again
    g2D.setTransform(oldAT);
    

    不过,可能还有更优雅的解决方案