Hi - Im creating the game "Tanks" for the fun of it. Im fine with creating and adding the images and other inner game workings but I have digressed abit and have encountered a problem.
The problem is this: I have painted the tank image to the panel but wanted to paint n number of images to the screen according to the panel size. Let me give an example - each X is a tank:

XXXXX
XXXXX
XXXXX
XXXXX
XXXXX

The tanks should be painted in columns, and when 5 images have been painted or y( size of screen ) it moves to the next column and so on and so forth. When i tried doing this I could paint the first column and most of the second. I know that once y hits a certain value it should be reset to its initial value and x should be incremented. Maybe some code may help explain this:

public void paint( Graphics g )
	{
		super.paint( g );
		Graphics2D g2d = (Graphics2D)g;
		
		int x = 0;		int y = 25;
		
		System.out.println( "Paint method Called in Frame Class: "+callFrmeIncrmt+" times" );
		callFrmeIncrmt++;
		
		while( y <= 250 )
		{
			g2d.drawImage( myImage.getTankImage(), x, y, this );
			y += 40;
			System.out.println( "Images painted: "+imgCounter );
			imgCounter++;
		}
	}

Also can anyone tell me if the paint method is automatically called twice by default using the above method? I have included a print statement in the paint method to track the number of times it is called. The output is:

Paint method Called in Frame Class: 1 times
Images painted: 1
Images painted: 2
Images painted: 3
Images painted: 4
Images painted: 5
Images painted: 6
Paint method Called in Frame Class: 2 times
Images painted: 7
Images painted: 8
Images painted: 9
Images painted: 10
Images painted: 11
Images painted: 12

Any ideas? Or am I yacking on too much?

Recommended Answers

All 8 Replies

Dear ,
what i understood from your problem that you are trying to draw images like ( images in table) , why you are increasing y only , why you don't increase x when you finish first column and so on

I do - I actually increment it by 75 when y meets a certain value. I just accidentally deleted that method.

You can use getWidth() and getHeight() on the component where you are painting to see how high/wide it is, then have two nested loops: one for x, one for y, painting and incrementing until x>=width and y>=height respectively (or stop at 5 if that happens first).
ps Recommended practice is to override paintComponent, not paint.

if your container JFrame, JPanel, JLabel ... just start with J, then paintComponent or paintIcon (JLabel)

You can use getWidth() and getHeight() on the component where you are painting to see how high/wide it is, then have two nested loops: one for x, one for y, painting and incrementing until x>=width and y>=height respectively (or stop at 5 if that happens first).
ps Recommended practice is to override paintComponent, not paint.

Why is this? Is it more efficient to override the paintComponent method instead of paint itself?

Paint paints the component, any children in that component, and any frames, borders, decorations etc - everything related to the component. If you override it you can suffer from vanishing borders etc.
paintComponent just paints the internal direct content of the component, so you override that and all the borders/children etc still get handled properly.

JamesCherrill - I take my hat off to you. Its amazing what a little point in the right direction will do. I took your advice and tweaked it into something I understood...and it works perfectly :D

I actually created several methods for controlling the values of x and y respectively; one would increment it by 75 or reset it to its initial value of 25 and likewise for x, minus the reset part. Here's the code, should anyone in the future have a similar problem:

( Please note this is only one of the classes and only some of the methods within that class! )

// Get y value
	public int getY()
	{
		System.out.println( "X: "+x );
		return y;
	}
	
	// Get x value
	public int getX()
	{
		System.out.println( "Y: "+y );
		return x;
	}
	
	// Add value to y
	public int incrmtY()
	{
		return y += 40;
	}
	
	// Add value to x
	public int incrmtX()
	{
		return x += 75;
	}
	
	// Reset value of Y
	public int resetY()
	{
		return y = 25;
	}
	
	public void paint( Graphics g )
	{
		super.paintComponents(g);
		Graphics2D g2d = (Graphics2D)g;
		
		x = 0;		y = 25;
		
		System.out.println( "Paint method Called in Frame Class: "+callFrmeIncrmt+" times" );
		callFrmeIncrmt++;
		
		// First for loop for x
		for( int i = 0; i < 5; i++ )
		{
			// Second for loop for y
			for( int j = 0; j < 5; j++ )
			{
				g2d.drawImage( myImage.getTankImage(), getX(), getY(), this );
				incrmtY();
			}
			resetY();
			incrmtX();
		}
		
	}

Thanks again for everyone who contributed :P

@ Katana24

paint that....hmmm, that delegate painting for a ComponentUI f.e. BasicButtonUI ...., that's maybe will be your second for Swing's level

<withOutAttack>I'm sure that this painting is so far, by order your basic missunderstood/issue in this thread</withOutAttack>

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;

public class TilePainter extends JPanel implements Scrollable {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame("Tiles");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new JScrollPane(new TilePainter()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
    private final int TILE_SIZE = 50;
    private final int TILE_COUNT = 100;
    private final int visibleTiles = 10;
    private final boolean[][] loaded;
    private final boolean[][] loading;
    private final Random random;

    public TilePainter() {
        setPreferredSize(new Dimension(TILE_SIZE * TILE_COUNT, TILE_SIZE * TILE_COUNT));
        loaded = new boolean[TILE_COUNT][TILE_COUNT];
        loading = new boolean[TILE_COUNT][TILE_COUNT];
        random = new Random();
    }

    public boolean getTile(final int x, final int y) {
        boolean canPaint = loaded[x][y];
        if (!canPaint && !loading[x][y]) {
            loading[x][y] = true;
            Timer timer = new Timer(random.nextInt(500),
                    new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            loaded[x][y] = true;
                            repaint(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                        }
                    });
            timer.setRepeats(false);
            timer.start();
        }
        return canPaint;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Rectangle clip = g.getClipBounds();
        int startX = clip.x - (clip.x % TILE_SIZE);
        int startY = clip.y - (clip.y % TILE_SIZE);
        for (int x = startX; x < clip.x + clip.width; x += TILE_SIZE) {
            for (int y = startY; y < clip.y + clip.height; y += TILE_SIZE) {
                if (getTile(x / TILE_SIZE, y / TILE_SIZE)) {
                    g.setColor(Color.GREEN);
                } else {
                    g.setColor(Color.RED);
                }
                g.fillRect(x, y, TILE_SIZE - 1, TILE_SIZE - 1);
            }
        }
    }

    @Override
    public Dimension getPreferredScrollableViewportSize() {
        return new Dimension(visibleTiles * TILE_SIZE, visibleTiles * TILE_SIZE);
    }

    @Override
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
        return TILE_SIZE * Math.max(1, visibleTiles - 1);
    }

    @Override
    public boolean getScrollableTracksViewportHeight() {
        return false;
    }

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return false;
    }

    @Override
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
        return TILE_SIZE;
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.