0

我有一个带有 GroupLayout 的 JPanel,里面有 3 个 JLabel。我还有一个隐藏的 JButton。

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

此时,它们是 2 个标签之间的按钮空间,并且它们唯一的按钮使用 setVisible() 显示或隐藏。当 btn 可见时,它下面的标签会向下为按钮腾出空间,如果 btn 被隐藏,它会再次恢复到原来的大小。

我想要什么 - 在 mouseEntered 中,按钮应该显示在标签本身上(让它重叠),我应该能够点击按钮。这一切都应该非常顺利地发生,没有屏幕闪烁。同样在 mouseExited 中,按钮应该被移除。

我该如何做到这一点?谁能帮我这个。

更新 @Andrew,谢谢我尝试使用 JLayeredPane,它确实有效。尽管该按钮未设置为可见假。这是我的 mouseMoved 代码:

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

奇怪 - 我尝试了带有 null 的布局,FlowLayout,但什么也看不到。尝试使用 BoxLayout 时,组件出现了。

结果在此处输入图像描述

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

4

2 回答 2

2

我想要什么 - 在 mouseEntered 中,按钮应该显示在标签本身上(让它重叠),我应该能够点击按钮。这一切都应该非常顺利地发生,没有屏幕闪烁。同样在 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();
            }
        });
    }    

}

输出

在此处输入图像描述

更新

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

于 2013-10-05T14:30:25.783 回答
1

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

在鼠标进入面板之前,您似乎需要label-label-label,然后您希望外观为label-button-label。很难想象我想要这样的 UI。

您不喜欢按钮的外观,您是否希望它只出现在鼠标悬停面板上?可以更改按钮的外观,使其看起来像您想要的样子,而无需所有这些带有中间标签和按钮的恶作剧吗?

我不知道您为什么提到计时器-您描述的任何内容都没有被计时,据我所知。此外,您应该能够将您所拥有的内容归结为一个可运行的小型示例并将其发布,以便有人可以看到您拥有什么以及它做了什么。

于 2013-10-05T13:58:11.433 回答