3

I have an issue with redrawing a JFrame that contains hundreds of JFrames inside it. I have an application that draws a "tile based" map and each tile is a JFrame. When I try to revalidate and redraw the JFrame you can visibly see random tiles appearing.

To combat this I have created a JPanel (blinds) that goes over the oldmap, and then the old map gets removed. Only then do I redraw. Then I add the new map and remove the "blind" and then re-draw again.

Is there a better way to do this. Some pop-in is still visible.

public void refreshMap(){
    JPanel blinds = new JPanel();
    blinds.setBackground(oCreator.getColorLight());
    blinds.setBounds(0, 0, length, height);
    add(blinds);
    if(currentMap != null){
        remove(currentMap);
    }
    revalidate();
    repaint();
    JPanel newMap = addMapPanel(map);
    newMap.setBounds(((length-absoluteMapLength)/2), ((height-absoluteMapHeight)/2), absoluteMapLength, absoluteMapHeight);
    remove(blinds);
    revalidate();
    repaint();
    add(newMap);
    currentMap = newMap;
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
deadfire19
  • 329
  • 2
  • 16
  • 3
    `"I have an issue with redrawing a JFrame that contains hundreds of JFrames inside it. I have an application that draws a "tile based" map and each tile is a JFrame."` This is a most unusual program design, one I would never recommend. I'd love to help you change this, but would need more information to try to understand just what you're trying to do, the overall effect you're trying to achieve. Note that an application usually creates one JFrame, one main parent window, and that's it. – Hovercraft Full Of Eels Apr 05 '14 at 23:59
  • I need to be able to add squares as shown in the picture linked in the OP in a grid pattern, I realise making 100s of JPanels is a big waste but I don't know what else to try with. I need to be able to display a ~20*~15 grid of squares. Currently it consists of 377 tiles. – deadfire19 Apr 06 '14 at 00:08

1 Answers1

3

If done right, there should be minimal delay in your change of tiles, but I'm not sure that your code and explanation can currently tell us where you're stuck. For example, run this code (my minimal example program) to see tiles changing color with minimal delay and no artifacts.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;

public class SquareGridTest extends JPanel {
   public static final Color[] COLORS = { Color.blue, Color.red, Color.yellow,
         Color.orange, Color.green, Color.cyan, Color.lightGray, Color.magenta,
         Color.white, Color.black };
   private static final Icon[] ICONS = new Icon[COLORS.length];
   private static final int ROWS = 20;
   private static final int COLS = 30;
   private static final int BI_WIDTH = 20;
   private static final int BI_HEIGHT = BI_WIDTH;
   private static final int TIMER_DELAY = 15;
   protected static final int NUMBER_TO_SWAP = 15;
   private JLabel[][] grid = new JLabel[ROWS][COLS];
   private Random random = new Random();

   static {
      for (int i = 0; i < ICONS.length; i++) {
         BufferedImage img = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
         Graphics g = img.getGraphics();
         g.setColor(COLORS[i]);
         g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
         g.dispose();
         ICONS[i] = new ImageIcon(img);
      }
   }

   public SquareGridTest() {
      setLayout(new GridLayout(ROWS, COLS));
      for (int row = 0; row < grid.length; row++) {
         for (int col = 0; col < grid[row].length; col++) {
            JLabel label = new JLabel();
            int index = random.nextInt(COLORS.length);
            label.setIcon(ICONS[index]);
            add(label);
            grid[row][col] = label;            
         }
      }

      new Timer(TIMER_DELAY, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent evt) {
            for (int i = 0; i < NUMBER_TO_SWAP; i++) {
               int row = random.nextInt(ROWS);
               int col = random.nextInt(COLS);
               int iconIndex = random.nextInt(ICONS.length);
               grid[row][col].setIcon(ICONS[iconIndex]);
            }
         }
      }).start();
   }

   private static void createAndShowGui() {
      SquareGridTest mainPanel = new SquareGridTest();

      JFrame frame = new JFrame("SquareGridTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

For more detailed help with your code, and to help us better understand your problem, consider creating and posting your own minimal example program.

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • That is amazing. Thanks for your help. I see you only changed the square that actually changed, which is the main thing I think. I tried to re-load the entire map on each refresh. I will try to use the same logic in my code. I will report back when I finish converting. – deadfire19 Apr 06 '14 at 00:47