1

I want to create pop-up image on my JPanel.

Now I have something like this:

enter image description here

but need to get something like this:

enter image description here

it will be after I press X1. how to do this in Java? Thnx.

Val
  • 4,225
  • 8
  • 36
  • 55
  • by press X1, do you mean, click on blue circle X1 or pressing X followed by pressing 1 on keyboard? Also is X1 image or a subclass of [JButton](http://docs.oracle.com/javase/6/docs/api/javax/swing/JButton.html) or something else? – linski Oct 09 '12 at 16:34
  • click on X1, X1 - it's JLable with icon. – Val Oct 09 '12 at 16:38
  • You could use something like [GlassPane](http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html) or [JLayer/JXLayer](http://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html), but for simplicity, I like the JPopupMenu suggestion ;) – MadProgrammer Oct 09 '12 at 19:26

2 Answers2

2

Create the menu like this:

JPopupMenu popupmenu = new JPopupMenu();
JMenuItem jMenuItem = new JMenuItem(new ImageIcon(getClass().getResource("/topmostpackage/sub/package/s/img.png")));
popupmenu.add(jMenuItem);

Then add the click handler to the button in question and show the menu like this:

MouseAdapter mouseAdapter = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent e) {
            super.mouseClicked(e);
            popupmenu.show(button, e.getXOnScreen(), e.getYOnScreen());  
        }

    };
    button.addMouseListener(mouseAdapter);

EDIT: For the above example to work you must put the image inside your package structure, if that's not the case you can read it like this:

    URI uri = new URI("file:///home/linski/empty.png");
    ImageIcon imageIcon = new ImageIcon(uri.toURL());

so, after file:// I put the path to the image on my linux file system. I cant test that on windows/mac, but, you can open the image via browser and read the correctly formatted path form the browser adress bar.

EDIT^2: this solution won't fit your need because it won't look exactly like in the image you provided - the balloon image will be a menu item, and the menu will be seen.

EDIT^3:

I'll give you a fast hack, instead of instantiating JPopupMenu, instantiate this class:

public class CustomPopUpMenu extends JPopupMenu {

    @Override
    protected void paintComponent(Graphics g) {}

}

Instead of instantiating JMenuItem instantiate this class:

public class CustomMenuItem extends JMenuItem {

    public CustomMenuItem(Icon icon) {
        super(icon);
    }

    @Override
    protected void paintComponent(Graphics g) {
        getIcon().paintIcon(this, g, 0, 0);
    }    

}

And you'll get almost what you want. Keep in mind that this is a "hack" (not hack, but "hack") - it is not how it is meant to be done. The right way to do it would be customizing JPopUpMenuUI (probably in conjuction with making your own subclass of that class).

I can't show you how, but I know that I'll learn it as soon as I'll have time. Also see this.

+1 one for interesting question :)

Community
  • 1
  • 1
linski
  • 5,046
  • 3
  • 22
  • 35
  • I got something like that: http://s017.radikal.ru/i408/1210/8f/b88723d1ae85.png with invisible background and border... – Val Oct 09 '12 at 16:39
  • You want to change the [Look And Feel](http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html) ,not entire but of particular component. Never did that to that extent and net reources are scarce. I'm currently trying to "hack" some classes I ll update if I manage to get something out of it.. – linski Oct 09 '12 at 17:07
2

As a starting point, something like this may work for you. (Very quickly put together, be gentle.) I think the GlassPane approach will be the cleanest looking. I'll leave it to you to add a pointer on the info bubble in the paintComponent() method.

enter image description here

static MyInfoBubble lastBubble;


public static void main(String[] args)
{
    JFrame frame = new JFrame();
    frame.setSize(new Dimension(500, 500));

    JPanel glassPane = new JPanel();
    glassPane.setOpaque(false);
    glassPane.setLayout(null);

    frame.setGlassPane(glassPane);
    frame.getGlassPane().setVisible(true);

    JPanel labelRowPanel = new JPanel();
    for (int ctr = 0; ctr < 7; ctr++) {
        labelRowPanel.add(makeButton(frame, "Button " + ctr));
    }

    frame.getContentPane().add(labelRowPanel);
    frame.setVisible(true);
}



private static JButton makeButton(final JFrame frame, final String label) {
    final JButton button = new JButton(label);

    button.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent arg0)
        {
            if (lastBubble != null)
            {
                lastBubble.setVisible(false);
                ((JPanel)frame.getGlassPane()).remove(lastBubble);
                lastBubble = null;
            }

            Point loc = button.getLocation();
            MyInfoBubble mib = new MyInfoBubble();
            mib.setBounds(loc.x+10, loc.y+30, 100, 50);
            ((JPanel)frame.getGlassPane()).add(mib);
            lastBubble = mib;

            ((JPanel)frame.getGlassPane()).validate();
            ((JPanel)frame.getGlassPane()).repaint();
        }

    });

    return button;
}


static class MyInfoBubble extends JPanel
{
    public MyInfoBubble()
    {
        setVisible(true);
    }


    public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.BLUE);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 20, 20);
    }

}
martinez314
  • 12,162
  • 5
  • 36
  • 63