Dragomirus
Dragomirus

Reputation: 449

java How to display only visible area in JPanel

So I've got JPanel inside JScrollPane. Is there any possible way to display only visible area on JPanel? Right now my piece of code looks like that:

public void paintComponent(Graphics g)
{
    super.paintComponent(g);

    for(int i = 0; i < m_xTiles; i++)
    {
        for(int j = 0; j < m_yTiles; j++)
        {
            m_mapTiles.get(i).get(j).DrawImage(g);
        }
    }
}

It's not something that I want because it's display everything and when I want to make a very big map the movment are very slow. I want to get visible rectangle on screan - positions of four pixels and then I will calculate to my own x and y :)

Upvotes: 1

Views: 769

Answers (1)

Holger
Holger

Reputation: 298143

Normally the graphic system cares about clipping operations outside the visible bounds so these operation become no-ops and are not expensive. So in most cases you don’t need to deal with these information as the graphics operations are the expensive part when painting.

However, sometimes you may encounter the situation that the operations you perform before the calls on the Graphics object become expensive, i.e. if you have a really large but only partially visible component (as you described). In this situation it might be useful to access the clipping information to perform manually skipping, especially if you are tiling your area, thus calculating which items to process is rather easy:

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    // I assert equal tiling of the actual size here, otherwise you may define
    // the tile sizes as constants and calculate preferredSize as tileWidth*m_xTiles
    // and tileHeight*m_yTiles, respectively
    final int tileWidth=getWidth()/m_xTiles;
    final int tileHeight=getHeight()/m_yTiles;

    Rectangle clip = g.getClipBounds();

    int firstX, lastX, firstY, lastY;
    if(clip == null) {
        firstX=0; lastX=m_xTiles-1;
        firstY=0; lastY=m_yTiles-1;
    }
    else {
       firstX=clip.x/tileWidth;  lastX=(clip.x+clip.width)/tileWidth;
       firstY=clip.y/tileHeight; lastY=(clip.y+clip.height)/tileHeight;
    }
    // note that the loop condition is <= now to handle partially visible tiles
    for(int i = firstX; i <= lastX; i++)
    {
        for(int j = firstY; j <= lastY; j++)
        {
            m_mapTiles.get(i).get(j).DrawImage(g);
        }
    }
}

Upvotes: 2

Related Questions