Java Swing中JLabel上的显示按钮

Java Swing中JLabel上的显示按钮,java,swing,hover,overlay,Java,Swing,Hover,Overlay,我有一个带有GroupLayout的JPanel,其中有3个JLabel。我还有一个隐藏的按钮 我在JPanel中添加了一个MouseListener,分别在mouseEntered和mouseExited事件中显示按钮和隐藏按钮 此时,他们的按钮位于两个标签之间,只有他们的按钮使用setVisible()显示或隐藏。当btn可见时,它下面的标签会向下移动,为按钮留出空间,如果btn被隐藏,它会再次恢复到原来的大小 我想要的-在mouseenterned中,按钮应该显示在标签上(让它重叠),我应

我有一个带有GroupLayout的JPanel,其中有3个JLabel。我还有一个隐藏的按钮

我在JPanel中添加了一个MouseListener,分别在mouseEntered和mouseExited事件中显示按钮和隐藏按钮

此时,他们的按钮位于两个标签之间,只有他们的按钮使用setVisible()显示或隐藏。当btn可见时,它下面的标签会向下移动,为按钮留出空间,如果btn被隐藏,它会再次恢复到原来的大小

我想要的-在mouseenterned中,按钮应该显示在标签上(让它重叠),我应该能够单击按钮。这一切都应该发生非常顺利,没有屏幕闪烁。类似地,在mouseExited中,应移除按钮

我如何做到这一点?有人能帮我吗

更新 @Andrew,谢谢我试过使用JLayeredPane,它确实有效。尽管按钮未设置为visible false。这是我的鼠标移动代码:

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();
        }
    }
}
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);
}
奇怪-我尝试了空的FlowLayout布局,但什么都看不到。尝试使用BoxLayout时,会显示组件

结果


主屏幕上有一个带有Gridlayout(2,3)的JPanel,在每个单元格中都添加了这个JPanel(MyPanel)。当我从1个单元格(即MyPanel)出来时,该面板的按钮应隐藏,这与上述代码无关。原因可能是什么?我还添加了revalidate()和repaint(),但没有任何效果

像这样的问题有点令人沮丧。几乎有足够的信息来描述你想要什么,或者问题是什么,但并不完全如此

似乎您希望在鼠标进入面板之前添加标签,然后希望外观为标签按钮标签。很难想象我想要一个这样的UI

按钮的外观是否有您不喜欢的地方,您希望它只出现在鼠标面板上?按钮的外观可以改变,使它看起来像你想要的样子,而不需要所有这些带有中间标签和按钮的hocus pocus吗


我不知道你为什么要提到计时器——据我所知,你所描述的一切都没有被计时。此外,你应该能够把你所拥有的东西浓缩成一个小的可运行的例子,然后发布出来,这样别人就可以看到你得到了什么以及它的作用。

像这样的问题有点令人沮丧。几乎有足够的信息来描述你想要什么,或者问题是什么,但并不完全如此

似乎您希望在鼠标进入面板之前添加标签,然后希望外观为标签按钮标签。很难想象我想要一个这样的UI

按钮的外观是否有您不喜欢的地方,您希望它只出现在鼠标面板上?按钮的外观可以改变,使它看起来像你想要的样子,而不需要所有这些带有中间标签和按钮的hocus pocus吗

我不知道你为什么要提到计时器——据我所知,你所描述的一切都没有被计时。此外,你应该能够把你所拥有的浓缩成一个小的可运行的例子,并发布它,这样别人就可以看到你所拥有的和它的作用

我想要的-在鼠标中,按钮应该显示在标签上 它本身(让它重叠)和我应该能够点击 按钮这一切都应该在没有屏幕的情况下非常顺利地进行 忽隐忽现。类似地,在mouseExited中,应移除按钮

由于
JLabel
是从
JComponent
扩展而来,您可以将组件添加到标签本身,只需先设置
LayoutManager
。这一事实在本文中得到了很好的解释

示例代码

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();
            }
        });
    }    

}
输出

更新

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();
            }
        });
    }    

}
正如@nIcEcOw指出的(谢谢!),鼠标事件的转换会产生令人讨厌的闪烁。我改进了这个示例,修复了这个和另一个未处理的方面,比如“当鼠标从
JButton退出时会发生什么?”

我想要的-在鼠标中,按钮应该显示在标签上 它本身(让它重叠)和我应该能够点击 按钮这一切都应该在没有屏幕的情况下非常顺利地进行 忽隐忽现。类似地,在mouseExited中,应移除按钮

由于
JLabel
是从
JComponent
扩展而来,您可以将组件添加到标签本身,只需先设置
LayoutManager
。这一事实在本文中得到了很好的解释

示例代码

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();
            }
        });
    }    

}
输出

更新

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();
            }
        });
    }    

}

正如@nIcEcOw指出的(谢谢!),鼠标事件的转换会产生令人讨厌的闪烁。我改进了示例,修复了这个和另一个未经处理的方面,如“鼠标退出
JButton
”时会发生什么?

@Tvd,以便更快地发布SSCCE,简短、可运行、可编译,因为a.m.问题大约是30-max50代码lines@rcook,计时器的使用只是我的猜测。在网上阅读时,我发现了一些实现,其中在事件中创建了一个计时器,并显示了任何其他组件/动画组件,直到用户出现。当用户移出时,计时器关闭&因此compo。我在想我也可以用这些东西。在我的评论中,我也补充了这一点。是的,我只希望btn在鼠标面板上,隐藏在鼠标左面板上。@Tvd要获得更好的帮助,请尽快发布一个SSCCE,简短、可运行、可编译,因为a.m.问题是大约30-max50代码lines@rcook,计时器的使用只是我的猜测。在网上阅读时,我发现了一些实现,其中在事件中创建了一个计时器,并显示了任何其他组件/动画组件,直到用户出现。当用户移出时,计时器关闭&因此compo。我在想我也可以用这些东西。在我的评论中,我还提到了