首页 > 解决方案 > 绘制组件似乎导致光标和标签的鼠标侦听器不起作用

问题描述

用于将LayerUI标签添加到选项卡式窗格的上角。想让这些标签显示为超链接,所以我将颜色设置为蓝色,将光标设置为一只手,然后添加一个mouselistener.

但是,当我绘制组件时,光标自定义和鼠标侦听器不起作用。

示例图像

在此处输入图像描述

示例应用程序:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.plaf.LayerUI;

public class TopRightCornerLabelLayerUITest {
    public static JPanel makeUI() {
        JPanel resultPanel = new JPanel();
        resultPanel.setLayout( new BorderLayout());
        resultPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.add("Tab 1", new JPanel());  
        tabbedPane.add("Tab 2", new JPanel());  

        resultPanel.add(new JLayer<JComponent>(tabbedPane, new TopRightCornerLabelLayerUI()), BorderLayout.CENTER);

        return resultPanel;
    }

    private static void initandShow()
    {
        JDialog dialog = new JDialog();
        dialog.getContentPane().add(makeUI());
        dialog.setSize(520, 240);
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
    }

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

    }
}

class TopRightCornerLabelLayerUI extends LayerUI<JComponent> {
    private JPanel rubberStamp = new JPanel();

    @Override public void paint(Graphics g, JComponent c) {
        super.paint(g, c);

        JLabel layoutHyperlink = new JLabel("<html><a href=''>File Layout and Descriptions</a></html>");
        JLabel templateHyperlink = new JLabel("<html><a href=''>Download Template</a></html>");

        layoutHyperlink.setForeground(Color.BLUE.darker());
        layoutHyperlink.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        layoutHyperlink.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // the user clicks on the label
                System.err.println("clicked");
            }
       });

        templateHyperlink.setForeground(Color.BLUE.darker());
        templateHyperlink.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        templateHyperlink.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // the user clicks on the label
                System.err.println("clicked");

            }
       });

        // Add components
        Dimension templateDimension = templateHyperlink.getPreferredSize();
        int x = c.getWidth() - templateDimension.width - 5;
        SwingUtilities.paintComponent(g, templateHyperlink, rubberStamp, x, 2, templateDimension.width , templateDimension.height);

        Dimension layoutDimension = layoutHyperlink.getPreferredSize();
        x = c.getWidth() - layoutDimension.width - 15 - templateDimension.width;
        SwingUtilities.paintComponent(g, layoutHyperlink, rubberStamp, x, 2, layoutDimension.width, templateDimension.height);

    }
}

标签: javaswing

解决方案


JLayer在我读到你的问题之前,我实际上是不知道上课的。我没有完整的答案,但我认为这足以让你朝着正确的方向前进。Oracle的 Java 教程中的课程帮助了我:如何使用 JLayer 类装饰组件。那节课有一节题为“响应事件” ,它帮助我弄清楚如何部分解决您的问题。基本上,您只是在绘制标签,而不是实际将它们添加为组件,因此它们不会响应鼠标事件。由于标签可以被认为JLayer作为组件添加的组件的一部分,因此您可以配置JLayer响应鼠标事件。如教程课程中所述,您需要覆盖TopRightCornerLabelLayerUI类中的其他一些方法。下面的代码包含其中两种方法。将它们添加到您的代码中,看看它们是否会给您预期的结果。

public void installUI(JComponent c) {
    super.installUI(c);
    ((JLayer<?>) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}

protected void processMouseEvent(MouseEvent e, JLayer l) {
    if (e.getID() == MouseEvent.MOUSE_CLICKED) {
        Point pt = e.getPoint();
        if (pt.x >= xTemplateHyperlink  &&  pt.x <= (xTemplateHyperlink + widthTemplateHyperlink)) {
            System.out.println("clicked");
        }
    }
}

编辑:忘了提到我在你的TopRightCornerLabelLayerUI班级中添加了以下成员......

private int xTemplateHyperlink;
private int yTemplateHyperlink;
private int widthTemplateHyperlink;
private int heightTemplateHyperlink;

并像这样在方法中设置它们的值paint()......

Dimension templateDimension = templateHyperlink.getPreferredSize();
xTemplateHyperlink = c.getWidth() - templateDimension.width - 5;
yTemplateHyperlink = 2;
widthTemplateHyperlink = templateDimension.width;
heightTemplateHyperlink = templateDimension.height;

它解释了方法中的代码processMouseEvent()


推荐阅读