簡體   English   中英

如何獲取java swing中鼠標的實時位置?

[英]How to get the live location of mouse in java swing?

我正在嘗試創建一個簡單的井字游戲,我想在鼠標所在的正方形上顯示高亮。 我在java.awt.Canvas上繪制游戲,目前,我嘗試了這些失敗的方法:

  • 我嘗試將MouseAdapter添加到我的 Canvas 並覆蓋其mouseEnter方法,但它僅在 cursor 進入畫布時起作用(正如它應該的那樣)。
  • 然后我添加了 9 個JPanel (每個正方形一個)並為每個添加了一個MouseAdapter 但它也沒有奏效。 我搜索了原因,發現我應該requestFocus()來啟用監聽器。

順便說一句,這是我的代碼:

Class 用於覆蓋MouseAdaper的方法:

public class MouseInput extends MouseAdapter {

    private final Game game;
    private final int i;
    private final int j;

    public MouseInput(Game game, JPanel panel){
        this.game = game;
        i = panel.getY() / 64;
        j = panel.getX() / 64;
    }
    @Override
    public void mouseEntered(MouseEvent e) {
        game.mouseEntered(i, j);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        game.mouseExited(i, j);
    }

    @Override
    public void mouseClicked(MouseEvent e){
        game.mouseClicked(i, j);
    }
}

游戲中的JPanel並向其中添加MouseListener

public class Game extends Canvas implements Runnable {
    private boolean isRunning = false;
    private Thread thread;
    private final JPanel[][] panels = new JPanel[3][3];

    public static void main(String[] args) {

        Game game = new Game();
        game.setPreferredSize(new Dimension(192, 192));

        JFrame frame = new JFrame();
        frame.add(game);
        frame.setResizable(false);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        game.start();
    }

    private void start(){
        if(isRunning){
            return;
        }

        isRunning = true;
        thread = new Thread(this);
        thread.start();
    }

    private void stop(){
        if(!isRunning){
            return;
        }

        isRunning = false;
        try {
            thread.join();
        } catch (InterruptedException ignored) {}
        System.exit(0);
    }

    @Override
    public void run(){
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < 3; j++){
                JPanel p  = new JPanel();
                p.setPreferredSize(new Dimension(64, 64));
                p.setLocation(j * 64, i * 64);
                p.addMouseListener(new MouseInput(this, p));
                panels[i][j] = p;
            }
        }
    }
}

Swing 不是線程安全的,是單線程的。 您不應該從事件調度線程的上下文之外更新 UI 或更新 UI 依賴的東西。

在您的情況下,面板實際上並未附加到任何東西(即添加到容器中),因此無法響應任何事件。

您還應該花時間學習一些布局管理基礎知識。

鼠標移動

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();

                JPanel board = new JPanel(new GridLayout(3, 3));
                for (int index = 0; index < 9; index++) {
                    board.add(new GridPane());
                }

                frame.add(board);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GridPane extends JPanel {

        private MouseListener mouseHandler;

        public GridPane() {
            setBorder(new LineBorder(Color.BLACK));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }

        @Override
        public void addNotify() {
            super.addNotify(); 

            if (mouseHandler != null) {
                removeMouseListener(mouseHandler);
            }

            mouseHandler = new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    setBackground(Color.RED);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    setBackground(null);
                }
            };

            addMouseListener(mouseHandler);
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            if (mouseHandler != null) {
                removeMouseListener(mouseHandler);
            }
        }


    }
}

而不是試圖讓一個聽眾嘗試更新游戲 model。 將游戲參考傳遞給每個面板並讓它完成這項工作。 這樣,您可以將“標識符”傳遞給每個可以傳遞回游戲的單元格,以便它可以做出一些需要的決定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM