0

I have a JPanel with GroupLayout with 3 JLabels in it. I also have a hidden JButton in it.

I have added a MouseListener to JPanel showing the button in mouseEntered and hide the button in mouseExited events respectively.

At this time, their is space for button between 2 labels and their only the button is shown or hidden using setVisible(). When the btn is visible, the labels below it goes down making space for button and if the btn is hidden it again comes to its original size.

What I want - in mouseEntered, the button should show on the label itself (let it be overlap) and I should be able to click on the button. This all should happen very smoothly without screen flickering. Similarly in mouseExited, the button should be removed.

How do I achieve this ? Can anyone help me with this.

UPDATE @Andrew, Thanks I tried with JLayeredPane and it does work. Though the button is not set to visible false. Here's my mouseMoved code :

public void mouseMoved(MouseEvent e) {
    if (e.getComponent() == layeredPane) {
        if (! startCustomBtn.isVisible())
            startCustomBtn.setVisible(true);
        startCustomBtn.setLocation(e.getX()-55, e.getY()-30);       
    } else {
        if (startCustomBtn.isVisible()) {
            startCustomBtn.setVisible(false);
            revalidate();
        }
    }
}

Layout of the JPanel :

private void layeredLayout() {
    layeredPane = new JLayeredPane();
    layeredPane.addMouseMotionListener(this);

    Insets insets = this.getInsets();
    Dimension size = rateLabel.getPreferredSize();
    rateLabel.setBounds(insets.left + 45, insets.top + 15, size.width, size.height);
    size = imageLabel.getPreferredSize();
    imageLabel.setBounds(insets.left + 15, insets.top + 40, size.width, size.height);

    size = label.getPreferredSize();
    label.setBounds(insets.left + 45, insets.top + imageLabel.getWidth() + 20 , size.width, size.height);

    size = startCustomBtn.getPreferredSize();
    startCustomBtn.setBounds(insets.left + 45, insets.top + 40 + size.height, size.width, size.height);

    layeredPane.add(rateLabel, new Integer(0));
    layeredPane.add(imageLabel, new Integer(1));
    layeredPane.add(label, new Integer(2));

    layeredPane.add(startCustomBtn, new Integer(1), 0);

    setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
    add(layeredPane);
}

Strange - I tried the layout with null, FlowLayout, but couldn't see anything. When tried with BoxLayout, components showed up.

REsult : enter image description here

Main screen has a JPanel with Gridlayout(2, 3) and in each cell this JPanel (MyPanel) is added. When I come out from 1 cell (i.e. MyPanel) the button of that panel should be hidden which is not happening with the above code. What can be the reason ? I also added revalidate() & also repaint() but nothing works. ????

Tvd
  • 4,463
  • 18
  • 79
  • 125
  • Though I am getting a flickering effect, my __java version "1.7.0_25"__ Have you tried to do this with __Java 6__ ? Though last sentence of the post, surely puts doubt, as to what exactly you are trying to do ? +1 though, as this indeed is flickering on my side too, if I use `setVisible(true/false)` on `mouseEntered/mouseExited` methods. Already upvoted it some time back :-) – nIcE cOw Oct 05 '13 at 14:12
  • All I want to achieve is want to show a clickable button on the Label with Icon smoothly without any disturbance. And on click of button, should be able to perform something. I had tried with layout (null), but btn is going under Icon & also not able to click it. So now am with Gridlayout. – Tvd Oct 05 '13 at 14:19
  • On searching a lot on net, I think I got to create another JPanel and add only JButton in it. Show this JPanel some how on mouse events and let it remain until btn clicked or mouseExited. OR may be paintComponent may be the solution. Don't know how to implement either of it so not able to try them too. Even not sure if I am correct or not. – Tvd Oct 05 '13 at 14:22
  • 2
    For better help sooner, post an [SSCCE](http://sscce.org/). Look into a [`JLayeredPane`](http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html) (or similar) to overlay the buttons. – Andrew Thompson Oct 05 '13 at 14:25

2 Answers2

3

What I want - in mouseEntered, the button should show on the label itself (let it be overlap) and I should be able to click on the button. This all should happen very smoothly without screen flickering. Similarly in mouseExited, the button should be removed.

As JLabel extends from JComponent you can add componentes to label itself, just need to set a LayoutManager first. This fact is well explained in this question.

Sample Code

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class Demo {

   private void initGUI(){

       final JButton button = new JButton("Hello!");
       button.setVisible(false);

       final JLabel testLabel = new JLabel("Welcome!");
       testLabel.setPreferredSize(new Dimension(200, 30));
       testLabel.setBorder(new LineBorder(Color.GRAY, 1));
       testLabel.setLayout(new BorderLayout());
       testLabel.add(button, BorderLayout.EAST);

       button.addMouseListener(new MouseAdapter() {
           @Override
           public void mouseExited(MouseEvent e) {
               Point mousePosition = MouseInfo.getPointerInfo().getLocation();
               if(testLabel.contains(mousePosition)){
                   testLabel.dispatchEvent(new MouseEvent(testLabel, MouseEvent.MOUSE_ENTERED, System.currentTimeMillis(), 0, mousePosition.x, mousePosition.y, 0, false));
               } else {
                   testLabel.dispatchEvent(new MouseEvent(testLabel, MouseEvent.MOUSE_EXITED, System.currentTimeMillis(), 0, mousePosition.x, mousePosition.y, 0, false));
               }
           }

       });

       button.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent e) {
               JOptionPane.showMessageDialog(null, "The button was pressed!");
               Point mousePosition = MouseInfo.getPointerInfo().getLocation();
               testLabel.dispatchEvent(new MouseEvent(testLabel, MouseEvent.MOUSE_EXITED, System.currentTimeMillis(), 0, mousePosition.x, mousePosition.y, 0, false));
           }
       });

       testLabel.addMouseListener(new MouseAdapter(){
           @Override
           public void mouseEntered(MouseEvent e) {
               JLabel label = (JLabel) e.getSource();
               label.setText("Here is the Button!");
               button.setVisible(true);
           }

           @Override
           public void mouseExited(MouseEvent e) {
               Point point = e.getPoint();
               point.setLocation(point.x - button.getX(), point.y - button.getY()); //make the point relative to the button's location
               if(!button.contains(point)) {
                   JLabel label = (JLabel) e.getSource();
                   label.setText("The button is gone!");
                   button.setVisible(false);
               }
           }
       }); 

       JPanel content = new JPanel(new FlowLayout());
       content.setPreferredSize(new Dimension(300,100));
       content.add(testLabel);

       JFrame frame = new JFrame("Demo");
       frame.setContentPane(content);
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       frame.pack();
       frame.setLocationRelativeTo(null);
       frame.setVisible(true);

   }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().initGUI();
            }
        });
    }    

}

Output

enter image description here

Update

As @nIcEcOw pointed out (thanks!), there's an annoying flickering generated by mouse events' transition. I improved the example fixing this and another untreated aspects like "what happens when mouse exits from JButton?"

Community
  • 1
  • 1
dic19
  • 17,821
  • 6
  • 40
  • 69
  • 1
    On my side, even if the mouse pointer is moved over the `JButton` the flickering occurs, which is not what the OP would want, as posted :( – nIcE cOw Oct 05 '13 at 15:11
  • @dic19, I didn't try your option as though it might be working , but it will still occupy space on the layout screen. I don't want that - that way is already happening now. Thanks – Tvd Oct 05 '13 at 16:12
  • 1
    @nIcEcOw you're totally right, thanks for pointing that out. The point of this example is explain the fact OP can add components to the `JLabel` itlsef. But there's no point on write an example that fails in some aspects, so I've fixed it. Thank you again! – dic19 Oct 07 '13 at 14:15
  • @Tvd now I completely get your question. I guess title is a little tricky and I misunderstood your target, sorry about that :( – dic19 Oct 07 '13 at 14:19
  • 1
    @dic19, that's ok, no problem. We misunderstand at times when we don't read or listen as stated - we read some part & then we are in our own assumptions. It happens with all of us. :-). My issue is still their only :(-. – Tvd Oct 08 '13 at 06:35
1

Questions like this are kind of frustrating. There is almost enough information to describe what you want, or what the problem is, but not quite.

It seems that you want label-label-label until the mouse enters the panel, then you want the appearance to be label-button-label. It's hard to imagine me wanting a UI to act like this.

Is there something about the appearance of the button you don't like, that you want it only to appear on mouse-over-panel? Can the button's appearance be altered so that it looks the way you want it to look, without all this hocus-pocus with the middle label and the button?

I don't have any idea why you mention a timer -- nothing that you describe is being timed, as near as I can tell. In addition, you should be able to boil down what you have to a small runnable example and post it, so that someone can see what you've got and what it does.

arcy
  • 12,845
  • 12
  • 58
  • 103
  • 1
    @Tvd for better help sooner post an SSCCE, short, runnable, compilable, because a.m. issue is about 30-max50 code lines – mKorbel Oct 05 '13 at 14:07
  • @rcook, use of timer was just my guess. As on reading on net I found implementations where in events a Timer was created and any other component/animated component was shown till the user was there. When user moved out, the timer was closed & thus the compo. I was thinking I also got to use any such thing. In my comment also I added this same point. Yes I only wanted btn on mouse-over panel and hide on mouse left panel. – Tvd Oct 05 '13 at 16:34