I wan to make the text big then become small again after few second and it will keep repeating become big then small. How should i code it?
//DUMMY POST nfinity Blade is a fighting game developed by Chair Entertainment and Epic Games and released through the App Store on December 9, 2010. It is the first iOS video game to run on the Unreal Engine. In the game, the unnamed player character fights a series of one-on-one battles in a derelict castle to face the immortal God King. When in battle, players swipe the screen to attack and parry, and tap the screen to dodge and block enemy attacks. Upon victory or defeat, the player restarts the game as the character's descendant with the same items and experience level. Developed by a team of twelve people, the game was intended to demonstrate the new iOS version of the Unreal Engine. Four free expansions added new equipment, endings, and game modes. The game made US$1.6 million in the//DUMMYPOST
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FontSizeAnimation extends JPanel implements ActionListener {
Timer timer;
int x = 1;
float alpha = 1;
public FontSizeAnimation() {
timer = new Timer(4, this);
timer.setInitialDelay(500);
timer.start();
}
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Font font = new Font("Dialog", Font.PLAIN, x);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String s = "Java";
int w = (int) getSize().getWidth();
int h = (int) getSize().getHeight();
int stringWidth = fm.stringWidth(s);
g2d.drawString(s, (w - stringWidth) / 2, h / 2);
}
public static void main(String[] args) {
JFrame frame = new JFrame("FontSizeAnimation");
frame.add(new FontSizeAnimation());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
x += 1;
alpha -= 0.0001;
repaint();
}
}
Of course there are multiple ways of achieving this, but you could create a variable that holds wheter the size of the font should get bigger or smaller. Update that variable in the actionPerformed() method and then change the font size according to what the variable's value is. Here's an example with your code (click here for a preview, would be too distracting in the post):
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FontSizeAnimation extends JPanel implements ActionListener {
Timer timer;
int x = 1;
int lastX = 1;
float alpha = 1;
boolean bigger;
public FontSizeAnimation() {
timer = new Timer(4, this);
timer.setInitialDelay(500);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Font font = new Font("Dialog", Font.PLAIN, x);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String s = "Java";
int w = (int) getSize().getWidth();
int h = (int) getSize().getHeight();
int stringWidth = fm.stringWidth(s);
g2d.drawString(s, (w - stringWidth) / 2, h / 2);
}
public static void main(String[] args) {
JFrame frame = new JFrame("FontSizeAnimation");
frame.add(new FontSizeAnimation());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (x > 50) {
bigger = false;
} else if (x < 2) {
bigger = true;
}
if (bigger) {
x++;
} else {
x--;
}
alpha -= 0.0001;
repaint();
}
}
Related
I've been working on a 2D game in Swing and accidently came across an issue. Normally, when I run my code and test the game, the game window is on my 240hz monitor and everything is nice and smooth, however, when I move the window to my 60hz monitor I notice that the animation for the "side-scrolling" obstacles aren't smooth at all. They're moving across the screen, but they're micro-stuttering the whole way across, and at regular intervals I've noticed.
I've tried using a thread instead of a timer and although the micro-stutters are reduced at lot, specifically when I set the delay to 16, they do still occur about every 1 second.
I'm not really sure what to do at this point, so any advice would be much appreciated!
Here are the relevant classes:
package dinoRun;
public class Main {
public static void main(String[] args) {
new Window();
}
}
package dinoRun;
import javax.swing.*;
public class Window extends JFrame {
static GamePanel panel;
Window() {
panel = new GamePanel();
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.pack();
this.setLocationRelativeTo(null);
this.setTitle("Dino Run");
this.setVisible(true);
}
}
package dinoRun;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends Renderer implements ActionListener {
final int WIDTH = 1280, HEIGHT = 720;
Rectangle dino;
ArrayList<Rectangle> cactii;
GamePanel() {
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
dino = new Rectangle(WIDTH / 20, HEIGHT / 2, 100, 100);
cactii = new ArrayList<>();
addCactus();
Timer timer = new Timer(1, this);
timer.start();
}
void paintDino(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(dino.x, dino.y, dino.width, dino.height);
}
void addCactus() {
Random rand = new Random();
int space = rand.nextInt(64) * 10;
cactii.add(new Rectangle(space + WIDTH * (cactii.size() + 1), HEIGHT / 2, 30, 100));
}
void paintCactus(Graphics g, Rectangle cactus) {
g.setColor(Color.BLACK);
g.fillRect(cactus.x, cactus.y, cactus.width, cactus.height);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
void repaint(Graphics g) {
g.setColor(Color.BLACK);
paintDino(g);
g.drawLine(0, HEIGHT / 2 + 100, WIDTH, HEIGHT / 2 + 100);
for (int i = 0; i < cactii.size(); i++){
if (cactii.get(i).getX() + cactii.get(i).getWidth() != 0) {
paintCactus(g, cactii.get(i));
cactii.get(i).translate(-10, 0);
} else {
cactii.remove(cactii.get(i));
i--;
}
}
addCactus();
}
}
package dinoRun;
import javax.swing.*;
import java.awt.*;
public class Renderer extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Window.panel.repaint(g);
}
}
I'm new to Java and I've recently been trying to make an Atari Breakout game. I managed to get the player moving and the ball to bounce but not at the same time in the JFrame (the component that was added the latest is the one that is being shown). I made two seperate classes for the player and the ball (both extending from JPanel) and I think that might be the problem, though I don't really know.
Anyway, this is the code for the player:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Player extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5,this);
int x=200,vel=0;
boolean outOfBoundsR = true, outOfBoundsL = true;
public Player(){
t.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r= g2.getClipBounds();
r.x = x;
g2.setColor(Color.blue);
g2.fill(new Rectangle2D.Double(r.getX(),350,100,5));
if(r.getX()>385){
vel=0;
outOfBoundsR = false;
}else if(r.getX()<0){
vel=0;
outOfBoundsL = false;
}
}
public void actionPerformed(ActionEvent e){
repaint();
x+=vel;
}
public void right(){
vel = 1;
}
public void left(){
vel = -1;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT&&outOfBoundsR){
outOfBoundsL=true;
right();
} else if(key == KeyEvent.VK_LEFT&&outOfBoundsL){
outOfBoundsR=true;
left();
}
}
public void keyReleased(KeyEvent e) {vel = 0;}
public void keyTyped(KeyEvent e) {}
}
This is the code for the ball:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.print.attribute.standard.Media;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ball extends JPanel implements ActionListener{
Timer t = new Timer(5,this);
double velx = 0, vely = -1, x = 250, y = 330;
public Ball(){
t.start();
setFocusable(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r = g2.getClipBounds();
r.x = (int) x;
r.y = (int) y;
g2.fill(new Ellipse2D.Double(r.getX(), r.getY(), 8, 8));
if(r.getY() < 0 || r.getY() > 355){
vely -= (vely*2);
}else if(r.getX() < 0 || r.getX() > 480){
velx -= (velx*2);
}
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
}
And this is the code for the GUI:
import javax.swing.JFrame;
public class Gui extends JFrame{
public static void main(String[] args) {
JFrame f= new JFrame(); // the frame
Ball b = new Ball(); // the ball
Player p = new Player();// the player
f.getContentPane().add(p);
f.getContentPane().add(b);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,400);
f.setVisible(true);
}
}
Thanks in advance! (I know this was a bit long...)
I don't know how you want your Ball and Player objects to interact, but in your example f.getContentPane().add(...) translates to f.getContentPane().add(..., BorderLayout.CENTER). Therefore, p is replaced by b in the subsequent call to add - the content pane of JFrame makes use of a BorderLayout by default.
Have a look at the Swing layout manager tutorial for more information.
I think that better way to do it is make player and ball as component and make next object which can be JPanel as a game. But your way should work too. Problem can be with chosen layout in your frame. I can suggest this changes for you.
public static void main(String[] args) {
JFrame f= new JFrame(); // the frame
Ball b = new Ball(); // the ball
Player p = new Player();// the player
f.getContentPane().add(p, BorderLayout.CENTRE);
f.getContentPane().add(b, BorderLayout.EAST);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,400);
f.setVisible(true);
}
This question already has an answer here:
netBeans gui problem
(1 answer)
Closed 8 years ago.
I'm trying to use canvas in java. I'm using netbeans GUI builder to add several canvases to the window but I'm not sure how to for example draw the line or rectangle on them. I read several manuals how to do that but I'm still beginner in Java and I didn't quite understand what am I supposed to do. The constructor of the class looks like this:
public Classname() {
initComponents();
canvas1.setBackground(Color.red); // That works.
// Now I want to (for example) draw a line on the canvas1 (or some other canvas)
}
Could somebody please explain me what code should I write and where to put it? Thanks in advance. (Sorry for my english.)
Assuming your mean java.awt.Canvas, I'd recommend that you shouldn't be using it. Two main reasons, one, it's a heavy weight component, which introduces a list of issues when mixed with Swing/lightweight components and two, it's not double buffered, which just adds additional overheads you're going to have to deal with.
The preferred means by which to perform custom painting is to generally create a new class that extends from JPanel and the override it's paintComponent method for example
public class PaintPane extends JPanel {
public PaintPane () {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
g2d.dispose();
}
}
This will draw a simple line across the middle of the panel.
You can then drag the class from the "Projects" tab into the form editor (and onto an existing form container), like you would with components from the palette
Take a look at Performing Custom Painting and 2D Graphics for more details
Updated with example based on comments
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawExample {
public static void main(String[] args) {
new DrawExample();
}
private DrawPane drawPane;
public DrawExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
drawPane = new DrawPane();
JButton addRect = new JButton("Add Rectangle");
addRect.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int width = drawPane.getWidth() - 1;
int height = drawPane.getHeight() - 1;
int x = (int)(Math.random() * (width - 5));
int y = (int)(Math.random() * (height - 5));
width -= x;
height -= y;
int rectWidth = (int)(Math.random() * width);
int rectHeight = (int)(Math.random() * height / 2);
drawPane.addRect(x, y, rectWidth, rectHeight);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(drawPane);
frame.add(addRect, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends JPanel {
private List<Shape> shapes;
public DrawPane() {
shapes = new ArrayList<Shape>(25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape shape : shapes) {
g2d.draw(shape);
}
g2d.dispose();
}
public void addRect(int x, int y, int width, int height) {
shapes.add(new Rectangle(x, y, width, height));
repaint();
}
}
}
I need 2 separate JPanels (or any lightweight components) on top of each-other and ultimately embedded within a JPanel, either directly or through something like a JLayeredPane. Thus, no heavy-weight components or glass pane. The lower JPanel (named BackgroundPanel) paints a background image or plays a video while maintaining aspect ratio and using an alpha. The upper panel (called CompassPanel) has icons on it and allows the user to add icons, delete them, and move them around (like a diagramming library, this functionality is not directly relevant to this post though). I cannot add many external dependencies due to bandwidth constraints with my JNLP app and deployment environment. However, if someone knows of a lightweight diagramming library that can handle alpha & aspect-ratio maintained background images and videos, I'm game. Otherwise, I cannot for the life of me figure out why this space is being allocated after a resize:
I have read the JAVA tutorial on going without a layout manager (not something I ever wanted to do, where are you GBL!?), but for these scaling requirements and having icons stay over the same portion of the image during resize, etc. I can't think of another way to do this.
Here is the code, I am using Java 1.7. Also, this is my first stackoverflow, don't be gentle ;-)
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
public class Panel extends JPanel {
private static final Logger logger = Logger.getLogger(Panel.class.getName());
public Panel() throws IOException {
final BufferedImage backgroundImage = ImageIO.read(new URL(
"http://www.windpoweringamerica.gov/images/windmaps/us_windmap_80meters_820w.jpg"));
final Dimension backgroundImageSize = new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
logger.log(Level.INFO, "Image dimensions: {0}", backgroundImageSize);
setToolTipText("This is the panel");
final JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setBorder(BorderFactory.createLineBorder(Color.RED, 10));
layeredPane.setToolTipText("This is the layered pane!");
layeredPane.getInsets().set(0, 0, 0, 0);
final BackgroundPanel backgroundImagePanel = new BackgroundPanel(backgroundImage);
final CompassPanel compassPanel = new CompassPanel();
backgroundImagePanel.setToolTipText("You'll probably never see me, I'm in the background, forever beneath the compass panel");
compassPanel.setToolTipText("I'm the compass panel");
// Per http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html, for every container w/o a layout manager, I must:
// 1) Set the container's layout manager to null by calling setLayout(null). -- I do this here
// 2) Call the Component class's setbounds method for each of the container's children. --- I do this when resizing
// 3) Call the Component class's repaint method. --- I do this when resizing
setLayout(null);
add(layeredPane);
layeredPane.add(backgroundImagePanel, JLayeredPane.DEFAULT_LAYER);
layeredPane.add(compassPanel, JLayeredPane.PALETTE_LAYER);
// Whenever this panel gets resized, make sure the layered pane gets resized to preserve the aspect ratio of the background image
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent evt) {
Dimension availableSize = calculateAvailableSize(Panel.this);
Rectangle contentBounds = calculateBoundsToFitImage(availableSize, backgroundImageSize);
// Ok, this is a big deal. Now I know how big everything has to be, lets force it all to be the right size & repaint.
layeredPane.setBounds(contentBounds);
backgroundImagePanel.setBounds(contentBounds);
compassPanel.setBounds(contentBounds);
Panel.this.repaint();
logger.info(String.format("Panel size: %s. Available size: %s. Content Bounds: %s", getSize(), availableSize, contentBounds));
}
});
}
/**
* Paints the constant fitted aspect-ratio background image with an alpha of 0.5
*/
private static class BackgroundPanel extends JPanel {
private static final Logger logger = Logger.getLogger(BackgroundPanel.class.getName());
private final AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f);
private final BufferedImage backgroundImage;
BackgroundPanel(BufferedImage backgroundImage) {
setLayout(null);
this.backgroundImage = backgroundImage;
}
private Dimension lastPaintedDimensions = null;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Dimension size = getSize();
if (lastPaintedDimensions == null || !size.equals(lastPaintedDimensions)) {
logger.log(Level.INFO, String.format("Painting background on %d x %d", size.width, size.height));
}
final Image paintMe = backgroundImage.getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);
final Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(paintMe, 0, 0, this);
g2.setColor(Color.BLUE);
g2.dispose();
lastPaintedDimensions = size;
}
};
private static class CompassPanel extends JPanel {
final List<Compass> compassLabels = new ArrayList<>();
CompassPanel() {
setLayout(null);
setOpaque(false);
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
}
private static class Compass extends JLabel {
private static final BufferedImage compassImage;
static {
try {
compassImage = ImageIO.read(new URL("http://cdn1.iconfinder.com/data/icons/gur-project-1/32/1_7.png"));
} catch (IOException ex) {
throw new RuntimeException("Failed to read compass image", ex);
}
}
final float xPercent, yPercent;
public Compass(float xPercent, float yPercent) {
this.xPercent = xPercent;
this.yPercent = yPercent;
setIcon(new ImageIcon(compassImage));
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
setOpaque(true);
setCursor(Cursor.getDefaultCursor());
}
}
public static void main(String[] args) throws IOException {
final JFrame frame = new JFrame("Hello Stackoverflowwwwwww! Here is a Dynamic Layered Pane Question.");
frame.setLayout(null);
frame.setContentPane(new Panel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
private static Dimension calculateAvailableSize(final JComponent component) {
int availableHeight = component.getSize().height;
int availableWidth = component.getSize().width;
final Insets insets = component.getInsets();
availableHeight -= insets.top;
availableHeight -= insets.bottom;
availableWidth -= insets.left;
availableWidth -= insets.right;
if (component.getBorder() != null) {
Insets borderInsets = component.getBorder().getBorderInsets(component);
if (borderInsets != null) {
availableHeight -= borderInsets.top;
availableHeight -= borderInsets.bottom;
availableWidth -= borderInsets.left;
availableWidth -= borderInsets.right;
}
}
return new Dimension(availableWidth, availableHeight);
}
private static Rectangle calculateBoundsToFitImage(Dimension parentSize, Dimension imageSize) {
final double scaleFactor;
final int xOffset, yOffset, scaledHeight, scaledWidth;
{
final double xScaleFactor = (double) parentSize.width / imageSize.width;
final double yScaleFactor = (double) parentSize.height / imageSize.height;
scaleFactor = xScaleFactor > yScaleFactor ? yScaleFactor : xScaleFactor;
scaledHeight = (int) Math.round(scaleFactor * imageSize.height);
scaledWidth = (int) Math.round(scaleFactor * imageSize.width);
}
xOffset = (int) ((parentSize.width - scaledWidth) / 2.0);
yOffset = (int) ((parentSize.height - scaledHeight) / 2.0);
return new Rectangle(xOffset, yOffset, scaledWidth, scaledHeight);
}
}
Doh. I just answered my own question. Calling #setBounds is relative to your parent container, so the x & y offsets need to be properly accounted for, so this fixes that:
backgroundImagePanel.setBounds(0, 0, contentBounds.width, contentBounds.height);
compassPanel.setBounds(0, 0, contentBounds.width, contentBounds.height);
I am using JFrame and I have kept a background image on my frame. Now the problem is that the size of image is smaller then the size of the frame so i have to keep the same image once again on the empty part of the window. If user clicks maximize button than I may have to put the image on empty region of the frame at run time. Can anyone tell me how to accomplish this?
It sounds as though you are talking about tiling vs. stretching, though it's not clear which behaviour you want.
This program has examples of both:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) throws IOException {
final Image image = ImageIO.read(new URL("http://sstatic.net/so/img/logo.png"));
final JFrame frame = new JFrame();
frame.add(new ImagePanel(image));
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
#SuppressWarnings("serial")
class ImagePanel extends JPanel {
private Image image;
private boolean tile;
ImagePanel(Image image) {
this.image = image;
this.tile = false;
final JCheckBox checkBox = new JCheckBox();
checkBox.setAction(new AbstractAction("Tile") {
public void actionPerformed(ActionEvent e) {
tile = checkBox.isSelected();
repaint();
}
});
add(checkBox, BorderLayout.SOUTH);
};
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (tile) {
int iw = image.getWidth(this);
int ih = image.getHeight(this);
if (iw > 0 && ih > 0) {
for (int x = 0; x < getWidth(); x += iw) {
for (int y = 0; y < getHeight(); y += ih) {
g.drawImage(image, x, y, iw, ih, this);
}
}
}
} else {
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
}
}
You want something like the background image of the windows desktop, when using the background image multiple times instead of resizing it or just display it centered?
You only have to keep the image once and just paint it multiple times in the paintComponent method.
Another way to tile an image is with TexturePaint:
public class TexturePanel extends JPanel {
private TexturePaint paint;
public TexturePanel(BufferedImage bi) {
super();
this.paint = new TexturePaint(bi, new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(paint);
g2.fill(new Rectangle(0, 0, getWidth(), getHeight()));
}
}