1

I have a problem. I don't know how to display an image by clicking a JButton.

I have a class which can show and hide an image:

/**
 * 
 */
package com.samples;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

/**
 * @author
 *
 */
public class New2 extends JFrame implements ActionListener {

    private static String SHOW_ACTION = "show";
    private static String HIDE_ACTION = "hide";

    private Image image = null;
    private boolean showImage = false;

    public New2(String filename) {
        setTitle("MyWindow");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(800, 600);

        this.image = new ImageIcon("..//src/img/Ster.png").getImage();

        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        container.add(createControls(), BorderLayout.SOUTH);
    }

    private JPanel createControls() {
        JButton showButton = new JButton("Show");
        showButton.addActionListener(this);
        showButton.setActionCommand(SHOW_ACTION);

        JButton hideButton = new JButton("Hide");
        hideButton.addActionListener(this);
        hideButton.setActionCommand(HIDE_ACTION);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));

        panel.add(showButton);
        panel.add(hideButton);

        return panel;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        if (showImage) {
            g.drawImage(image, 100, 200, image.getWidth(null), image.getHeight(null), null);
        }
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        String actionCommand = event.getActionCommand();

        if (SHOW_ACTION.equals(actionCommand)) {
            showImage = true;
        } else if (HIDE_ACTION.equals(actionCommand)) {
            showImage = false;
        }

        repaint();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                New2 frame = new New2("resources/image.jpg");
                frame.setVisible(true);
            }
        });
    }
}

I'm working with MVC so I want the code for the JButton in my map for controllers but I don't know how to do this.

package View;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;


import Controller.HomeController;
import Controller.KeeperController;

public class Selectie extends JFrame{

    private JLabel label, label1, label2;
    private JButton keeper;
    private JPanel panel;
    private Container window = getContentPane();
    private KeeperController controller;


    public Selectie()
    {
        initGUI();

    }

    public void initGUI()
    {
        setLayout(null);
        setTitle();
        setSize(800,600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        label = new JLabel();       
        label.setBounds(0, 0, 266, 800);
        label.setBackground(Color.RED);
        label.setOpaque(true);
        window.add(label);

        label1 = new JLabel();
        label1.setBounds(266, 0, 266, 800);
        label1.setBackground(Color.BLACK);
        label1.setOpaque(true);
        window.add(label1);

        label2 = new JLabel();
        label2.setBounds(532, 0, 266, 800);
        label2.setBackground(Color.RED);
        label2.setOpaque(true);
        window.add(label2);

        keeper = new JButton("1. "+""+" Kenneth Vermeer");
        keeper.setBounds(60, 500, 200, 25);
        keeper.setFocusable(false);
        keeper.setBorderPainted(false);
        keeper.setContentAreaFilled(false);
        keeper.setFont(new Font("Arial",Font.PLAIN,17));
        label.add(keeper);

        }

}

The button keeper needs to show the image when it is clicked.

naugler
  • 1,060
  • 10
  • 31
Ismail
  • 59
  • 1
  • 3
  • 15
  • Do you need class `New2` or is it just an example? In that case, we'd rather need to see the controller classes (`Controller.HomeController`, `Controller.KeeperController`) then `New2`. – Andreas Dolk Mar 15 '12 at 14:25
  • @lsmail : I had added the diagram representing, how the directory structure has to be, and how the `path` should have to be to access an image. Do have a look :-) – nIcE cOw Mar 16 '12 at 11:20

3 Answers3

5

As said likewise, by others, always use JLabel to display images. That way it's easy to add/remove them as an when needed, instead of painting. Moreover, in your code you are overriding paint(...), for Swing we prefer to override paintComponent(...) method of the respective JComponent if the said component in question has one.

Here try this code, I had separated the Controller part, you might get some idea, as to how to do things :

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

/**
 * @author
 *
 */
public class New2 extends JFrame
{

    private static String SHOW_ACTION = "show";
    private static String HIDE_ACTION = "hide";

    public New2(String filename) 
    {
        setTitle("MyWindow");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(800, 600);        

        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        container.add(createControls(), BorderLayout.CENTER);
    }

    private JPanel createControls() 
    {
        JButton showButton = new JButton("Show");        
        showButton.setActionCommand(SHOW_ACTION);

        JButton hideButton = new JButton("Hide");        
        hideButton.setActionCommand(HIDE_ACTION);

        JLabel imageLabel = new JLabel();

        New2Controller n2c = new New2Controller(showButton
                                                                        , hideButton, imageLabel);
        showButton.addActionListener(n2c);          
        hideButton.addActionListener(n2c);  

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));

        panel.add(imageLabel);
        panel.add(showButton);
        panel.add(hideButton);

        return panel;
    }

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        EventQueue.invokeLater(new Runnable() 
        {
            @Override
            public void run() 
            {
                New2 frame = new New2("/img/image.jpg");
                frame.setVisible(true);
            }
        });
    }
}

class New2Controller implements ActionListener
{
    private JButton showButton;
    private JButton hideButton;
    private JLabel imageLabel;
    private static String SHOW_ACTION = "show";
    private static String HIDE_ACTION = "hide";
    private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");

    public New2Controller(JButton show, JButton hide, JLabel label)
    {
        showButton = show;
        hideButton = hide;
        imageLabel = label;
    }

    public void actionPerformed(ActionEvent event)
    {
        String actionCommand = event.getActionCommand();

        if (SHOW_ACTION.equals(actionCommand)) 
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {                       
                    imageLabel.setIcon(infoIcon);
                }
            });
        } 
        else if (HIDE_ACTION.equals(actionCommand)) 
        {
            imageLabel.setIcon(null);
        }
    }
}

This code represents how you read using ImageIO and URL,

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import javax.imageio.ImageIO;

/**
 * @author
 *
 */
public class New2 extends JFrame
{
    private static String SHOW_ACTION = "show";
    private static String HIDE_ACTION = "hide";

    public New2(String filename) 
    {
        setTitle("MyWindow");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(800, 600);        

        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        container.add(createControls(), BorderLayout.CENTER);
    }

    private JPanel createControls() 
    {
        JButton showButton = new JButton("Show");        
        showButton.setActionCommand(SHOW_ACTION);

        JButton hideButton = new JButton("Hide");        
        hideButton.setActionCommand(HIDE_ACTION);

        JLabel imageLabel = new JLabel();

        New2Controller n2c = new New2Controller(showButton
                                      , hideButton, imageLabel);
        showButton.addActionListener(n2c);          
        hideButton.addActionListener(n2c);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));

        panel.add(imageLabel);
        panel.add(showButton);
        panel.add(hideButton);

        return panel;
    }

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        EventQueue.invokeLater(new Runnable() 
        {
            @Override
            public void run() 
            {
                New2 frame = new New2("/img/image.jpg");  
                frame.setVisible(true);
            }
        });
    }
}

class New2Controller implements ActionListener
{
    private JButton showButton;
    private JButton hideButton;
    private JLabel imageLabel;
    private Image image;
    private ImageIcon imageIcon;
    private static String SHOW_ACTION = "show";
    private static String HIDE_ACTION = "hide";

    public New2Controller(JButton show, JButton hide, JLabel label)
    {
        showButton = show;
        hideButton = hide;
        imageLabel = label;
        try
        {
            image = ImageIO.read(getClass().getResource("/img/caIcon.png"));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        imageIcon = new ImageIcon(image);
    }

    public void actionPerformed(ActionEvent event)
    {
        String actionCommand = event.getActionCommand();

        if (SHOW_ACTION.equals(actionCommand)) 
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {                       
                    imageLabel.setIcon(imageIcon );
                }
            });
        } 
        else if (HIDE_ACTION.equals(actionCommand)) 
        {
            imageLabel.setIcon(null);
        }
    }
}

Moreover, when you are using BorderLayout never use NORTH, EAST, WEST and SOUTH for BorderLayout. They have been replaced with PAGE_START, LINE_START, LINE_END and PAGE_END respectively.

A BorderLayout object has five areas. These areas are specified by the BorderLayout constants:

  • PAGE_START
  • PAGE_END
  • LINESTART
  • LINE_END
  • CENTER

Version note: Before JDK release 1.4, the preferred names for the various areas were different, ranging from points of the compass (for example, BorderLayout.NORTH for the top area) to wordier versions of the constants we use in our examples. The constants our examples use are preferred because they are standard and enable programs to adjust to languages that have different orientations.

Directory Structure :

                                Your Project
                                |          | 
                              classes     src 
                              |     |
                             img  *.class(or package Folder)  

Now use getClass().getResource("/img/star.png");

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • 1
    A good trick with image based examples is to either hot-link to them on the internet (by `URL`) or pull them from the icons used by the JRE. – Andrew Thompson Mar 15 '12 at 14:59
  • 1
    @AndrewThompson : Ahha, yeah as I had seen you doing that many a times :-), that's a good thingy. Just sometimes your head rolls only in one direction, as usual, since it is used to doing it that way. Thankyou for turning my head towards the other direction :-) and do Keep Smiling :-) – nIcE cOw Mar 15 '12 at 15:26
  • *"seen you doing that many a times"* Pulling the icons from the JRE is a clever trick that mKorbel showed me, but I'm always forgetting the details of where to find them. :( – Andrew Thompson Mar 15 '12 at 15:32
  • @AndrewThompson : Hopefully, this new update is what you meant :-) – nIcE cOw Mar 15 '12 at 15:41
  • Well, it's the way you or mKorbel might do it. I will most likely have forgotten again, all too soon. ;) – Andrew Thompson Mar 15 '12 at 15:53
  • I take Icons [from one of most used container on this forum :-)](http://stackoverflow.com/a/7944388/714968) – mKorbel Mar 15 '12 at 18:35
  • @mKorbel : LOL there is one very interesting post of yours `MyToggleButton`, I had taken this idea from that thingy :-) I still had that program with myself for further help :-) – nIcE cOw Mar 15 '12 at 18:37
  • Thanks mate this is what i was looking for, but i can't fix the thing with the image very complicated i got errors java.lang.IllegalArgumentException: input == null! at javax.imageio.ImageIO.read(Unknown Source) at Controller.New2Controller.(New2Controller.java:36) at View.New2.createControls(New2.java:54) at View.New2.(New2.java:41) at View.New2$1.run(New2.java:78) – Ismail Mar 16 '12 at 10:29
  • @ismail : This happens when you are not getting in input i.e. the image from the source folder. Are you using any IDE or simple NOTEPAD or NOTEPAD++ or JEDIT?. If you doing it manually then do one thing put your `img` folder containing `star.png` inside your `classes` folder, and then access it by writing `getClass().getResource("/img/Ster.png");` . Do remember the first forward slash. – nIcE cOw Mar 16 '12 at 10:37
  • @Ismail : Hehe, You are most Welcome and Keep Smiling :-) – nIcE cOw Mar 16 '12 at 11:56
4

1) use JLabel#setIcon() instead of painting image as background to the JFrame

2) create methods into class Selectie

private void setIconToLabel (Icon icon){

     myDesiredLabel.setIcon(icon);
}

3) don't create a new JFrame for another image use CardLayout instaed

mKorbel
  • 109,525
  • 20
  • 134
  • 319
2

You can simply add a JLable to show image on it. After this, you can setVisible JLabel depending on condition.

Rahul Borkar
  • 2,742
  • 3
  • 24
  • 38