当前位置: 首页 > 知识库问答 >
问题:

如何将多个MouseListeners添加到单个JFrame?

竺勇
2023-03-14

我有两件事情要做:在鼠标悬停时突出显示JPanel,在鼠标拖动时移动一个蓝色方块。问题是,这需要我将MouseListeners添加到不同的组件中。当我这样做时,我只能使用一个功能——另一个被阻止了。我该怎么做才能让两个功能都工作?

注意:有时候JFrame不会显示任何东西——你只需要一直运行它,直到它显示为止(通常需要2-3次尝试)。如果它做了任何其他奇怪的事情,就继续运行它,直到它工作。如果之后仍然不起作用,请发表评论

Main(创建JFrame、容器和子对象,并添加鼠标侦听器)

public class Main extends JFrame{
    private static final long serialVersionUID = 7163215339973706671L;
    private static final Dimension containerSize = new Dimension(640, 477);
    static JLayeredPane layeredPane;
    static JPanel container;

    public Main() {
        super("Multiple MouseListeners Test");
        setSize(640, 477);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

        layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(containerSize);
        getContentPane().add(layeredPane);

        createContainer();

        layeredPane.add(container, JLayeredPane.DEFAULT_LAYER);

        createChildren(4, 4);

        new MovableObject();

        MovableObjectMouseListener moml = new MovableObjectMouseListener();
        //comment these two out and the highlighter works
        layeredPane.addMouseListener(moml);
        layeredPane.addMouseMotionListener(moml);
    }

    private void createChildren(int columns, int rows){
        for (int i = 0; i < columns; i++){
            for (int j = 0; j < rows; j++){
                JPanel child = new JPanel(new BorderLayout());
                child.setBackground(Color.LIGHT_GRAY);
                //comment this out and you can move the MovableObject
                child.addMouseListener(new HighlightJPanelsMouseListener());
                container.add(child);
            }
        }
    }

    private JPanel createContainer(){
        container = new JPanel();
        container.setLayout(createLayout(4, 4, 1, 1));
        container.setPreferredSize(containerSize);
        container.setBounds(0, 0, containerSize.width, containerSize.height);
        return container;
    }

    private GridLayout createLayout(int rows, int columns, int hGap, int vGap){
        GridLayout layout = new GridLayout(rows, columns);
        layout.setHgap(hGap);
        layout.setVgap(vGap);
        return layout;
    }

    public static void main(String[] args) {
        new Main();
    }
}

HighlightJPanelMouseListener(创建将添加到子级的MouseListener)

public class HighlightJPanelsMouseListener implements MouseListener{
    private Border grayBorder = BorderFactory.createLineBorder(Color.DARK_GRAY);

    public HighlightJPanelsMouseListener() {
    }

    public void mouseEntered(MouseEvent e) {
        Component comp = (Component) e.getSource();
        JPanel parent = (JPanel) comp;
        parent.setBorder(grayBorder);
        parent.revalidate();
    }

    public void mouseExited(MouseEvent e) {
        Component comp = (Component) e.getSource();
        JPanel parent = (JPanel) comp;
        parent.setBorder(null);
        parent.revalidate();
    }

    public void mousePressed(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseClicked(MouseEvent e) {}
}

MovableObject(创建MovableObject)

下载blueSquare。png,或使用其他图像。记住把下面图片的名字改成你的名字。

public class MovableObject {
    public MovableObject() {
        JPanel parent = (JPanel) Main.container.findComponentAt(10, 10);
        ImageIcon icon = null;
        //use any image you might have laying around your workspace - or download the one above
        URL imgURL = MovableObject.class.getResource("/blueSquare.png");

        if (imgURL != null){
            icon = new ImageIcon(imgURL);
        }else{
            System.err.println("Couldn't find file");
        }

        JLabel movableObject = new JLabel(icon);
        parent.add(movableObject);
        parent.revalidate();
    }
}

MovableObjectMouseListener(创建用于MovableObject的MouseListener)

public class MovableObjectMouseListener implements MouseListener, MouseMotionListener{
    private JLabel replacement;
    private int xAdjustment, yAdjustment;

    public void mousePressed(MouseEvent e){
        replacement = null;
        Component c =  Main.container.findComponentAt(e.getX(), e.getY());

        if (!(c instanceof JLabel)){
            return;
        }

        Point parentLocation = c.getParent().getLocation();
        xAdjustment = parentLocation.x - e.getX();
        yAdjustment = parentLocation.y - e.getY();
        replacement = (JLabel)c;
        replacement.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);

        Main.layeredPane.add(replacement, JLayeredPane.DRAG_LAYER);
        Main.layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    }

    public void mouseDragged(MouseEvent me){
        if (replacement == null){
            return;
        }

        int x = me.getX() + xAdjustment;
        int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
        x = Math.min(x, xMax);
        x = Math.max(x, 0);

        int y = me.getY() + yAdjustment;
        int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
        y = Math.min(y, yMax);
        y = Math.max(y, 0);

        replacement.setLocation(x, y);
     }


    public void mouseReleased(MouseEvent e){
        Main.layeredPane.setCursor(null);

        if (replacement == null){
            return;
        }

        int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
        int x = Math.min(e.getX(), xMax);
        x = Math.max(x, 0);

        int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
        int y = Math.min(e.getY(), yMax);
        y = Math.max(y, 0);


        Component c = Main.container.findComponentAt(x, y);
        Container parent = (Container) c;
        parent.add(replacement);
        parent.validate();  
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

共有1个答案

丰誉
2023-03-14

我没有详细查看您的代码,但我建议您需要将拖动MouseListener添加到可移动对象(即JLabel),而不是面板。然后标签将获得拖动事件,面板将获得鼠标输入/退出事件。

这将导致在移动标签时生成mouseExited事件的另一个问题(这是您不希望发生的)。查看:如何避免在任何嵌套组件上启动鼠标,以解决此问题。

 类似资料:
  • 问题内容: 所以,我想要的是选择一个项目时要运行的另一段代码。但是我的问题是,如何对特定项目实施? 这是我的代码: 我该怎么做才能添加到“车辆”,“自行车/自行车”,“船”,“房屋”,“企业”,“对象”,“工作”,“等级”和“许可证”项中? 问题答案: 如果您希望在选择更改时发生某些事情,则不希望使用MouseListener,而希望使用。它不仅是正确的抽象,而且请记住,不使用鼠标就可以更改选择。

  • 问题内容: 我有一个 JFrame 。 我也有一个 Box 类,它扩展了 Component 。该box类具有一个 paint 方法,该方法可以创建一个填充的矩形。 当我将这些Box组件的多个添加到我的JFrame时,当我在JFrame上调用 重绘 时,仅显示最近添加的一个。 我看了一下布局管理器,但是我不确定那不是我想要的。我所希望的是能够在屏幕上的任何位置制作整个矩形的动画。 (我还尝试创建一

  • 我在边框的中心有一个标题栏。对于链接哈希图中的每个条目,我想在标题栏中添加一个按钮。这个标题栏已经存在于fxml文件中,并且具有fx: id field dContainer。 如果一次添加一个键值对,按钮将一个接一个出现。但是,当我试图通过从文本文件导入链接的hashmap一次添加它们时,按钮不会出现。它将加载一个条目,然后抛出nullpointerexception。 导入文本文件和将条目添加

  • 我想合并/添加一个新泽西项目B(已经运行良好)到一个新泽西项目a,这将充当一个过滤器/安全层。因此,作为一个基本步骤,我在项目a的构建路径上向项目B添加了依赖项,并在构建路径中向部署程序集添加了相同的依赖项。我从这篇文章中了解到,我可以通过将servlet放在同一个中,并使用以不同的方式映射它们来实现这一点。当我试图访问项目B的资源时,我没有任何运气。 因此,当我尝试访问时,它工作得很好。但是当我

  • 我希望来自两个不同类的两个图像并排扩展JPanel。 我遇到的问题是两个JPanel应该在JFrame内部,但是当我做framename.add(panel)时,它会替换另一个,而不是并排添加其中两个。 我尝试在主类中添加flowlayout和其他布局,但是没有一个图像显示出来。 所以我的问题是,如果我有两个扩展Jpanel的类,我如何在Jframe中添加这两个面板,以便它们并排(彼此相邻)而不替

  • 我正在尝试将日志从单台机器上的不同目录收集到本地文件系统文件或 HDFS。 我已经注册了 2 个来源 r1、r2。两个源都指向单通道C1。有一个接收器连接到通道。K1 请找到下面的配置文件: 但是当我使用代理 a1 启动 Flume 时,只有一个源 (r2) 正在启动。水槽代理启动日志: 谢谢