在MouseListener的画布不工作(MouseListener in Canvas not w

2019-10-16 17:24发布

我有一个游戏,我试图用Java做的一个问题。 我想一个MouseListener的连接到我的画布,然而,当我点击画布上,没有任何反应。 我想我可能会附着在MouseListener的到了错误的事情,但我不知道是什么把它连接到。 我曾尝试将其连接到JFrame和画布。 这里是我的代码:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.Random;

public class Gravity extends Canvas {

    public static final int screenw = 1024;
    public static final int screenh = 768;

    public static Random gen = new Random();

    public static Boolean started = false;

    public static int[] starx = new int[100];
    public static int[] stary = new int[100];
    public static Color[] starc = new Color[100];

    public static JFrame frame;
    public static Gravity canvas;
    public static Image buffer;
    public static Graphics bg;

    public static int[] xh = new int[1000];
    public static int[] yh = new int[1000];

    public static int i = 0;

    public static Image title;

    public static ArrayList<Integer> ptx = new ArrayList<Integer>();
    public static ArrayList<Integer> pty = new ArrayList<Integer>();
    double x = 100;
    double y = 100;

    public Gravity(){
    }

    public void paint (Graphics g) {
        frame.addMouseListener(new MouseListener(){
            public void mouseClicked(MouseEvent e){
                started = true;
                System.out.println("Mouse was clicked");
            }

            public void mouseEntered(MouseEvent arg0) {}
            public void mouseExited(MouseEvent arg0) {}
            public void mousePressed(MouseEvent arg0) {}
            public void mouseReleased(MouseEvent arg0) {}
        });


        buffer = createImage(screenw, screenh);
        bg = buffer.getGraphics();

        int w = getWidth();
        int h = getHeight();

        double px = getWidth()/2; 
        double py = getHeight()/2;

        bg.setColor(Color.BLACK);
        bg.fillRect(0, 0, w, h); //black background

        for (int j=0; j < 100; j++){ //make stars
            starx[j] = gen.nextInt(w);
            stary[j] = gen.nextInt(h);
            starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
            bg.setColor(starc[j]);
            bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
            bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
        }

        try {
            title = ImageIO.read(new ByteArrayInputStream(Base64.decode(""))); //I have omitted the Base64 code for the image for my title screen
        } catch (IOException e) {
            e.printStackTrace();
        }

        bg.drawImage(title, 100, 100, null);
        g.drawImage(buffer, 0, 0, null);

        while (!started){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }

        double xvel = -15;
        double yvel = 10;

        for (int j=0; j < 100; j++){ //store stars
            starx[j] = gen.nextInt(w);
            stary[j] = gen.nextInt(h);
            starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
        }

        Image test = createImage(200,200);
        Graphics testg = test.getGraphics();
        testg.drawLine(50,50,150,150);

        while(true){
            g.drawImage(buffer, 0,0, null);
            try {
                Thread.sleep(33);
            } catch (Exception e) {
                e.printStackTrace();
            }

            bg.setColor(Color.BLACK);
            bg.fillRect(0, 0, w, h); //black background


            for (int j=0; j < 100; j++){ //draw stars
                bg.setColor(starc[j]);
                bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
                bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
            }

            bg.setColor(Color.BLUE);

            if (i > 0){
                for (int z=0; z < i-1; z++){
                    bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1));
                }
            }

            bg.setColor(Color.CYAN);
            bg.fillOval((int)px, (int)py, 25, 25); //planet

            bg.setColor(Color.RED);
            bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship

            double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2));

            double m = (y-py)/(x-px);
            double ms = Math.sqrt(Math.abs(m));
            if (m < 0) ms = -ms;

            double xchg = fg;
            double ychg = fg*ms;

            if (x > px){
                xchg = -xchg;
                ychg = -ychg;
            }

            xvel += xchg;
            yvel += ychg;

            x += xvel;
            y += yvel;

            ptx.add((int)x);
            pty.add((int)y);

            i++;
        }
    }

    public static void main(String[] args){

        canvas = new Gravity();
        frame = new JFrame();
        frame.setSize(screenw, screenh);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(canvas);

        frame.setVisible(true);
    }


    public static double dist(double x1, double y1, double x2, double y2){
        double x = x2-x1;
        double y = y2-y1;
        return Math.sqrt((x*x)+(y*y));
    }
}

Answer 1:

一般的提示,以点形式:

  1. 不要混合使用AWT(如Canvas与Swing(EG) JFrame )组件。 取而代之的是帆布的,使用JPanel并重写paintComponent(Graphics) ,而不是paint(Graphics)
  2. 不要调用Thread.sleep(n)在EDT。 而是使用基于Swing的Timer调用repaint()
  3. 不要在paint方法执行长时间运行的操作,尤其是开始一个无限循环! 即使缓冲图片的创作只应在的情况下完成的屏幕大小的变化。 (左为 'TODO' - BNI)
  4. 添加MouseListener在构造函数中一次或init()方法,而不是每次油漆被调用。
  5. 强烈建议所有Nate的编号的笔记列表。

试试这个代码,并仔细比较它原来看到的变化。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.event.*;
import java.util.ArrayList;

import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.Random;

public class Gravity extends JPanel {

    public static final int screenw = 800;
    public static final int screenh = 600;

    public static Random gen = new Random();

    public static int[] starx = new int[100];
    public static int[] stary = new int[100];
    public static Color[] starc = new Color[100];

    public static Image buffer;
    public static Graphics bg;

    public static int[] xh = new int[1000];
    public static int[] yh = new int[1000];

    public static int i = 0;

    public static ArrayList<Integer> ptx = new ArrayList<Integer>();
    public static ArrayList<Integer> pty = new ArrayList<Integer>();
    double x = 100;
    double y = 100;

    Timer timer;

    public Gravity(){
        // set thre PREFERRED size!
        setPreferredSize(new Dimension(screenw, screenh));
        addMouseListener(new MouseListener(){
                    public void mouseClicked(MouseEvent e){
                        System.out.println("Mouse was clicked");
                        timer.start();
                    }

                    public void mouseEntered(MouseEvent arg0) {}
                    public void mouseExited(MouseEvent arg0) {}
                    public void mousePressed(MouseEvent arg0) {}
                    public void mouseReleased(MouseEvent arg0) {}
        });
        ActionListener animation = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                repaint();
            }
        };
        timer = new Timer(50, animation);
    }

    @Override
    public void paintComponent(Graphics g) {
        buffer = createImage(screenw, screenh);
        bg = buffer.getGraphics();

        int w = getWidth();
        int h = getHeight();

        double px = getWidth()/2;
        double py = getHeight()/2;

        bg.setColor(Color.BLACK);
        bg.fillRect(0, 0, w, h); //black background

        for (int j=0; j < 100; j++){ //make stars
            starx[j] = gen.nextInt(w);
            stary[j] = gen.nextInt(h);
            starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
            bg.setColor(starc[j]);
            bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
            bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
        }

        g.drawImage(buffer, 0, 0, null);

        double xvel = -15;
        double yvel = 10;

        for (int j=0; j < 100; j++){ //store stars
            starx[j] = gen.nextInt(w);
            stary[j] = gen.nextInt(h);
            starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
        }

        Image test = createImage(200,200);
        Graphics testg = test.getGraphics();
        testg.drawLine(50,50,150,150);

        g.drawImage(buffer, 0,0, null);
        try {
            Thread.sleep(33);
        } catch (Exception e) {
            e.printStackTrace();
        }

        bg.setColor(Color.BLACK);
        bg.fillRect(0, 0, w, h); //black background


        for (int j=0; j < 100; j++){ //draw stars
            bg.setColor(starc[j]);
            bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
            bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
        }

        bg.setColor(Color.BLUE);

        if (i > 0){
            for (int z=0; z < i-1; z++){
                bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1));
            }
        }

        bg.setColor(Color.CYAN);
        bg.fillOval((int)px, (int)py, 25, 25); //planet

        bg.setColor(Color.RED);
        bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship

        double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2));

        double m = (y-py)/(x-px);
        double ms = Math.sqrt(Math.abs(m));
        if (m < 0) ms = -ms;

        double xchg = fg;
        double ychg = fg*ms;

        if (x > px){
            xchg = -xchg;
            ychg = -ychg;
        }

        xvel += xchg;
        yvel += ychg;

        x += xvel;
        y += yvel;

        ptx.add((int)x);
        pty.add((int)y);

        i++;
    }

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().add(new Gravity());
                frame.setResizable(false);
                frame.pack();

                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }


    public static double dist(double x1, double y1, double x2, double y2){
        double x = x2-x1;
        double y = y2-y1;
        return Math.sqrt((x*x)+(y*y));
    }
}


Answer 2:

用一个JComponent而不是Canvas的。 你会想鼠标监听器添加到该对象。 您还需要设置鼠标监听器在构造函数,而不是paint()方法。

编辑:你在做多,在paint()方法作为@AndrewThompson指出。

public Gravity() {
    addMouseListener(new MouseListener() {

        @Override
        public void mouseClicked(MouseEvent e) {
            System.out.println("Mouse was clicked");
        }

        @Override
        public void mouseEntered(MouseEvent arg0) {
        }

        @Override
        public void mouseExited(MouseEvent arg0) {
        }

        @Override
        public void mousePressed(MouseEvent arg0) {
        }

        @Override
        public void mouseReleased(MouseEvent arg0) {
        }
    });
}

@Override
public void paint(Graphics g) {

    buffer = createImage(screenw, screenh);
    bg = buffer.getGraphics();

    ...

    bg.setColor(Color.BLACK);
    bg.fillRect(0, 0, w, h); // black background

    for (int j = 0; j < 100; j++) { // make stars
        ...
    }

    bg.drawImage(title, 100, 100, null);
    g.drawImage(buffer, 0, 0, null);

    double xvel = -15;
    double yvel = 10;

    for (int j = 0; j < 100; j++) { // store stars
        ...
    }

    Image test = createImage(200, 200);
    Graphics testg = test.getGraphics();
    testg.drawLine(50, 50, 150, 150);

    g.drawImage(buffer, 0, 0, null);
    bg.setColor(Color.BLACK);
    bg.fillRect(0, 0, w, h); // black background

    for (int j = 0; j < 100; j++) { // draw stars
        ...
    }

    bg.setColor(Color.BLUE);

    if (i > 0) {
        for (int z = 0; z < i - 1; z++) {
            bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z + 1), pty.get(z + 1));
        }
    }

    bg.setColor(Color.CYAN);
    bg.fillOval((int) px, (int) py, 25, 25); // planet

    bg.setColor(Color.RED);
    bg.fillRect((int) (x - 5), (int) (y - 5), 10, 10); // ship

    ....

    ptx.add((int) x);
    pty.add((int) y);
}

public static void main(String[] args) {
    ...

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    ...
}

关于你的代码注释:

  1. 避免领域public static 。 这是没有必要的,而且通常99.9%的时间带来了麻烦以后。
  2. 这幅画代码似乎不必要地使用缓冲区-该test图像是不是在所有目前使用的!
  3. 我删除了while(true)循环,但发现您正在绘制的图像,修改图像,然后再绘制图像。 你也许可以做到这一点一气呵成。
  4. 你应该能够避免使用的Image完全因为你正在创建一个新的每次缓冲paint()被调用,并在开始清理它。 只需直接绘制图形来g
  5. 避免从内执行I / O paint()方法。 施工期间或在后台线程加载图片。


Answer 3:

您paint()方法被占用,处理鼠标点击事件,由于在线程(!开始)循环,永不退出。 开始是不正确的,因为的MouseListener的的mouseClicked()不会被调用,因为开始是真实的paint()方法在等待! 如果删除循环中,while(true)循环将产生类似的效果。 而油漆发生任何鼠标事件()运行后会排队,直到paint()方法返回。



文章来源: MouseListener in Canvas not working