I'm trying to make a window that switches between pics when the button "change" is pressed. When I'm trying to run the program, the Java logo pops up like the program is about to start, but then it just disappear. I'm kind of stuck now and I'm hoping that someone can give me a hint about what might be wrong.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.imageio.*;
import javax.swing.*;
public class ImageViewer extends JFrame{
private JPanel panel;
private JLabel imageLabel;
private JButton button;
private Icon[] icons = {};
private static final long serialVersionUID = 1L;
public ImageViewer() {
try {
panel = new JPanel();
URL url1 = new URL("http://www.sm.luth.se/csee/courses/d0010e/l/prob/10tj5Ei9o/LTU-Teatern.jpg");
URL url2 = new URL("http://www.sm.luth.se/csee/courses/d0010e/l/prob/10tj5Ei9o/LTU-Vetenskapens-hus.jpg");
Icon image = new ImageIcon(ImageIO.read(url1));
Icon image2 = new ImageIcon(ImageIO.read(url2));
icons[0] = image;
icons[1] = image2;
imageLabel = new JLabel();
panel.add(button);
panel.add(imageLabel);
button = new JButton("Change");
button.addActionListener(new ActionListener() {
private boolean value = false;
{
}
public void actionPerformed(ActionEvent arg0) {
value = value == true ? false : true;
if (value == false) {
imageLabel.setIcon(icons[0]);
}else {
imageLabel.setIcon(icons[1]);
}
}
});
this.setContentPane(panel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}catch (Exception e) {
}
}
public static void main(String args[]) {
new ImageViewer();
}
}
First, here's what I created to give you some hints.
And here's the code. The hints will follow after the code.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageViewer implements Runnable {
private boolean isImage1;
private BufferedImage image;
private ImageData imageData;
private JLabel label;
public static void main(String args[]) {
SwingUtilities.invokeLater(new ImageViewer());
}
public ImageViewer() {
this.imageData = new ImageData();
this.image = imageData.getImage1();
this.isImage1 = true;
}
#Override
public void run() {
JFrame frame = new JFrame("Image Viewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
label = new JLabel(new ImageIcon(image));
panel.add(label);
JButton button = new JButton("Change");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (isImage1) {
image = imageData.getImage2();
} else {
image = imageData.getImage1();
}
label.setIcon(new ImageIcon(image));
isImage1 = !isImage1;
}
});
panel.add(button);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public class ImageData {
private BufferedImage image1;
private BufferedImage image2;
public ImageData() {
URL url1;
URL url2;
try {
url1 = new URL("http://www.sm.luth.se/csee/courses/d0010e/l/prob/10tj5Ei9o/LTU-Teatern.jpg");
url2 = new URL("http://www.sm.luth.se/csee/courses/d0010e/l/prob/10tj5Ei9o/LTU-Vetenskapens-hus.jpg");
this.image1 = readImage(url1);
this.image2 = readImage(url2);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private BufferedImage readImage(URL url) {
try {
return ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public BufferedImage getImage1() {
return image1;
}
public BufferedImage getImage2() {
return image2;
}
}
}
So here are the hints.
Do not extend JFrame, or any Swing component, unless you intend to override one or more of the class methods.
Always start your Swing project on the Event Dispatch Thread (EDT). I implemented Runnable in the main ImageViewer class for convenience. Your main method should always contain a call to SwingUtilities invokeLater.
I moved the reading of the images to its own data class. Always separate the data from the view. I usually use the model / view / controller architecture to create a Swing project.
I checked for errors in the URLs or the actual image reading. If an error had occurred, it would have printed a stack trace which would have helped me find the error. Never enclose whole methods in a try-catch block.
The only Swing component that needed to be a class variable was the JLabel component. Only make the class variables that you need for the whole class. My habit is to make all the class variables private, as well as the class methods. Only expose the methods that need to be exposed.
Once I did all these things, writing the action listener was trivial.
Related
Here's description of my problem (in one picture!):
I would like to know:
1.) Why this is happening (I have even tried to setMaximumSize(), setPreferredSize(), setMinimumSize()!)?
2.) How I should resolve this? (I used GridLayout. It may or may not be super effective)
This is the setup code:
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.CardLayout;
import java.awt.Dimension;
public class IntroScreen extends JFrame implements ActionListener
{
private boolean sandboxed = true;
private final String SELECTION = "selection", CLEAN = "clean";
private JPanel container;
private DirectorySelectionPanel selectionPanel;
private DirectoryCleanerPanel cleanerPanel;
public IntroScreen()
{
super("Directory Cleaner");
add((container = setupContent()));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
JOptionPane.showMessageDialog(this, this.getSize());
}
private JPanel setupContent()
{
JPanel content = new JPanel(new CardLayout());
this.selectionPanel = new DirectorySelectionPanel(this.sandboxed);
this.selectionPanel.getButton().addActionListener(this);
content.add(this.selectionPanel, this.SELECTION);
this.cleanerPanel = new DirectoryCleanerPanel(false);
content.add(this.cleanerPanel, this.CLEAN);
return content;
}
#Override
public void actionPerformed(ActionEvent event)
{
// get the source of the event
Object source = event.getSource();
// if it was the selectionPanel's button
if (source.equals(this.selectionPanel.getButton()))
{
if (this.selectionPanel.validateSelections())
{
System.out.println("Test line");
((CardLayout)this.container.getLayout()).show(this.container, this.CLEAN);
// must figure out the correct size for this
// TODO: Find a way to force the size of this to be around 450-by-90 pixels
this.setSize(450,90);
}
}
// otherwise
else
{
// show the selectionPanel
this.setSize(312,253); // revert back to the original size
}
}
public static void main(String[] args)
{
new IntroScreen();
}
}
I'm trying to make a simple stickman game where the stickman runs. I've added 2 pictures; 1 where he's standing and 1 where he's running. Have made a JFrame and have tried to switch between the pictures in it by adding the first pic then remove it and add the another.
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Spil extends JFrame {
private static String path_for_image = "index.jpeg";
private static String path2_for_image = "run.jpeg";
#SuppressWarnings("deprecation")
public void run(){
JFrame frame = new JFrame("STICKMAN");
frame.setVisible(true);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon image = new ImageIcon(path_for_image);
JLabel label = new JLabel(image);
ImageIcon image2 = new ImageIcon(path2_for_image);
JLabel label2 = new JLabel(image2);
while(true){
add(label);
label.move(10, 0);
if(label.isEnabled()){
remove(label);
add(label2);
} else {
remove(label2);
add(label);
}
}
}
}
^^Here I make the JFrame and the code below is my main class:
EDIT:
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Spil extends JFrame {
private static String path_for_image = "index.jpeg";
private static String path2_for_image = "run.jpeg";
#SuppressWarnings("deprecation")
public void run(){
JFrame frame = new JFrame("STICKMAN");
frame.setVisible(true);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon image = new ImageIcon(path_for_image);
JLabel label = new JLabel(image);
ImageIcon image2 = new ImageIcon(path2_for_image);
JLabel label2 = new JLabel(image2);
while(true){
frame.add(label);
label.move(10, 0);
if(label.isEnabled()){
frame.remove(label);
frame.add(label2);
} else {
frame.remove(label2);
frame.add(label);
}
}
}
}
public class Main {
public static void main(String[] args){
Spil run = new Spil();
run.run();
}
}
The problem is that the JFrame appears but without the pictures
use swing timer
there are bunch of problems in your code
1) add(label); should be frame.add(label); you have extends your class with frame .but you have created frame local varible and used it.so add will add to your class/jframe instead of frame.so your frame don't have a lable.
either you can remove extends keyword or you can use your Spil class as a jframe then you don't need to create a another frame variable.
JFrame frame = new JFrame("STICKMAN");) .see example 2 how to do using extends jframe
2) label.isEnabled() always true so you never execute else block.to isEnable be false it should be disabled.
3) removing and adding jlables is really inefficient you can easily change image icon.
4) infinite loop will block the Edt and freez your gui.swing timer will handle this without blocking EDT
5) animation need a time gap if you do very fast it really doesn't look nice.in this example i have set time gap to 10 millisecond. you can change speed of your animation by changing value 10.
swing timer is easy to use and perfect for your requirement.
example 1 without extends JFrame
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class Spil {
private static final ImageIcon img1 = new ImageIcon("index.jpeg");
private static final ImageIcon img2 = new ImageIcon("run.jpeg");
boolean bool = false;
public void run() {
JFrame frame = new JFrame("STICKMAN");
frame.setVisible(true);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel(img1);
frame.add(label);
Timer t = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (bool) {
label.setIcon(img1);
} else {
label.setIcon(img2);
}
bool=!bool;
}
});
t.start();
}
public static void main(String[] args) {
Spil run = new Spil();
run.run();
}
}
example 2 / extends Jframe
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class Spil extends JFrame {
private static final ImageIcon img1 = new ImageIcon("index.jpeg");
private static final ImageIcon img2 = new ImageIcon("run.jpeg");
boolean bool = false;
public void run() {
super.setTitle("STICKMAN");
JLabel label = new JLabel(img1);
add(label);
Timer t = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (bool) {
label.setIcon(img1);
} else {
label.setIcon(img2);
}
bool = !bool;
}
});
t.start();
}
public static void main(String[] args) {
Spil run = new Spil();
run.setSize(400,300);
run.setVisible(true);
run.run();
}
}
I'm working on this project and I need it run as an applet and an application. This is what I have but I stuck on where to go because I can't find anything on the internet. Are there any resources or does someone have some quick advice to give me?
public class Project extends JApplet {
public void init() {
try {
URL pictureURL = new URL(getDocumentBase(), "sample.jpg");
myPicture = ImageIO.read(pictureURL);
myIcon = new ImageIcon(myPicture);
myLabel = new JLabel(myIcon);
} catch (Exception e) {
e.printStackTrace();
}
add(label, BorderLayout.NORTH);
add(bio);
add(bio, BorderLayout.CENTER);
pane.add(play);
getContentPane().add(pane, BorderLayout.SOUTH);
play.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try{
FileInputStream FIS = new FileInputStream("sample.mp3");
player = new Player (FIS);
player.play();
} catch (Exception e1) {
e1.printStackTrace();
}}});
}
public static void main(String args[]) {
JFrame frame = new JFrame("");
frame.getContentPane().add();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.show();
}
private JPanel pane = new JPanel();
private TextArea bio = new TextArea("Bio");
private JButton play = new JButton("Play");
private Image myPicture;
private ImageIcon icon;
private JLabel label;
private Player player;
}
When trying to run something as an applet and as an application, there are several caveats.
Applets have a certain life cycle that must be obeyed. One can add the applet to the content pane of the JFrame and manually call init(), but in general, if the applet expects its start() or stop() methods to be called, things may become tricky...
More importantly: The way how resources are handled is different between applets and applications.
Handling files in applets (e.g. with a FileInputStream) may have security implications, and will plainly not work in some cases - e.g. when the applet is embedded into a website. (Also see What Applets Can and Cannot Do).
Conversely, when running this as an application, calling getDocumentBase() does not make sense. There simply is no "document base" for an application.
Nevertheless, it is possible to write a program that can be shown as an Applet or as an Application. The main difference will then be whether the main JPanel is placed into a JApplet or into a JFrame, and how data is read.
One approach for reading data that works for applets as well as for applications is via getClass().getResourceAsStream("file.txt"), given that the respective file is in the class path.
I hesitated a while, whether I should post an example, targeting the main question, or whether I should modify your code so that it works. I'll do both:
Here is an example that can be executed as an Applet or as an Application. It will read and display a "sample.jpg". (This file is currently basically expected to be "in the same directory as the .class-file". More details about resource handling, classpaths and stream handling are beyond the scope of this answer)
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class AppletOrApplicationExample extends JApplet
{
#Override
public void init()
{
add(new AppletOrApplicationMainComponent());
}
public static void main(String args[])
{
JFrame frame = new JFrame("");
frame.getContentPane().add(new AppletOrApplicationMainComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
class AppletOrApplicationMainComponent extends JPanel
{
public AppletOrApplicationMainComponent()
{
super(new BorderLayout());
InputStream stream = getClass().getResourceAsStream("sample.jpg");
if (stream == null)
{
add(new JLabel("Resource not found"), BorderLayout.NORTH);
}
else
{
try
{
BufferedImage image = ImageIO.read(stream);
add(new JLabel(new ImageIcon(image)), BorderLayout.NORTH);
}
catch (IOException e1)
{
add(new JLabel("Could not load image"), BorderLayout.NORTH);
}
}
JTextArea textArea = new JTextArea("Text...");
add(textArea, BorderLayout.CENTER);
JButton button = new JButton("Button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
doSomething();
}
});
add(button, BorderLayout.SOUTH);
}
private void doSomething()
{
System.out.println("Button was clicked");
}
}
And here is something that is still a bit closer to your original code. However, I'd strongly recommend to factor out the actual application logic as far as possible. For example, your main GUI component should then not be the applet itself, but a JPanel. Resources should not be read directly via FileInputStreams or URLs from the document base, but only from InputStreams. This is basically the code that you posted, with the fewest modifications that are necessary to get it running as an applet or an application:
import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Module5Assignment2 extends JApplet
{
public void init()
{
try
{
InputStream stream = getClass().getResourceAsStream("sample.jpg");
if (stream == null)
{
System.out.println("Resource not found");
}
else
{
myPicture = ImageIO.read(stream);
icon = new ImageIcon(myPicture);
label = new JLabel(icon);
add(label, BorderLayout.NORTH);
}
}
catch (Exception e)
{
e.printStackTrace();
}
add(bio);
add(bio, BorderLayout.CENTER);
pane.add(play);
getContentPane().add(pane, BorderLayout.SOUTH);
play.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
FileInputStream FIS = new FileInputStream("sample.mp3");
// player = new Player (FIS);
// player.play();
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
});
}
public static void main(String args[])
{
JFrame frame = new JFrame("");
// ******PRETTY SURE I NEED TO ADD SOMETHING HERE*************
Module5Assignment2 contents = new Module5Assignment2();
frame.getContentPane().add(contents);
contents.init();
// *************************************************************
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.show();
}
private JPanel pane = new JPanel();
private TextArea bio = new TextArea(
"This is the bio of Christian Sprague; he doesn't like typing things.");
private JButton play = new JButton("Play");
private Image myPicture;
private ImageIcon icon;
private JLabel label;
// private Player player;
}
I want to show a changing image on my frame. The imagepath is always the same, but the image will be getting overwritten every 10 seconds from another program.
The problem is that the image is not changing when I overwrite it with another image with the same name. So in my understanding: Compiler looks every look in the path and gets the image -> when the image changed it will be changed on the frame!
I hope you understand my problem and somebody could help me.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUI extends JFrame{
public ImageIcon imageBar;
public JLabel labelimage1;
private JLabel labelimage2;
private JLabel bar1 = new JLabel();
private JLabel bar2 = new JLabel();
private JLabel bar3 = new JLabel();
private JLabel bar4 = new JLabel();
private JLabel bar5 = new JLabel();
private JButton buttonBar1 = new JButton("1");
private JButton buttonBar2 = new JButton("2");
private JButton buttonBar3 = new JButton("3");
private JButton buttonBar4 = new JButton("4");
private JButton buttonBar5 = new JButton("5");
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel();
private JPanel panel3 = new JPanel();
private JFrame window = new JFrame("Interface");
public GUI(){
//set the layouts
panel1.setLayout(new GridLayout(1, 2));
panel2.setLayout(new GridLayout(2, 1));
panel3.setLayout(new GridLayout(2, 5));
//place Panel2 and Panel3 in the window
panel1.add(panel2);
panel1.add(panel3);
//----Panel2
//refreshImage();
//----Panel3
panel3.add(buttonBar1); //add the bars 1-5 on panel3
panel3.add(buttonBar2);
panel3.add(buttonBar3);
panel3.add(buttonBar4);
panel3.add(buttonBar5);
//configure the frame
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setSize(800, 400);
window.getContentPane().add(panel1);
}
public void refreshImage() {
panel2.removeAll(); //delete the old panel
//panel2.repaint();
//panel2.revalidate()
DrawImage pan = new DrawImage();
panel2.add(pan);
panel2.add(labelimage2);
}
}
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class DrawImage extends JPanel implements ActionListener{
private ImageIcon image;
public DrawImage(){
image = new ImageIcon("C:\\Users\\usuario\\Desktop\\image.png");
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
image.paintIcon(this, g, 50, 50);
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
import java.io.File;
public class Main {
public static void main(String[] args) {
GUI Interface = new GUI();
while(true)
{
Interface.refreshImage();
try {
Thread.sleep(5000); //wait for 5000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thank you very much!
The likely cause is Java is caching the image in memory, associated with the source name. So rather then trying to reload the image again, Java simply returns the cached version.
You could use ImageIcon#getImage#flush to force Java to reconstruct the image
Problems
You are calling refreshImage from a Thread other then the Event Dispatching Thread, this could cause issues with the updating of the components and cause rendering artifacts
You are forcefully removing the DrawImage pane and adding a new instance, rather the trying to reload the image
You're calling repaint within the paintComponent method, don't do this...
You should consider using a Swing Timer, which will allow you to schedule a regular update and be notified within the context of the Event Dispatching Thread.
You could provide a simple refresh method which flushes the current ImageIcon and schedule a repaint of the panel...or you could just use a JLabel and save your self the time
An example of Image#flush
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SlideShow {
public ImageIcon imageBar;
public static void main(String[] args) {
new SlideShow();
}
public SlideShow() {
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 DrawImage());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawImage extends JPanel {
private ImageIcon image;
public DrawImage() {
image = new ImageIcon("D:\\thumbs\\image.png");
Timer timer = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
refresh();
}
});
timer.start();
}
public void refresh() {
image.getImage().flush();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image.getImage(), 0, 0, this);
}
}
}
The problem with this, is because the image data is loaded in a background thread, it won't may no be available when the component is first repainted, which could make the component appear to flicker.
A better approach would be to use ImageIO.read, which will ensure that the image is fully loaded before the method returns, the draw back here is that could cause the application to "pause" momentary as the image is loaded, personally, I'd use the refresh method to stop the the Timer (or set the Timer to non-repeating), start a background Thread to load the image (using ImageIO.read) call repaint (which is thread safe) and restart the Timer...
Your while (true) loop risks typing up the Swing event thread locking your program. If it doesn't do that, then you risk unpredictable threading issues by making Swing calls off of the event Thread. These problems can be solved easily by your using a Swing Timer not a while true loop to do your swapping.
Rather than removing and adding components, why not simply display images as ImageIcons within a single non-swapped JLabel.
To swap images here, simply call setIcon(...) on the JLabel.
For an example of using a Swing Timer to swap images, please check out my answer to a similar question here.
For example:
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TimerImageSwapper {
public static final String[] IMAGE_URLS = {
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_01.png",
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_02.png",
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_04.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_08.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_05.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_01.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_06.png" };
private ImageIcon[] icons = new ImageIcon[IMAGE_URLS.length];
private JLabel mainLabel = new JLabel();
private int iconIndex = 0;;
public TimerImageSwapper(int timerDelay) throws IOException {
for (int i = 0; i < icons.length; i++) {
URL imgUrl = new URL(IMAGE_URLS[i]);
BufferedImage image = ImageIO.read(imgUrl);
icons[i] = new ImageIcon(image);
}
mainLabel.setIcon(icons[iconIndex]);
new Timer(timerDelay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
iconIndex++;
iconIndex %= IMAGE_URLS.length;
mainLabel.setIcon(icons[iconIndex]);
}
}).start();
}
public Component getMainComponent() {
return mainLabel;
}
private static void createAndShowGui() {
TimerImageSwapper timerImageSwapper;
try {
timerImageSwapper = new TimerImageSwapper(5 * 1000);
JFrame frame = new JFrame("Timer Image Swapper");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(timerImageSwapper.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I tried to create a floating dialog box which contains a loader gif image and some text. I have got the following class:
public class InfoDialog extends JDialog {
public InfoDialog() {
setSize(200, 50);
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
setUndecorated(true);
setLocationRelativeTo(null);
URL url = InfoDialog.class.getClassLoader().getResource("loader.gif");
ImageIcon loading = new ImageIcon(url);
getContentPane().add(new JLabel("Logging in ... ", loading, JLabel.CENTER));
}
}
However, when I call:
InfoDialog infoDialog = new InfoDialog()
infoDialog.setVisible(true);
An empty dialog is shown. The ImageIcon and the Label is not shown in the dialog box.
What did I do wrong in this code?
Many thanks.
Images are usually placed into a "resource" Source Folder,
and then accessed as a byte stream,
package com.foo;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class Demo
{
private static final String IMAGE_URL = "/resource/bar.png";
public static void main(String[] args)
{
createAndShowGUI();
}
private static void createAndShowGUI()
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setTitle("Image Loading Demo");
dialog.add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResourceAsStream(IMAGE_URL)))));
dialog.pack();
dialog.setLocationByPlatform(true);
dialog.setVisible(true);
}
catch (IOException e)
{
e.printStackTrace();
}
}
});
}
}
to produce Morgan Freeman.
I would add the ImageIcon to a JLabel and then add JLabel to JDialog contentPane followed by a this.validate and this.repaint in the constructor.
To debug, sometimes you need actual code without which these are just suggestions based on assumptions