I'm trying to draw Images with Graphics2D on JFrame.
But this code only displays blank background.
How to do that?
Java Version: SE-1.6
IDE: Eclipse
My code looks like this:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.geom.Line2D;
import java.util.TimerTask;
import javax.swing.JFrame;
public class GraphicTest extends JFrame{
public static void main(String[] args) {
GraphicTest gt = new GraphicTest();
gt.start();
}
JFrame frame;
BufferStrategy strategy;
GraphicTest(){
int width = 320;
int height = 240;
this.frame = new JFrame("test");
this.frame.setSize(width, height);
this.frame.setLocationRelativeTo(null);
this.frame.setLocation(576, 336);
this.frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
this.frame.setUndecorated(true);
this.frame.setBackground(new Color(0, 0, 0, 50));
this.frame.setVisible(true);
this.frame.setIgnoreRepaint(true);
this.frame.createBufferStrategy(2);
this.strategy = this.frame.getBufferStrategy();
}
public void onExit(){
System.exit(0);
}
void start(){
java.util.Timer timer = new java.util.Timer();
timer.schedule(new RenderTask(), 0, 16);
}
class RenderTask extends TimerTask{
int count = 0;
#Override
public void run() {
GraphicTest.this.render();
}
}
void render() {
// Some moving images
Graphics2D g2 = (Graphics2D)this.strategy.getDrawGraphics();
g2.setStroke(new BasicStroke(5.0f));
Line2D line = new Line2D.Double(20, 40, 120, 140);
g2.draw(line);
this.strategy.show();
}
}
Thank you for any help you can provide.
BufferStrategy is normally associated with heavy weight components, which don't have any concept of transparency.
Transparent and translucent (per alpha pixeling) is not "officially" supported under Java 6
Making a window translucent effects anything else painted to it...this very annoying, regardless if you are using Java 6 or 7
The secret is to make the Window transparent to begin with, then overlay a transparent component that has a special "translucent" paint effect.
Under Java 6 (update 10 I think), there became available a private API called AWTUtilities which provide the ability to make a window transparent or translucent, the following example is based on that API.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TransparentWindowAnimation {
public static void main(String[] args) {
new TransparentWindowAnimation();
}
public TransparentWindowAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
if (supportsPerAlphaPixel()) {
try {
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
setOpaque(frame, false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
} else {
System.err.println("Per pixel alphering is not supported");
}
}
});
}
public static boolean supportsPerAlphaPixel() {
boolean support = false;
try {
Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
support = true;
} catch (Exception exp) {
}
return support;
}
public static void setOpaque(Window window, boolean opaque) throws Exception {
try {
Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
if (awtUtilsClass != null) {
Method method = awtUtilsClass.getMethod("setWindowOpaque", Window.class, boolean.class);
method.invoke(null, window, opaque);
}
} catch (Exception exp) {
throw new Exception("Window opacity not supported");
}
}
public class PaintPane extends JPanel {
private BufferedImage img;
private int xPos, yPos = 100;
private int xDelta = 0;
private int yDelta = 0;
public PaintPane() {
while (xDelta == 0) {
xDelta = (int)((Math.random() * 8)) - 4;
}
while (yDelta == 0) {
yDelta = (int)((Math.random() * 8)) - 4;
}
setOpaque(false);
try {
img = ImageIO.read(new File("AngryBird.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
yPos += yDelta;
if (xPos - (img.getWidth() / 2) <= 0) {
xPos = img.getWidth() / 2;
xDelta *= -1;
}
if (xPos + (img.getWidth() / 2) >= getWidth()) {
xPos = getWidth() - (img.getWidth() / 2);
xDelta *= -1;
}
if (yPos - (img.getHeight() / 2) <= 0) {
yPos = img.getHeight() / 2;
yDelta *= -1;
}
if (yPos + (img.getHeight() / 2) >= getHeight()) {
yPos = getHeight() - (img.getHeight() / 2);
yDelta *= -1;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(128, 128, 128, 128));
g2d.fillRect(0, 0, getWidth(), getHeight());
int x = xPos - (img.getWidth() / 2);
int y = yPos - (img.getHeight()/ 2);
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
Another way can be seen here. It can be accomplished by
frame.setBackground(new Color(0, 0, 0, 0));
....
setOpaque(false); //for the JPanel being painted on.
Related
class DrawIma extends JPanel{
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i=0;i<20;i++){
for (int j=0;j<20;j++) {
g.drawImage(BuArr[i*20+j], 20*i, 20*j, 20, 20, null);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
In this part, BuArr are the 400 blocks divided from a BufferedImage, now i want them to be draw one by one, but the method can not draw the blocks separately, how can i do this?
Swing is single thread and not thread safe.
This means that you should not perform any long running or blocking (Thread.sleep) operations within the IU thread (the Event Dispatching Thread). It also means that you can not update, modify or create UI elements outside of the EDT context.
Instead, use a Swing Timer to generate a repeated callback at a specified interval and render the portions of the image to something like a BufferedImage, which you can the paint to the component via its paintComponent method...
See Concurrency in Swing and How to use Swing Timers for more details
Because it was a good time waster
This generates a List of Rectangles which represent the individual blocks I want to paint, I then randomise the List and run the Timer, picking the top most Rectangle off the List and using BufferedImage#getSubImage to draw it from the master to the buffer, which gets painted to the screen...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestImage {
public static void main(String[] args) {
new TestImage();
}
public TestImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage master;
private BufferedImage copy;
private List<Rectangle> blocks;
public TestPane() {
setBackground(Color.BLACK);
try {
master = ImageIO.read(new File("..."));
copy = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics();
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
g2d.setComposite(composite);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.fillRect(0, 0, master.getWidth(), master.getHeight());
g2d.dispose();
int blockSize = 40;
int width = master.getWidth();
int height = master.getHeight();
float aspect = Math.min(width, height) / (float) Math.max(width, height);
int blockHeight = blockSize;
blocks = new ArrayList<>(blockSize * 2);
for (int y = 0; y < master.getHeight(); y += blockHeight) {
if (y + blockHeight > master.getHeight()) {
blockHeight = master.getHeight() - y;
}
int blockWidth = blockSize;
for (int x = 0; x < master.getWidth(); x += blockWidth) {
if (x + blockWidth > master.getWidth()) {
blockWidth = master.getWidth() - x;
}
Rectangle block = new Rectangle(x, y, blockWidth, blockHeight);
blocks.add(block);
}
}
Collections.shuffle(blocks);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (blocks.isEmpty()) {
((Timer) e.getSource()).stop();
} else {
Graphics2D g2d = copy.createGraphics();
Rectangle block = blocks.remove(0);
g2d.drawImage(master.getSubimage(block.x, block.y, block.width, block.height), block.x, block.y, TestPane.this);
g2d.dispose();
repaint();
}
}
});
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return master == null ? new Dimension(200, 200) : new Dimension(master.getWidth(), master.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (copy != null) {
int x = (getWidth() - copy.getWidth()) / 2;
int y = (getHeight() - copy.getHeight()) / 2;
g2d.drawImage(copy, x, y, this);
}
g2d.dispose();
}
}
}
I'm fairly new to programming with graphics and I'm attempting to code a side scrolling 2D game. At the moment, I'm trying to figure out how to approach redrawing a scrolling image as it appears in the JFrame. I'm using 8x8 pixel blocks as images. One possible issue I thought about concerns moving a sprite just 1 or 2 pixels and still rendering each image as it appears pixel by pixel on/off of the screen. How do I go about rendering the image/blocks pixel by pixel instead of whole images should the sprite barely move? Any feedback is much appreciated!
This is a proof of concept only! I randomly generate the tiles that get painted, I hope you have some kind of virtual map setup so you know which tiles to paint at any given virtual point!
Basically, what this does, is when the screen is moved left or right, it shifts the "master" image left or right and stitches new tiles onto new edge
My test was using a style sheet of 31x31 cells (don't ask, I just grab it off the net)
This is VERY scaled down example of the output, it was running at 1100x700+
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Scroll {
public static void main(String[] args) {
new Scroll();
}
public Scroll() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage screen;
private BufferedImage styleSheet;
public TestPane() {
try {
styleSheet = ImageIO.read(getClass().getResource("/StyleSheet.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
ActionMap am = getActionMap();
am.put("left", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
stitch(-31);
}
});
am.put("right", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
stitch(31);
}
});
}
#Override
public void invalidate() {
screen = null;
super.invalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void stitch(int direction) {
if (screen == null) {
prepareScreen();
}
Random r = new Random();
BufferedImage update = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = update.createGraphics();
g2d.drawImage(screen, direction, 0, this);
int gap = direction < 0 ? (direction * -1) : direction;
int xOffset = 0;
if (direction < 0) {
xOffset = getWidth() - gap;
}
for (int x = 0; x < gap; x += 31) {
for (int y = 0; y < getHeight(); y += 31) {
xOffset += x;
int cellx = 2;
int celly = 2;
if (r.nextBoolean()) {
cellx = 7;
celly = 5;
}
BufferedImage tile = styleSheet.getSubimage((cellx * 33) + 1, (celly * 33) + 1, 31, 31);
g2d.drawImage(tile, xOffset, y, this);
}
}
g2d.dispose();
screen = update;
repaint();
}
protected void prepareScreen() {
if (screen == null) {
screen = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Random r = new Random();
Graphics2D g2d = screen.createGraphics();
for (int x = 0; x < getWidth(); x += 31) {
for (int y = 0; y < getHeight(); y += 31) {
int cellx = 2;
int celly = 2;
if (r.nextBoolean()) {
cellx = 7;
celly = 5;
}
BufferedImage tile = styleSheet.getSubimage((cellx * 33) + 1, (celly * 33) + 1, 31, 31);
g2d.drawImage(tile, x, y, this);
}
}
g2d.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (screen == null) {
prepareScreen();
}
g2d.drawImage(screen, 0, 0, this);
g2d.dispose();
}
}
}
I am currently working on a simple top down shooter. The object is a ball that slides around the screen, and I am trying to make a sort of wet-dragging affect.
I am using Java Swing and just the default Graphics2d lib inside.
This is what I have:
and this is my goal:
I need to know how I can make a curved line that has the ability to change alpha at the trailing end. I have searched online but I can only find non-dynamic solutions. (The tail needs to update as the player moves across the screen.)
A simple solution might be to simple add each point to a List of Points which before the player is moved.
You would simply then need to iterate this list and either simple use something like Graphics#drawLine or even GeneralPath to render the "drag" line, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Drag {
public static void main(String[] args) {
new Drag();
}
public Drag() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points;
private Point pos;
private int diametere = 10;
public TestPane() {
points = new ArrayList<>(25);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
ActionMap am = getActionMap();
am.put("left", new MoveAction(-5, 0));
am.put("right", new MoveAction(5, 0));
am.put("up", new MoveAction(0, -5));
am.put("down", new MoveAction(0, 5));
pos = new Point(100 - (diametere / 2), 100 - (diametere / 2));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (points.size() > 1) {
g2d.setColor(Color.RED);
GeneralPath path = new GeneralPath();
boolean started = false;
System.out.println("----");
for (Point p : points) {
if (started) {
System.out.println(p);
path.lineTo(p.x, p.y);
} else {
path.moveTo(p.x, p.y);
started = true;
}
}
g2d.draw(path);
}
int radius = (int) (diametere / 2d);
g2d.setColor(Color.GREEN);
g2d.draw(new Ellipse2D.Double(pos.x - radius, pos.y - radius, diametere, diametere));
g2d.dispose();
}
protected void moveBy(int xDelta, int yDelta) {
if (pos.x + xDelta < 0) {
xDelta = 0;
pos.x = 0;
} else if (pos.x + xDelta + diametere > getWidth()) {
xDelta = 0;
pos.x = getWidth() - diametere;
}
if (pos.y + yDelta < 0) {
yDelta = 0;
pos.y = 0;
} else if (pos.y + yDelta + diametere > getHeight()) {
yDelta = 0;
pos.y = getWidth() - diametere;
}
points.add(new Point(pos));
pos.x += xDelta;
pos.y += yDelta;
repaint();
}
public class MoveAction extends AbstractAction {
private int xDelta;
private int yDelta;
public MoveAction(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
moveBy(xDelta, yDelta);
}
}
}
}
Hmm.. maybe you need something like this:
public class BallArea extends JComponent {
static final int MAX_SIZE = 63;
static final BasicStroke stroke = new BasicStroke(5);
final Queue<Point> points = new LinkedList();
public BallArea() {
setSize(400, 400);
setBackground(Color.BLACK);
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
if (points.size() >= MAX_SIZE) {
points.poll();
}
points.add(e.getPoint());
repaint();
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(stroke);
int i = 1;
Point prev = null;
for (Point p : points) {
if (prev == null) {
prev = p;
continue;
}
g2.setColor(new Color(255, 0, 0, i*4));
g.drawLine(prev.x, prev.y, p.x, p.y);
i++;
prev = p;
}
}
}
What I have implemented till now in java is ask the user to upload an image from the directory. My next step is that when the image is loaded a grid is placed above that image just for visual purpose so that the image gets divided in a, say 10 x 10 grids. How do I implement this stuff? Here's what I have implemented till now.
JFileChooser choose=new JFileChooser();
choose.showOpenDialog(null);
File f=choose.getSelectedFile();
String filename=f.getAbsolutePath();
path.setText(filename);
BufferedImage img;
try {
img=ImageIO.read(f);
Image dimg = img.getScaledInstance(500,500,Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(dimg);
image_label.setIcon(imageIcon);
}
catch(Exception e) {
System.out.println(e);
}
paint the image in a panel
protected void paintComponent(Grapchics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
Then based on the the number of cells you want, say 10x10, just draw 100 cells (drawRect()) over the image. Something like
protected void paintComponent(Grapchics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
int cellHeight = (int)(getHeight() / 10);
int cellWidth = (int)(getWidth() / 10);
for (int y = 0; y < getWidth(); y += cellHeight) {
for (int x = 0; x < getHeight(); x += cellWidth){
g.drawRect(x, y, cellWidth, cellHeight);
}
}
}
I haven't test it, but the basic concept is there. You may also want to use variables (a constant probably) for the 10.
UPDATE 1
You can see the precision's a little off because I used int, but you can use doubles and draw by using Grapchics2D Rectangle2D.Double. I'm too lazy to change it
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageGrid extends JPanel {
private static final int CELLS = 10;
BufferedImage img;
public ImageGrid() {
try {
img = ImageIO.read(getClass().getResource("/resources/stackoverflow5.png"));
} catch (IOException ex) {
Logger.getLogger(ImageGrid.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
int cellHeight = (int) (getHeight() / CELLS);
int cellWidth = (int) (getWidth() / CELLS);
for (int y = 0; y < getHeight(); y += cellHeight) {
for (int x = 0; x < getWidth(); x += cellWidth) {
g.drawRect(x, y, cellWidth, cellHeight);
}
}
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(300, 300)
: new Dimension(img.getWidth(), img.getHeight());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
JPanel wrapperPanel = new JPanel(new GridBagLayout());
wrapperPanel.add(new ImageGrid());
frame.add(wrapperPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
UPDATE 2 With JLabel
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageGrid extends JLabel {
private static final int CELLS = 10;
BufferedImage img;
public ImageGrid() {
try {
img = ImageIO.read(getClass().getResource("/resources/stackoverflow5.png"));
setIcon(new ImageIcon(img));
} catch (IOException ex) {
Logger.getLogger(ImageGrid.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
int cellHeight = (int) (getHeight() / CELLS);
int cellWidth = (int) (getWidth() / CELLS);
for (int y = 0; y < getHeight(); y += cellHeight) {
for (int x = 0; x < getWidth(); x += cellWidth) {
g.drawRect(x, y, cellWidth, cellHeight);
}
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
JPanel wrapperPanel = new JPanel(new GridBagLayout());
wrapperPanel.add(new ImageGrid());
frame.add(wrapperPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
I have a paint method that I have draw a rectangle and move it across the screen and what I want it to do I when the rectangle goes off the screen to move it back to the start of the JFrame. I assume it would be something like if(rectangle.isoffthescreen){ put it back on the screen } but I don't know how to do that. Also, I want to know if you can do something to the rect like JFrame frame = new JFrame();, but for obviously for the rectangle. I'm sorry if this is confusing.
#MadProgrammer Here is where I am at so far
public class main extends JPanel {
public static int place = -350;
public Rectangle rect;
public int xDelta;
public main() {
rect = new Rectangle(0, 75, 50, 50);
xDelta = 4;
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rect.x += xDelta;
if (rect.x + rect.width > getWidth() - 1) {
rect.x = getWidth() - rect.width;
xDelta *= -1;
} else if (rect.x < 0) {
rect.x = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
Random r = new Random();
int r1;
r1 = r.nextInt(5);
if (r1 == 0) {
g2d.setColor(Color.WHITE);
} else if (r1 == 1) {
g2d.setColor(Color.BLUE);
} else if (r1 == 2) {
g2d.setColor(Color.RED);
} else if (r1 == 3) {
g2d.setColor(Color.GREEN);
} else if (r1 == 4) {
g2d.setColor(Color.PINK);
} else {
g2d.setColor(Color.CYAN);
}
place += 50;
rect = new Rectangle(place, 100, 300, 200);
g2d.draw(rect);
g2d.fill(rect);
g2d.dispose();
try {
Thread.sleep(400);
} catch (Exception e) {
}
repaint();
}
}
and
public class frame {
public static JFrame frame;
public static void main(String args[]){
frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setResizable(false);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
main m = new main();
m.setBackground(Color.BLACK);
frame.add(m);
}
}
I still can't get it to work.
First of, you should avoid overriding paint of top level containers and instead use something the extends from JComponent (like JPanel) and override it's paintComponent.
There are a number of reasons, but in your case, the frame contains a decoration which sits inside the viewable area.
The basic process would be to check edge cases...
if (box.x + box.width > getWidth() - 1) {
// The boxes right edge is beyond the right edge of it's container
} else if (box.x < 0) {
// The boxes left edge is beyond the left edge of it's container
}
This checks to see if the box's right edge is beyond the containers right edge and if the box's left edge is beyond the left edge of the container.
It would be a simple process to included vertical checking as well.
Updated with example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Move {
public static void main(String[] args) {
new Move();
}
public Move() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Rectangle box;
private int xDelta;
public TestPane() {
box = new Rectangle(0, 75, 50, 50);
xDelta = 4;
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
box.x += xDelta;
if (box.x + box.width > getWidth() - 1) {
box.x = getWidth() - box.width;
xDelta *= -1;
} else if (box.x < 0) {
box.x = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.fill(box);
g2d.dispose();
}
}
}
Update from OP's example code
Immediately, a number of things worry me...
Overriding paint
Calling Thread.sleep in the paint method
Calling repaint from within the paint method
Creating a new Rectangle in the paint method
The reliance on the place variable
Check out Performing Custom Painting for more details about painting in Swing
You should never block or perform long running processing the Event Dispatching Thread, this will prevent the EDT from processing (amongst other things) paint requests and new events. By calling Thread.sleep in the paint method, you are preventing Swing from updating the screen.
Check out Concurrency in Swing for more details.
Calling repaint (or any method that might call repaint) within a paint method is a sure way to consume you CPU cycle.
You may want to check out Painting in AWT and Swing for more details about the paint process in Swing
By creating a new Rectangle in the paint method, you are throwing away any changes that the Timer has made, effectively stopping you rectangle from moving effectively...
The place method is not required. Animation is the illusion of change over time, hence the use of the Timer and xDelta.
Updated based on your code example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Move {
public static void main(String[] args) {
new Move();
}
public Move() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Main());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Main extends JPanel {
public static int place = -350;
public Rectangle rect;
public int xDelta;
public Main() {
rect = new Rectangle(0, 75, 50, 50);
xDelta = 4;
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rect.x += xDelta;
if (rect.x + rect.width > getWidth() - 1) {
rect.x = getWidth() - rect.width;
xDelta *= -1;
} else if (rect.x < 0) {
rect.x = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Random r = new Random();
int r1;
r1 = r.nextInt(5);
if (r1 == 0) {
g2d.setColor(Color.WHITE);
} else if (r1 == 1) {
g2d.setColor(Color.BLUE);
} else if (r1 == 2) {
g2d.setColor(Color.RED);
} else if (r1 == 3) {
g2d.setColor(Color.GREEN);
} else if (r1 == 4) {
g2d.setColor(Color.PINK);
} else {
g2d.setColor(Color.CYAN);
}
// place += 50;
// rect = new Rectangle(place, 100, 300, 200);
g2d.draw(rect);
g2d.fill(rect);
g2d.dispose();
}
}
}