简体   繁体   English

在Swing中的JLabel上显示按钮

[英]Show button on JLabel in Swing

I have a JPanel with GroupLayout with 3 JLabels in it. 我有一个带有3个JLabel的GroupLayout的JPanel。 I also have a hidden JButton in it. 我也有一个隐藏的JButton。

I have added a MouseListener to JPanel showing the button in mouseEntered and hide the button in mouseExited events respectively. 我已经向JPanel添加了MouseListener,以在mouseEntered中显示按钮,并分别在mouseExited事件中隐藏按钮。

At this time, their is space for button between 2 labels and their only the button is shown or hidden using setVisible(). 此时,它们是2个标签之间的按钮空间,并且仅使用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. 当btn可见时,其下方的标签会下降,从而为按钮留出空间;如果btn隐藏,则其大小将再次恢复为原始大小。

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. 我想要的-在mouseEntered中,按钮应该显示在标签本身上(让它重叠),并且我应该能够单击该按钮。 This all should happen very smoothly without screen flickering. 所有这些都应该非常平稳地发生,而不会出现屏幕闪烁。 Similarly in mouseExited, the button should be removed. 同样,在mouseExited中,应删除按钮。

How do I achieve this ? 我该如何实现? Can anyone help me with this. 谁能帮我这个。

UPDATE @Andrew, Thanks I tried with JLayeredPane and it does work. 更新 @Andrew,谢谢我尝试使用JLayeredPane,它确实有效。 Though the button is not set to visible false. 虽然该按钮未设置为visible false。 Here's my mouseMoved code : 这是我的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();
        }
    }
}

Layout of the JPanel : 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. 奇怪-我尝试使用null,FlowLayout进行布局,但什么也看不到。 When tried with BoxLayout, components showed up. 当尝试使用BoxLayout时,出现了组件。

REsult : 结果 在此处输入图片说明

Main screen has a JPanel with Gridlayout(2, 3) and in each cell this JPanel (MyPanel) is added. 主屏幕上有一个带有Gridlayout(2,3)的JPanel,并且在每个单元格中都添加了这个JPanel(MyPanel)。 When I come out from 1 cell (ie MyPanel) the button of that panel should be hidden which is not happening with the above code. 当我从1个单元格(即MyPanel)出来时,该面板的按钮应该被隐藏,而上面的代码并没有发生。 What can be the reason ? 可能是什么原因? I also added revalidate() & also repaint() but nothing works. 我还添加了revalidate()和repaint(),但是没有任何效果。 ???? ????

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. 我想要的-在mouseEntered中,按钮应该显示在标签本身上(让它重叠),并且我应该能够单击该按钮。 This all should happen very smoothly without screen flickering. 所有这些都应该非常平稳地发生,而不会出现屏幕闪烁。 Similarly in mouseExited, the button should be removed. 同样,在mouseExited中,应删除按钮。

As JLabel extends from JComponent you can add componentes to label itself, just need to set a LayoutManager first. 随着JLabelJComponent扩展而来,您可以添加组件以标记自身,只需首先设置LayoutManager 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 输出量

在此处输入图片说明

Update 更新资料

As @nIcEcOw pointed out (thanks!), there's an annoying flickering generated by mouse events' transition. 正如@nIcEcOw指出的(谢谢!),鼠标事件的过渡会产生烦人的闪烁。 I improved the example fixing this and another untreated aspects like "what happens when mouse exits from JButton ?" 我改进了修复此问题的示例以及另一个未处理的方面,例如“当鼠标从JButton退出时会发生什么?”

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. 似乎您希望在鼠标进入面板之前使用label-label-label,然后您希望外观是label-button-label。 It's hard to imagine me wanting a UI to act like this. 很难想象我想要一个UI像这样。

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. 此外,您应该能够将所需的内容简化为一个可运行的小示例,然后将其发布,以便其他人可以看到您所拥有的内容及其作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM