import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; /** * A small extension to JPanel, meant to allow * the JPanel to support a tiling image background. * The tiled background is correctly drawn inside * any Border that the panel might have. Note * that JTiledPanel containers are always opaque. * If you give the tiling image as null, then * JTiledPanel behaves exactly like an opaque * JPanel. */ public class JTiledPanel extends JPanel { private Image tileimage; private int tilewidth; private int tileheight; private Rectangle rb; private Insets ri; /** * Create a JTiledPanel with the given image. * The tile argument may be null, you can set it later * with setTileImage(). Note that a JTiledPanel is * always opaque. */ public JTiledPanel(Image tile) { super(); setTileImage(tile); setOpaque(true); rb = new Rectangle(0,0,1,1); ri = new Insets(0,0,0,0); } /** * Create a JTiledPanel with the given image and * layout manager and double buffering status. * Either or both of the first two arguments * may be null. */ public JTiledPanel(Image tile, LayoutManager mgr, boolean isDB) { super(mgr, isDB); setTileImage(tile); setOpaque(true); rb = new Rectangle(0,0,1,1); ri = new Insets(0,0,0,0); } /** * Get the current tiling image, or null if there * isn't any right now. */ public Image getTileImage() { return tileimage; } /** * Set the current tiling image. To prevent tiling, * call this method with null. Note that this method * does NOT call repaint for you; if you want the panel * to repaint immediately, you must call repaint() * yourself. */ public void setTileImage(Image tile) { tileimage = tile; tilewidth = 0; tileheight = 0; } /** * Paint this component, including the tiled * background image, if any. */ public void paintComponent(Graphics g) { super.paintComponent(g); if (tileimage != null && tilewidth <= 0) { tileheight = tileimage.getHeight(this); tilewidth = tileimage.getWidth(this); } if (tileimage != null && tilewidth > 0) { Color bg = getBackground(); getBounds(rb); Insets riv = getInsets(ri); rb.translate(riv.left, riv.top); rb.width -= (riv.left + riv.right); rb.height -= (riv.top + riv.bottom); Shape ccache = g.getClip(); g.clipRect(rb.x, rb.y, rb.width, rb.height); int xp, yp; for(yp = rb.y; yp < rb.y + rb.height; yp += tileheight) { for(xp = rb.x; xp < rb.x + rb.width; xp += tilewidth) { g.drawImage(tileimage, xp, yp, bg, this); } } g.setClip(ccache); } } /** * Small main to do a self-test. Tiles with a image file * name taken from the command line. For example, if you * have a directory named images and an image in it * named tile1.gif then you would run this test * main as java JTiledPanel images/tile1.gif. */ public static void main(String [] args) { if (args.length == 0) { System.out.println("Usage: java JTiledPanel imagefile"); System.exit(0); } JFrame f = new JFrame("Test JTiledPanel " + args[0]); ImageIcon ic = new ImageIcon(args[0]); JTiledPanel jtp = new JTiledPanel(ic.getImage()); jtp.setBorder(BorderFactory.createMatteBorder(3,4,5,6,Color.green)); jtp.add(new JButton("Press Me!")); jtp.add(new JButton("Press Me Too!")); f.getContentPane().add(jtp, BorderLayout.CENTER); f.setSize(350,290); f.show(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { System.exit(0); } }); } }