The Program use a rectangle in which a Ball can be caught from a JLabel with an Image.
The problem is in the Timer class, in which a counter counts, the time. While it counts the time is shown on a JLabel. But the Image that should catch the Ball, jumps every time to the start position, creating a tremble.
I tried to remove the JLabel and use instead System.out.println(), and it worked as well.
Perhaps the Swing Timer doesn't like calls for JLabel, what could be the cause?
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
timeL.setText("Time :" + df.format(duration - clockTime));
//System.out.println("Time :" + df.format(duration - clockTime));
The Code was modified a bit, it works as expected, I hope it's correct.
Now the Image may be moved around independently of the Ball's Speed, and the Image stays at the moved position.
To add the Picture, add in the Project Folder a new Folder, named "resources". I tested it with Netbeans 8.2 .
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
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 ImageMoveTest implements ActionListener {
JPanel panel;
Image rimg;
Thread t;
int x;
int y;
int v;
int z;
int n;
public static void main(String[] args) throws InterruptedException, IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new ImageMoveTest().startApp();
} catch (InterruptedException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public void startApp() throws InterruptedException, IOException {
panel = new DrawPanel();
InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("i6.jpeg");
BufferedImage img = ImageIO.read(inStream);
rimg = img.getScaledInstance(150, 150, Image.SCALE_SMOOTH);
MoveMouse mm = new MoveMouse();
panel.addMouseMotionListener((MouseMotionListener) mm);
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel).setBackground(Color.white);
f.setSize(750, 750);
f.setResizable(false);
f.setVisible(true);
f.setLocationRelativeTo(null);
MathC mc = new MathC();
t = new Thread(mc);
t.start();
}
class MoveMouse extends JPanel implements MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
v=e.getX();
z=e.getY();
this.repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
class MathC implements Runnable {
#Override
public void run() {
while(true) {
// x,y here
x = (int) (Math.random() * panel.getWidth());
y = (int) (Math.random() * panel.getHeight());
panel.repaint();
try {
t.sleep(700);
} catch (InterruptedException ex) {
Logger.getLogger(ImageMoveTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
class DrawPanel extends JPanel {
public void update(Graphics g) {
super.paintChildren(g);
}
public void paintChildren( Graphics g) {
super.paintChildren(g);
drawIt(g);
// repaint the backround to see the single circle moving
// draw the Ball
g.setColor(Color.red);
g.fillOval(x, y, 35, 35);
g.drawOval(x, y, 35, 35);
this.repaint();
}
public void drawIt(Graphics g) {
super.paintChildren(g);
// draw Rectangle
g.drawRect(0,0,this.getWidth(),this.getHeight());
// draw the Image
g.drawImage(rimg, v, z, this);
this.repaint();
}
}
}
Related
I am having trouble generating multiple oval shapes when clicking the panel of the frame. What I want is that it will generate many oval shapes and those shapes will move downward. One of the requirement is to use two multi threading. However in my case, the program I created is that, it will only generate one oval shape and the position is randomly changing. Can anyone please help me one this.
package ovalrandomcolors;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.List;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class OvalRandomColors extends JPanel{
private int ovalX = 50;
private int ovalY =50;
private int ovalPositionX = 250;
private int ovalPositionY = 250;
private Color color = Color.YELLOW;
public OvalRandomColors(){
setBackground(Color.DARK_GRAY);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);
g.setColor(color);
g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JFrame frame = new JFrame();
final OvalRandomColors oval = new OvalRandomColors();
oval.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
OvalWithThreading firstThread = new OvalWithThreading(oval);
OvalWithThreading secondThread = new OvalWithThreading(oval);
Thread first = new Thread(firstThread);
Thread second = new Thread(secondThread);
second.start();
first.start();
}
});
frame.add(oval);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,700);
frame.setVisible(true);
}
});
}
public void updateOval(){
int r = (int)(Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int)(Math.random() * 255);
color = new Color(r,g,b);
ovalPositionX = (int)(Math.random() * 78);
ovalPositionY = (int) (Math.random() * 245);
animateOval();
repaint();
}
public void animateOval(){
// ovalPositionX += 30;
ovalPositionY += 30;
}
public static class OvalWithThreading implements Runnable{
private final OvalRandomColors ovalShape;
public OvalWithThreading(OvalRandomColors oS){
this.ovalShape = oS;
}
#Override
public void run() {
for(;;){
ovalShape.updateOval();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(OvalRandomColors.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
Let's start with, Swing is not Thread safe, so having another Thread which update the state of objects which the UI depends to render requires some serious considerations. Normally, I'd recommend using a Swing Timer or SwingWorker to accomplish this, but those aren't the "requirements"
In order to render multiple objects, you need some way to store them, so you can update their states and renderer them. The simplest solution is a List, you can see Collections Trail for more details.
Now, if you also need to manage color, you can take a look at how I managed the deltas for each shape and should give you one idea for doing that
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 ReentrantLock shapesLock = new ReentrantLock();
private List<Ellipse2D> shapes;
public TestPane() {
shapes = new ArrayList<>(25);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
shapesLock.lock();
try {
shapes.add(new Ellipse2D.Double(e.getX() - 5, e.getY() - 5, 10, 10));
} finally {
shapesLock.unlock();
}
}
});
Thread t = new Thread(new Runnable() {
private Map<Shape, Double> deltas = new HashMap<>();
#Override
public void run() {
while (true) {
try {
shapesLock.lock();
try {
Rectangle containerBounds = getBounds();
containerBounds.setLocation(0, 0);
Iterator<Ellipse2D> it = shapes.iterator();
while (it.hasNext()) {
Ellipse2D shape = it.next();
Rectangle2D bounds = shape.getBounds2D();
double y = bounds.getY();
Double delta = deltas.get(shape);
if (delta == null) {
delta = 0d;
}
y += delta;
shape.setFrame(bounds.getX(), y, bounds.getWidth(), bounds.getHeight());
if (containerBounds.contains(shape.getBounds())) {
delta = Math.min(delta + 0.25, 6d);
deltas.put(shape, delta);
} else {
it.remove();
}
}
} finally {
shapesLock.unlock();
}
repaint();
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
}
});
t.setDaemon(false);
t.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
shapesLock.lock();
try {
for (Ellipse2D shape : shapes) {
g2d.fill(shape);
}
} finally {
shapesLock.unlock();
}
g2d.dispose();
}
}
}
I am new to Java and need help. I am making a GUI for an application using images made from photoshop, and want to create a menu using images which highlights when user hover mouse over them. I have tried mouseEntered(); method by getting mouse x, y co-ordinates but it's not working. Here is the code.
public class GUI extends JComponent{
public void paintComponent(Graphics g){
super.paintComponent(g);
ImageIcon exitBtnImg = new ImageIcon("src/images/userInterface/exitBtn.png");
g.drawImage(exitBtnImg.getImage(), 0, 5, this);
mouseHandler handler = new mouseHandler();
addMouseListener(handler);
}
}
public class mouseHandler implements MouseListener{
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
if((e.getX()>100&&e.getX()<300)&&(e.getY()>50&&e.getY()<196)){
repaint();
}
}
#Override
public void mouseExited(MouseEvent e) {
}
}
Don't load resources in paintComponent, your paint method should run as fast as it can
Don't add listeners within the paint methods, this will get called a lot, so you're just repeatedly adding new listeners each time your component is painted
Use a MouseMotionListener instead of a MouseListener, you want the mouseMoved event
You need some way to know where the image is painted, so you can determine if the mouse moved within it's bounds.
Have a look at How to Write a Mouse-Motion Listener and Painting in AWT and Swing for more details.
This example uses a simple Rectangle to define the location that the image is painted within, when the mouse moves within the confines of that Rectangle, a flag is set and the component is repainted, which paints a alpha based highlight effect over the image
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
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);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
private Rectangle drawRectangle;
private boolean highlight = false;
public TestPane() throws IOException {
img = ImageIO.read(...);
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
highlight = drawRectangle.contains(e.getPoint());
repaint();
}
});
int width = getPreferredSize().width;
int height = getPreferredSize().height;
int x = (width - img.getWidth()) / 2;
int y = (height - img.getHeight()) / 2;
drawRectangle = new Rectangle(x, y, img.getWidth(), img.getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, drawRectangle.x, drawRectangle.y, this);
if (highlight) {
g2d.setColor(Color.RED);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(drawRectangle);
}
g2d.dispose();
}
}
}
Now, having said all that, you might be better off using the rollover capabilities of JButton, which will basically do the same thing.
See How to Use Buttons, Check Boxes, and Radio Buttons for more details
I am having trouble with my Java project for school.
The plan was to make a simple game where you need to catch the ball and if you catch the ball you will get points.
At the moment I have 2 problems:
I have no idea how I make the balls appear at a random width and make it stay at that width (cause random value is constantly changing ).
How can I make a statement that checks if the catcher caught the ball?
This is my current code:
import instruct.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.swing.Timer;
public class opdracht extends WindowPanel implements MouseMotionListener {
List<comet> comets;
Image afb1;
Image afb2;
Image comet;
int xmuis;
int score;
int random;
int h;
int plaats;
static int randomNum;
private static final int D_W = 700;
private static final int X_INC = 10;
public opdracht() throws IOException {
score = 0;
h = -100;
afb1 = ImageIO.read(new File("afb/space.jpg"));
afb2 = ImageIO.read(new File("afb/pipe.png"));
BufferedImage cometbuf = ImageIO.read(new File("afb/comet.png"));
File output = new File("comet.png");
ImageIO.write(cometbuf, "png", output);
comet = ImageIO.read(new File("comet.png"));
addMouseMotionListener(this);
try {
drawcomet();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
plaats = randomNum;
comets = new LinkedList<>();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Iterator<comet> it = comets.iterator();
while (it.hasNext()) {
comet ball = it.next();
if (ball.h > D_W) {
it.remove();
System.out.println(comets.size());
} else {
ball.h += X_INC;
repaint();
}
}
}
});
timer.start();
}
public void paintComponent(Graphics g) {
g.drawImage(afb1, 0, 0, 1200, 800, this);
g.setColor(Color.yellow);
g.setFont(new Font("TimesRoman", Font.PLAIN, 30));
g.drawString("score = " + score, 1020, 30);
for (comet ball : comets) {
ball.drawcomet(g);
}
g.drawImage(afb2, xmuis, 730, 70, 75, this);
}
public static void randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
randomNum = rand.nextInt((max - min) + 1) + min;
System.out.print(randomNum);
}
public void drawcomet() throws InterruptedException {
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
comets.add(new comet(comet));
}
}, 0, 2, TimeUnit.SECONDS);
}
public class comet {
protected int h;
Image comet;
public comet(Image image) {
comet = image;
}
public void drawcomet(Graphics g) {
g.drawImage(comet, plaats, h, 75, 50, null);
}
}
public void mouseMoved(MouseEvent e) {
xmuis = e.getX();
repaint();
}
public void mouseDragged(MouseEvent e) {
// do something
}
public static void main(String[] a) throws IOException {
new opdracht().createGUI();
}
}
package instruct;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class WindowPanel extends JPanel {
JFrame frame;
public WindowPanel() {
this.setPreferredSize(new Dimension(1200, 800));
this.setFocusable(true);
this.requestFocusInWindow();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// System.out.println( "class: "+ getClass().getName() );
frame.setTitle("Space Game");
}
protected void createAndShowGUI() {
frame = new JFrame();
frame.setSize(1200, 800);
frame.setLocation(300, 100);
frame.setResizable(false);
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor =
Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0),
"blank cursor");
// Set the blank cursor to the JFrame.
frame.getContentPane().setCursor(blankCursor);
}
public void createGUI() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public JFrame getFrame() {
return frame;
}
}
First question: "I have no idea how i make the ball's appear at a random width."
I assume you want to give the ball (= an instance of the comet class) a random x position (= the plaats field)? You could make the following changes (which make the randomNum field no longer required, this could now be a local variable):
//plaats = randomNum;
plaats = randInt(0, 1200);
// more code...
//public static void randInt(int min, int max) {
public static int randInt(int min, int max) {
// more code...
return randomNum;
}
Second question: "And how can make a statement that checks if catcher cached ball."
To determine whether the ball is catched, you could compare xmuis to plaats when the y coordinate of the ball (the h field?) is equal to the top of the pipe (around 730).
I'm trying to add a image to a java canvas.
I'm using the "ImageIO.read" to get the image source. The problem i'm facing is that i don't know how to display it on the canvas after reading the image location. Also later i will need to load a different image(e.g. after a button pressed) how can i do this. The update (canvas.update) method needs a "Graphics" parameter instead of an image.
Below you'll find my code simplified (i left out all code that's not relevant to the canvas issue.)
public class MainWindow {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
window = new MainWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
Canvas csStatusImage = new Canvas();
csStatusImage.setBounds(393, 36, 200, 200);
frame.getContentPane().add(csStatusImage);
Image iMg;
try {
iMg = ImageIO.read(new File("Images/Error_status_1.png"));
csStatusImage.imageUpdate(iMg, 10, 2, 2, 9, 10);
csStatusImage.checkImage(iMg, (ImageObserver) this);
csStatusImage.createImage((ImageProducer) iMg);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
First of all, you going to need some way to paint the image. To achieve this, you can override the paint method of the java.awt.Canvas class
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
Frame frame = new Frame("Testing");
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.add(new ImageCanvas());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class ImageCanvas extends Canvas {
private BufferedImage img;
public ImageCanvas() {
try {
img = ImageIO.read(new File("Images/Error_status_1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (img != null) {
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g.drawImage(img, x, y, this);
}
}
}
}
I have to tell you, AWT is out-of-date by some 15+ years, replaced by Swing. You may find it hard to get additional support with this API. If you can, you'd better of using Swing or JavaFX
I have a program that scales an image to the size of the screen. I currently have a component listener listening for a componentResized event, but this is not what I want. I would like the method to only be called one the user lift's there finger off their mouse, not as they are doing the resizing. This way, my image will not constantly be resizing to the user's specifications.
Thanks!
A solution is to supply a Swing Timer which is reset each time componentResized is called. This injects a small delay between the last resize event and the time you should perform the resize action.
import javax.swing.Timer;
//...
// Declare an instance variable...
private Timer resizeTimer;
//...
// Probably in you classes constructor
resizeTimer = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Actually perform the resizing of the image...
resizeBackgroundImage();
}
});
// Don't want a repeating event...
resizeTimer.setRepeats(false);
//...
public void componentResized(ComponentEvent evt) {
resizeTimre.restart();
}
This basically, sets it up so that it will require 250 milliseconds between resize events before an attempt is made to resize the image. You can play around with the value to suit your own needs.
Updated with runnable example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
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 RescaleTest {
public static void main(String[] args) {
new RescaleTest();
}
public RescaleTest() {
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 master;
private Image scaled;
private Timer resizeTimer;
public TestPane() {
try {
master = ImageIO.read(new File("/path/to/your/image"));
scaled = master;
} catch (IOException exp) {
exp.printStackTrace();
}
resizeTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resizeBackground();
}
});
resizeTimer.setRepeats(false);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
resizeTimer.restart();
}
});
}
protected void resizeBackground() {
// This is not my preferred scaling process, I prefer to use
// a divide and conqure approach and do so in the background
// where possible, but this is beyond the scope of the question...
if (getWidth() < getHeight()) {
scaled = master.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
} else {
scaled = master.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
repaint();
}
#Override
public Dimension getPreferredSize() {
return master != null ? new Dimension(master.getWidth(), master.getHeight()) : new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (scaled != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g2d.drawImage(scaled, x, y, this);
g2d.dispose();
}
}
}
}
nb: The scaling used in this example is not my preferred method and was done for demonstration purposes only. See The Perils of Image.getScaledInstance() for details and Scale the ImageIcon automatically to label size for an alterantive approach...
If you put Toolkit.getDefaultToolkit().setDynamicLayout(false); right inside of main it will disable the frame from updating dynamically as you increase/decrease it's size. The ui will only be updated after you stop resizing.
import MainMenu.GameManager;
import java.awt.*;
import java.io.IOException;
public class Main {
Main(){
}
public static void main(String[] args) throws IOException {
GameManager manager = new GameManager();
Toolkit.getDefaultToolkit().setDynamicLayout(false);
}
}