ImageIcon Help + Close a JOptionPane

2019-01-20 18:49发布

问题:

I'm trying to get the PayPal logo come up when you click the 'rightbutton' is clicked. Unfortunately, all that shows is the default Java logo with the cup of coffee and a pen.

Also, how can I make it so once you click "OK" or "Cancel" it closes the JOptionPane, currently, when you click "OK" nothing happens, it keeps giving you the "OK" / "Cancel" option.

rightbutton = new JButton("Right.");
add(rightbutton);
rightbutton.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEvent event){
                //what do we want to happen when we
                //click the button
                final ImageIcon icon = new ImageIcon("C:\\Users\\Scr3am\\Desktop\\paypal.jpg");
                JOptionPane.showOptionDialog(null, "Congratulations, you clicked the button.", "Congrats", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new Object[] { panel }, icon);
            }
        }
);

FULL CODE

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class Password extends JFrame {

    JButton leftbutton;
    JButton centerbutton;
    JButton rightbutton;
    FlowLayout layout;
    Container container;




    Password(){
        super("Toolbar");
        layout = new FlowLayout();
        //get bulk of window, so it knows where to put the stuff
        container = getContentPane();
        setLayout(layout);

        //left stuff in here
        leftbutton = new JButton("Left");
        add(leftbutton);
        leftbutton.addActionListener(
                new ActionListener(){
                    public void actionPerformed(ActionEvent event){
                        //what do we want to happen when we
                        //click the button
                        layout.setAlignment(FlowLayout.LEFT);

                    }


                }

        );

        final JPanel panel = new JPanel();
        panel.add(new JButton("OK"));
        panel.add(new JButton("Cancel"));

        //center stuff in here
        centerbutton = new JButton("Center");
        add(centerbutton);
        centerbutton.addActionListener(
                new ActionListener(){
                    public void actionPerformed(ActionEvent event){
                        //what do we want to happen when we
                        //click the button
                        layout.setAlignment(FlowLayout.CENTER);
                        layout.layoutContainer(container);

                    }
                }
        );

        //right stuff in here
        rightbutton = new JButton("Right.");
        add(rightbutton);
        rightbutton.addActionListener(
                new ActionListener(){
                    public void actionPerformed(ActionEvent event){
                        //what do we want to happen when we
                        //click the button
                        try {
                            final ImageIcon icon = new ImageIcon(ImageIO.read(new File("paypalicon.gif")));

                            JOptionPane.showOptionDialog(
                                    null,
                                    "Congratulations, you clicked the button.",
                                    "Congrats",
                                    JOptionPane.OK_OPTION,
                                    JOptionPane.PLAIN_MESSAGE,
                                    icon,
                                    new Object[]{"Okay"},
                                    "Okay");
                        } catch (IOException exp) {
                            exp.printStackTrace();
                        }



                    }
                }
        );
    }


}

Errors:

javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1275)
at Password$3.actionPerformed(Password.java:79)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6414)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3275)
at java.awt.Component.processEvent(Component.java:6179)
at java.awt.Container.processEvent(Container.java:2084)
at java.awt.Component.dispatchEventImpl(Component.java:4776)
at java.awt.Container.dispatchEventImpl(Container.java:2142)
at java.awt.Component.dispatchEvent(Component.java:4604)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4618)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4279)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4209)
at java.awt.Container.dispatchEventImpl(Container.java:2128)
at java.awt.Window.dispatchEventImpl(Window.java:2492)
at java.awt.Component.dispatchEvent(Component.java:4604)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:717)
at java.awt.EventQueue.access$400(EventQueue.java:82)
at java.awt.EventQueue$2.run(EventQueue.java:676)
at java.awt.EventQueue$2.run(EventQueue.java:674)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:690)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:687)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

回答1:

I think you have your parameters around the wrong way

try {
    final ImageIcon icon = new ImageIcon(ImageIO.read(new File("paypalicon.gif")));

    JOptionPane.showOptionDialog(
            null,
            "Congratulations, you clicked the button.",
            "Congrats",
            JOptionPane.OK_OPTION,
            JOptionPane.PLAIN_MESSAGE,
            icon,
            new Object[]{"Okay"},
            "Okay");
} catch (IOException exp) {
    exp.printStackTrace();
}

JOptionPane declares showOptionDialog as having the following parameters (in order)

  • Component, the parent component associated with the dialog
  • Object, the message to be displayed
  • String, the dialog title
  • int, the type of options (if not specified), such as JOptionPane.OKAY_CANCEL_OPTION
  • int, the message type, such as JOptionPane.INFORMATION_MESSAGE, which can define the icon that the dialog will use
  • Icon, the icon to be displayed on the dialog
  • Object[], the options to be made available to the user (buttons)
  • Object, the initial option which is given focus

You seem to be passing...

  • null as the parent, okay.
  • "Congratulations, you clicked the button.", okay
  • "Congrats", okay
  • JOptionPane.DEFAULT_OPTION, okay
  • JOptionPane.INFORMATION_MESSAGE probably okay, I'd use JOptionPane.PLAIN_MESSAGE, but that's me
  • null...no icon?
  • new Object[] { panel }, not sure if this is okay, but at least it's in the right place
  • icon...this isn't even a value i the option parameters you passed ... think this is missed place.

The problem with the buttons comes down to the fact that they are disconnected from the dialog. The dialog has absolutely no way to know that the buttons are been clicked, you'd have to provide that functionality via some kind of ActionListener...to be honest, it'd just pass String values as the options parameter and let JOptionPane render them as buttons, as it will then deal with closing the dialog, otherwise it gets real messy, real quick...



回答2:

For the ImageIcon, it's because you have the arguments in the wrong order:

JOptionPane.showOptionDialog(
    null,
    "Congratulations, you clicked the button.",
    "Congrats",
    JOptionPane.DEFAULT_OPTION,
    JOptionPane.INFORMATION_MESSAGE,
    null,
    new Object[] { panel },
    icon
);

So right now you are providing null for the icon and the icon for the initial value. It should be:

JOptionPane.showOptionDialog(
    null,
    "Congratulations, you clicked the button.",
    "Congrats",
    JOptionPane.DEFAULT_OPTION,
    JOptionPane.INFORMATION_MESSAGE,
    icon,
    new Object[] { panel },
    null
);

For the other question, it looks like you are providing your own options as some kind of panel. I guess technically what you could do is use a constructor so you have a reference to the JOptionPane that you can dismiss programatically but you do not need to do this. Instead, I would recommend using the regular OK_CANCEL_OPTION which will do this for you.

int optionChosen = JOptionPane.showConfirmDialog(
    null,
    "Congratulations, you clicked the button.",
    "Congrats",
    JOptionPane.OK_CANCEL_OPTION,
    JOptionPane.INFORMATION_MESSAGE,
    icon
);

Edit for your comment:

  • Try replacing the backslashes in the path with forward slashes. The doc says the path is converted to URL and to use forward slashes. See also File.separator vs Slash in Paths.
  • The doc says the image is loaded in the background. So in other words you might be displaying the image before the data is loaded. There's two things you could do. First, preloading the image at the start of the program by making it a static member, second using ImageIO which will load the image fully immediately.

You should really preload the image anyway. Otherwise you are reading the file every time you show the dialog.

static final ImageIcon paypalIcon;
static {
    BufferedImage img = null;
    try {
        img = ImageIO.read(new File("your/path"));
    } catch(IOException ioe) {
        ioe.printStackTrace(System.err);
    }

    // set to null if the image failed to load
    // if you pass null to showXXXDialog it uses the Look & Feel default
    // this way the program still works if it can't find the file
    if(img == null) {
        paypalIcon = null;
    } else {
        paypalIcon = new ImageIcon(img);
    }
}