Change Images on jframe when a button is clicked in Java - java

I have been trying to figure this out why not the next picture showing on the same panel after click the button. I want to separate those classes not into one class and used repaint() to re-invoke paintComponent() with the new pic.
Please help me. I am almost dying :(
when I run this, the first picture appears well. when the button is clicked to change the first picture to the second one, the Panel just keep on showing the first picture.
Thank you.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
class drawImage extends JPanel {
BufferedImage[] b = new BufferedImage[2];
public drawImage() {
try {
b[0] = ImageIO.read(new File("img/gameOn.png"));
b[1] = ImageIO.read(new File("img/gameOff.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(b[0], 0, 0, null);
}
public void setNextImage(BufferedImage image) {
b[0] = image;
repaint();
}
public BufferedImage getB0() {
return b[0];
}
public BufferedImage getB1() {
return b[1];
}
}// end drawImage
class clickedListener implements ActionListener {
BufferedImage pre = new drawImage().getB0();
BufferedImage next = new drawImage().getB1();
#Override
public void actionPerformed(ActionEvent e) {
new drawImage().setNextImage(next);
}
}
public class buttonFrame {
public static void main(String[] args) throws IOException {
JFrame jf = new JFrame("Button & Frame");
JButton btn = new JButton("Click");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
jf.setLayout(new GridLayout(2, 0));
jf.add(new drawImage());
jf.add(btn);
jf.setSize(200, 250);
btn.addActionListener(new clickedListener());
}
}

Why not change your approach and make use of a JLabel instead? Set your image as an icon on the label and add it to your JPanel:
BufferedImage image = ImageIO.read(new File("image-path"));
JLabel label = new JLabel(new ImageIcon(image));
panel.add(label);
You can then make subsequent calls to JLabel#setIcon(...) each time you want the image to change.

You can also use ImageIcon like this
image = new ImageIcon(imageList[1]);
and when each time button is clicked you can change image like this
label.setIcon(image);

Related

how to add image to the JFrame

I need help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame. d help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame.
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.JFrame;
class PPJJ extends JFrame implements ActionListener, KeyListener
{
public void paint(Graphics g) {
Toolkit t=Toolkit.getDefaultToolkit();
Image i=t.getImage("tenor.gif");
g.drawImage(i, 120,100,this);
}
public static void main(String[] args)
{
JFrame frame = new JFrame("VOLUNTEER FOR THING");
PPJJ obj = new PPJJ();
JPanel panel = new JPanel();
JLabel lname = new JLabel("Enter your name here");
JTextField tname = new JTextField(21);
JButton btn = new JButton("Click");
btn.addActionListener(obj);
tname.addKeyListener(obj);
panel.add(lname);
panel.add(tname);
panel.add(btn);
frame.add(panel);
frame.setSize(300, 130);
frame.show();
frame.setLocationRelativeTo(null);
PPJJ m = new PPJJ();
JFrame f =new JFrame();
//f.add(m);
f.setSize(500,500);
f.setVisible(true);
frame.add(new JLabel(new ImageIcon("volunteer.jpeg")));
}
public void actionPerformed(ActionEvent e)
{
String s = e.getActionCommand();
if(s.equals("Click here")){
JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_ENTER){
JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
}
}
#Override
public void keyReleased(KeyEvent arg) {}
#Override
public void keyTyped(KeyEvent arg) {}
}
Oh, animated GIFs 😓.
Image handling isn't simple in most cases, but animated GIFs are whole other level of pain ... I mean fun.
Normally, I prefer to use ImageIO.read, but ImageIO returns a BufferedImage and it's not (easily) possible to then render animated GIFs through it.
The "easy" route of displaying animated GIFs is by using Image or ImageIcon.
The first step is get your image "embedded" within your application context (assuming that you're not allowing the user to select the image). How this is done will depend on your IDE and build system (Eclipse and Netbeans allow you to simply include them in the src folder, when you're not using Maven).
Next, you want to use Class#getResource to obtain a URL reference to the embedded resource. In this case, you can use ImageIO.read, ImageIcon(URL) or Toolkit#getImage(URL) to load the image. But, as I've said, ImageIO.read isn't going to help you.
Next, you need a component which can render the image, lucky for us, Swing can do this pretty much auto magically for use, all we need to do is make sure the component is passed as the ImageObserver reference, for example...
public class BackgroundPane extends JPanel {
private Image image;
public BackgroundPane(Image image) {
this.image = image;
}
#Override
public Dimension getPreferredSize() {
Image image = getBackgroundImage();
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
public Image getBackgroundImage() {
return image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = getBackgroundImage();
if (image == null) {
return;
}
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
Also, note, JLabel supports animated GIFs via it's icon property as well, but look at How to set a background picture in JPanel for reasons why you shouldn't use a JLabel as a background container.
Now, all we need to do is load the image, pass it to the background, add what ever content we need to the component and show it, easy, or at least it should be. ImageIcon and Toolkit#getImage both off load the reading of the image to a background thread, so inspecting the images dimensions before the image is loaded will return 0x0 😓, so, we need to wait for it to load (this is why I prefer ImageIO.read as it won't return until the image is loaded or an error occurs).
Something like...
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
BackgroundPane backgroundPane = new BackgroundPane(image);
// Did I mention I had this workflow, but ImageIO doesn't
// support animated images, without a lot of work
MediaTracker mt = new MediaTracker(backgroundPane);
mt.addImage(image, 0);
mt.waitForAll();
// The image is now loaded, hooray for us
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
BackgroundPane backgroundPane = new BackgroundPane(image);
// Did I mention I had this workflow, but ImageIO doesn't
// support animated images, without a lot of work
MediaTracker mt = new MediaTracker(backgroundPane);
mt.addImage(image, 0);
mt.waitForAll();
backgroundPane.setLayout(new GridBagLayout());
JLabel label = new JLabel("All your kitty is belong to us");
label.setForeground(Color.WHITE);
backgroundPane.add(label);
JFrame frame = new JFrame();
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class BackgroundPane extends JPanel {
private Image image;
public BackgroundPane(Image image) {
this.image = image;
}
#Override
public Dimension getPreferredSize() {
Image image = getBackgroundImage();
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
public Image getBackgroundImage() {
return image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = getBackgroundImage();
if (image == null) {
return;
}
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
}
Please note...
If you're not using an animated GIF, then you can just use ImageIO.read instead of Toolkit#getImage and you won't need to wait (as ImageIO.read works in the current thread), in which case the code would look more like...
try {
BackgroundPane backgroundPane = new BackgroundPane(ImageIO.read(getClass().getResource("/images/kitty.gif")));
backgroundPane.setLayout(new GridBagLayout());
JLabel label = new JLabel("All your kitty is belong to us");
label.setForeground(Color.WHITE);
backgroundPane.add(label);
JFrame frame = new JFrame();
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
(the BackgroundPane code doesn't change)

Wrong RGB values are returned

I am trying to get the RGB value of a pixel of an image. (The pixel that the mouse is over). Here is the code which adds the image and the code which attends to the mouse ::
/// I got this code somewhere from StackOverFlow;
///Couldn't find the link;
label = new JLabel();
try {
// THIS PICTURE IS NOT MINE
targetImg = ImageIO.read(new java.net.URL("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFAhy8GM1F3_TyPjG7ezbeFRUy00PN4hpJCA&usqp=CAU"));
label.setIcon(new ImageIcon(rescale(targetImg)));
panel1.add(label);
fields = new JPanel();
fields.setBorder(new EmptyBorder(5, 5, 5, 5));
red = new JTextField(3);
green = new JTextField(3);
blue = new JTextField(3);
red.setEditable(false);
green.setEditable(false);
blue.setEditable(false);
fields.add(red);
fields.add(green);
fields.add(blue);
panel1.add(fields);
label.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
try{
int packedInt = targetImg.getRGB(e.getX(), e.getY());
Color color = new Color(packedInt, true);
fields.setBackground(color);
red.setText(Integer.toString(color.getRed()));
green.setText(Integer.toString(color.getGreen()));
blue.setText(Integer.toString(color.getBlue()));
}
catch (ArrayIndexOutOfBoundsException exception) { }
}
});
} catch (IOException ex) {
ex.printStackTrace();
}
This runs and compiles fine; However, sometimes the color returned by the RGB is not the color my mouse is on; Here is a pic ::
https://i.stack.imgur.com/R5qIx.png
Note: The white cross is an approximate location of where it is; A screenshot apparently does not take the mouse too.
The code is also laggy. Sometimes it hangs on one pixel and I have to wait until it runs again.
Why does this happen, and what can I do to prevent this? How can I solve this problem?
Since you only provided a code snippet, I created the following GUI.
Since the picture was so small, I put it under the RGB display.
The main problem was matching coordinate systems so that the mouse pointer would point to the pixel in the image. When you put the image inside a JLabel, you have to translate the mouse coordinate to an image coordinate.
I sidestepped the coordinate system problem by creating a drawing JPanel. By drawing the image on a drawing JPanel and adding the MouseMotionListener to the drawing JPanel, the mouse coordinates match the image coordinates.
I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created a JFrame, an RGB JPanel, and a drawing JPanel. The JFrame methods must be executed in a specific order. This is the order I use for all my Swing applications.
The RGB JPanel uses a FlowLayout to separate the red, green, and blue JTextFields.
The drawing JPanel draws the image. The drawing JPanel is the same size as the image. Again, by drawing the image on a drawing JPanel and adding the MouseMotionListener to the drawing JPanel, the mouse coordinates match the image coordinates.
I made the ColorListener a separate class. I basically copied your code to the mouseMoved method.
Here's the complete runnable code. I made the classes inner classes so I could paste this code as one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class RGBProcessor implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new RGBProcessor());
}
private BufferedImage image;
private Color panelColor;
private DrawingPanel drawingPanel;
private JPanel rgbPanel;
private JTextField redField;
private JTextField greenField;
private JTextField blueField;
public RGBProcessor() {
this.panelColor = Color.RED;
this.image = getImage();
this.drawingPanel = new DrawingPanel(this, image);
this.rgbPanel = createRGBPanel();
}
#Override
public void run() {
JFrame frame = new JFrame("RGB Processor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(rgbPanel, BorderLayout.BEFORE_FIRST_LINE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createRGBPanel() {
JPanel panel = new JPanel();
panel.setBackground(panelColor);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
redField = new JTextField(4);
redField.setEditable(false);
panel.add(redField);
greenField = new JTextField(4);
greenField.setEditable(false);
panel.add(greenField);
blueField = new JTextField(4);
blueField.setEditable(false);
panel.add(blueField);
return panel;
}
private BufferedImage getImage() {
try {
return ImageIO.read(new URL("https://encrypted-tbn0.gstatic.com/"
+ "images?q=tbn:ANd9GcSFAhy8GM1F3_TyPjG7ezbe"
+ "FRUy00PN4hpJCA&usqp=CAU"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void setPanelColor(Color color) {
this.panelColor = color;
this.rgbPanel.setBackground(color);
}
public JTextField getRedField() {
return redField;
}
public JTextField getGreenField() {
return greenField;
}
public JTextField getBlueField() {
return blueField;
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage image;
public DrawingPanel(RGBProcessor frame, BufferedImage image) {
this.image = image;
this.setPreferredSize(new Dimension(image.getWidth(),
image.getHeight()));
this.addMouseMotionListener(new ColorListener(frame, image));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public class ColorListener extends MouseAdapter {
private RGBProcessor frame;
private BufferedImage image;
public ColorListener(RGBProcessor frame, BufferedImage image) {
this.frame = frame;
this.image = image;
}
#Override
public void mouseMoved(MouseEvent event) {
int packedInt = image.getRGB(event.getX(), event.getY());
Color color = new Color(packedInt, true);
frame.setPanelColor(color);
frame.getRedField().setText(Integer.toString(color.getRed()));
frame.getGreenField().setText(Integer.toString(color.getGreen()));
frame.getBlueField().setText(Integer.toString(color.getBlue()));
}
}
}

JFrame does not show picture from JLabel

my JFrame does not show the image of my JLabel.
The JFrame is shown but without the background image.
Expected result was: JFrame that shows a background image ("stelle.png").
I'd greatly appreciate if anyone could help :-)
Thanks!
Simon
public static void main(String[] args) {
new Gui();
}
public class Label extends JLabel {
#Override protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g.drawImage(Var.quadro, 0, 0, 800,600, null);
repaint();
}
}
public class Var {
static BufferedImage quadro;
public Var(){
try {
quadro = ImageIO.read(new File("quadri/stelle.png"));
}
catch (IOException e) {
e.printStackTrace();
System.out.println("No picture");
}
}
}
public class Gui {
public Gui(){
JFrame rahmen = new JFrame();
rahmen.setSize(800,600);
rahmen.setLocationRelativeTo(null);
rahmen.setVisible(true);
rahmen.setResizable(false);
rahmen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
rahmen.setLayout(null);
rahmen.setTitle("Gioco");
Label label = new Label();
label.setVisible(true);
label.setBounds(0, 0, 800, 600);
rahmen.add(label);
}
}
Hi Have tweaked your solution below:
keep the package structure intact for the Test.java(can copy all code in it) and your pic stelle.png, refer the attached image below for this example to work seem less.
for incorporating changes in your own structure please keep image in a relative package quadri (refer the attached image, see how i kept it)
Please pay attention to my comments.
package com.demo.test.stack;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
//Main class for executing test
public class Test {
public static void main(String[] args) {
new Gui();
}
}
//this is you extended Label class be careful while importing
class Label extends JLabel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g.drawImage(Var.quadro, 0, 0, 800, 600, null);
repaint();
}
}
class Var {
static BufferedImage quadro;
//initializing the static variable in static class block (since you are using it directly)
static {
try {
//gettting the absolute path of your image
URL url = Test.class.getResource("quadri/stelle.png");
System.out.println(url.getPath());
quadro = ImageIO.read(new File(url.getPath()));
System.out.println("quadro: " + quadro);
} catch (IOException e) {
e.printStackTrace();
System.out.println("No picture");
}
}
}
//your feature class
class Gui {
public Gui() {
JFrame rahmen = new JFrame();
rahmen.setSize(800, 600);
rahmen.setLocationRelativeTo(null);
rahmen.setVisible(true);
rahmen.setResizable(false);
rahmen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
rahmen.setLayout(null);
rahmen.setTitle("Gioco");
Label label = new Label(); //<<this label is your extended label (i.e com.demo.test.stack.Label)and not awt label
label.setVisible(true);
label.setBounds(0, 0, 800, 600);
rahmen.add(label);
}
}
Let me know if you ave any other queries.
Regards and welcome to SO.
Cheers

Java problems with gif in label

A gif that I tried to put into a JPanel isn't showing up after clicking the button that triggers it until I resize the window. When it does show up, it does not fit the JPanel and is not animated. I looked at several posts that dealt with this but I don't understand how to use them in my case.
/*
* Author: Raymo111
* Date: 13/04/2018
* Description: Wishes happy birthday to a special someone
*/
//Imports java GUI classes
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
// Main class with JFrame and ActionListener enabled
public class Happy_Birthday_GUI extends JFrame implements ActionListener {
// Class variables
private static JButton startButton = new JButton("CLICK TO START");
private static JPanel startPanel = new JPanel(), gifPanel = new JPanel();
private static Color blue = new Color(126, 192, 238), pink = new Color(255, 192, 203);
private static GridLayout grid1 = new GridLayout(1, 1);
// Constructor
public Happy_Birthday_GUI() {
// Initial screen
startButton.addActionListener(this);
startButton.setFont(new Font("Comic Sans MS", Font.PLAIN, 50));
startPanel.setLayout(grid1);
startPanel.add(startButton);
startPanel.setBorder(BorderFactory.createLineBorder(blue, 100));
startButton.setBackground(pink);
getContentPane().add(startPanel);
// Sets title, size, layout (grid 1x1), and location of GUI window (center)
setTitle("Happy Birthday from Dolphin");
setSize(840, 840);
setLayout(grid1);
setLocationRelativeTo(null);
setVisible(true);
}
// Main method
public static void main(String[] args) {
new Happy_Birthday_GUI();
}
// Action Performed method
public void actionPerformed(ActionEvent event) {
// Proceed to gif and song
if (startButton == event.getSource()) {
getContentPane().removeAll();
BufferedImage dolphin;
gifPanel.setLayout(grid1);
gifPanel.setBorder(BorderFactory.createLineBorder(pink, 100));
try {
dolphin = ImageIO.read(new File("C:\\Users\\raymo\\Pictures\\dolphin.gif"));
JLabel gifLabel = new JLabel(new ImageIcon(dolphin));
gifPanel.add(gifLabel);
} catch (IOException e) {
e.printStackTrace();
}
getContentPane().add(gifPanel);
}
}
}
Here is dolphin.gif. It's cute.
How do I get it to show up immediately after clicking the start button as an animated gif that fits the JPanel? Thanks in advance.
BufferedImage doesn't support painting animated Gifs, instead, you'll need to make use of Image (or preferably, ImageIcon).
This could then be applied directly to a JLabel, which will perform the animation operation itself.
animated gif that fits he JPanel?
Okay, that's a much more complex problem. One approach would be to convert the Gif to the required size, but needless to say, that's very, very complex.
A simpler solution might be to use a AffineTransform and scale the image to meet the requirements of the component itself. This would require a custom component, capable of calculating the scale and painting each frame of the image.
Luckily for you, JPanel is an ImageObserver, this means it's capable of painting the gif animation
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
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 ImageIcon image;
public TestPane() {
image = new ImageIcon("/Users/swhitehead/Downloads/NbENe.gif");
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
#Override
protected void paintComponent(Graphics g) {
int imageWidth = image.getIconWidth();
int imageHeight = image.getIconHeight();
if (imageWidth == 0 || imageHeight == 0) {
return;
}
double widthScale = (double)getWidth() / (double)imageWidth;
double heightScale = (double)getHeight() / (double)imageHeight;
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image.getImage(), AffineTransform.getScaleInstance(widthScale, heightScale), this);
g2d.dispose();
}
}
}
I tried to put into a JPanel isn't showing up after clicking the button
When you add (or remove) components from a visible GUI the basic code is:
panel.add(...);
panel.revalidate();
panel.repaint();
The revalidate() is need to invoke the layout manager so the component is given a size.
is not animated.
Use a JLabel with an ImageIcon to display images. A JLabel will animated the gif.
When it does show up, it does not fit the JPanel and
You can try the Stretch Icon which is designed to fill the space available to the label.
I ended up doing:
gifPanel.add(new TestPane());
getContentPane().add(gifPanel);
revalidate();
repaint();
using camickr's revalidate and repaint, and MadProgrammer's TestPane class,
which worked very well to get the gif to animate, resize correctly and display immediately.

How would I change the JFrame background image while project is running

I set my background with
static JLabel board = new JLabel(new ImageIcon("img/rsz_board.png"));
frame.setContentPane(board);
And I tried to change the background with a button by doing this:
static JLabel board2 = new JLabel(new ImageIcon("img/board.png"));
JButton button2 = new JButton("Test");
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
frame.setContentPane(board2);
}
});
When I click the button, nothing will happen. If I click the button and then resize the window by dragging it with my cursor, the background will change but all my buttons will disappear. What am I doing wrong?
I think you should use revalidate() and repaint() after changing the background.
try this:
static JLabel board2 = new JLabel(new ImageIcon("img/board.png"));
JButton button2 = new JButton("Test");
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
frame.setContentPane(board2);
frame.revalidate();
frame.repaint();
}
});
If I click the button and then resize the window by dragging it with my cursor, the background will change but all my buttons will disappear
That is because all the buttons have been added to the "board" component not the "board2" component.
I tried to change the background with a button by doing this:
Don't change the label that is being used as the content pane. Instead change the Icon of the label:
//frame.setContentPane(board2);
board.setIcon( new ImageIcon("img/board.png") );
Perhaps a better way to do what you want: create a JPanel that draws the image in the background within its paintComponent method, that has its own layout manager which helps allow you to add components to the JPanel in any fashion you deem appropriate. You would give this class an Image field, and then within the paintComponent method, draw whatever image is being referenced by that field. Or if you want to swap a collection of images, give it an ArrayList<Image> field (below called images), and then draw the current image that is referenced by an index to that list (in my code below called imageIndex).
Comments on your code:
You're using static variables for some Swing components, and that suggests that you should re-think your design. Only declare static that which makes sense being static, and Swing GUI components are almost never in that category.
When you use a JLabel as you're using it, the label always sizes to the image and the text it holds (if any) which is OK for some applications, but dangerous for others. A JPanel will set its preferred size to that of the components it holds depending on the layout. That all changes of course if you explicitly change its getPreferredSize() method as I have done.
For example, compile and run the complete program code below:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class ChangeBackground extends JPanel {
public static final String ROOT_PATH = "https://upload.wikimedia.org/wikipedia/commons/thumb/";
public static final String[] IMG_PATHS = {
"0/01/Sundomecloseup.JPG/640px-Sundomecloseup.JPG",
"3/31/Hanalei,_Kauai_HI.JPG/640px-Hanalei,_Kauai_HI.JPG",
"a/a3/Castle_of_Vajdahunyad.jpg/640px-Castle_of_Vajdahunyad.jpg",
"d/d6/HeratFridayMosque.jpg/640px-HeratFridayMosque.jpg",
"1/16/Hebridean_ram.jpg/640px-Hebridean_ram.jpg",
"1/11/Ouagadougou_Maison_du_peuple.jpg/640px-Ouagadougou_Maison_du_peuple.jpg",
"9/96/Menger-Schwamm-einfarbig.jpg/640px-Menger-Schwamm-einfarbig.jpg",
"4/4f/Olympias.1.JPG/640px-Olympias.1.JPG",
"1/18/Uscapitolindaylight.jpg/640px-Uscapitolindaylight.jpg",
"9/9a/Below_Golden_Gate_Bridge.jpeg/640px-Below_Golden_Gate_Bridge.jpeg",
"2/29/Eiffel_Tower_(2962488972).jpg/640px-Eiffel_Tower_(2962488972).jpg",
"8/8f/Notre-Dame_Cathedral_Basilica.jpg/640px-Notre-Dame_Cathedral_Basilica.jpg"
};
private static final int PREF_W = 640;
private static final int PREF_H = 480;
private List<Image> images = new ArrayList<>();
private int imageIndex = 0;
public ChangeBackground(List<Image> images) {
this.images = images;
add(new JButton(new NextImageAction("Next Image")));
}
public void nextImage() {
imageIndex++;
imageIndex %= images.size();
repaint();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class NextImageAction extends AbstractAction {
public NextImageAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent arg0) {
nextImage();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(images.get(imageIndex), 0, 0, this);
}
private static void createAndShowGui(final List<Image> images) {
ChangeBackground mainPanel = new ChangeBackground(images);
JFrame frame = new JFrame("ChangeBackground");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
final List<Image> imgs = new ArrayList<>();
for (String imagePath : IMG_PATHS) {
imagePath = ROOT_PATH + imagePath;
try {
URL imgUrl = new URL(imagePath);
imgs.add(ImageIO.read(imgUrl));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
SwingUtilities.invokeLater(() -> createAndShowGui(imgs));
}
}

Categories