Question

When I start the program everything in one panel is rendered with 0,0 at the edge of the frame however when I repaint in a listener (no where else in the code works) it positions 0,0 at the edge of the panel. If I remove everything from the panel that moves then it renders the first panel twice. This is a problem as the first time a listener is performed everything moves down

I would post a picture but I do not have enough reputation so I shall attempt to make a diagram using text

1 = panel1
2 = panel1 clone
0 = panel2 0,0
3 = panel2
x = blank

befor click:
0111111
3333333
3333333

after click with panel2:
1111111
0333333
3333333

after click without panel2:
1111111
0222222
XXXXXXX

The class with the broken panel is TestPanel This is the class that calls 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);

    }
}

This class has the paintcomponent method

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);
                        }
                    }
                }

            }
        }
    }

}
Was it helpful?

Solution

Although it's not possible to easily test this based on the posted code, it's very likely that this is caused by the call to Graphics2D#setTransform.

Quoting from the JavaDoc:

Overwrites the Transform in the Graphics2D context. WARNING: This method should never be used to apply a new coordinate transform on top of an existing transform because the Graphics2D might already have a transform that is needed for other purposes, such as rendering Swing components or applying a scaling transformation to adjust for the resolution of a printer.

To add a coordinate transform, use the transform, rotate, scale, or shear methods. The setTransform method is intended only for restoring the original Graphics2D transform after rendering, as shown in this example:

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

EDIT: An attempt to apply this pattern to your for-loop, where you called setTransform, could roughly look like this:

// 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);

There may be more elegant solutions, though....

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top