Java - MouseListener在paintComponent中的Action事件 [英] Java - MouseListener Action Event in paintComponent

查看:148
本文介绍了Java - MouseListener在paintComponent中的Action事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里我有一个使用paintComponent在mouseClicked位置绘制一个矩形的代码。我可以得到输出消息,但与图形和.draw()相关的任何东西都不会工作。



代码:

  import java.awt。*; 
import java.awt.event。*;
import javax.swing。*;

public final class testclass extends JFrame {

static JPanel p;
定时器t;
int x = 1;
int y = 1;
int xspeed = 1;
int yspeed = 1;

public testclass(){
initComponents();
this.setBounds(100,300,500,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.start();
this.add(p);
}

public void initComponents(){
final ActionListener action = new ActionListener(){

public void actionPerformed(ActionEvent evt){
System.out.println(Hello!);
p.repaint();
}
};

t = new Timer(50,action);
p = new JPanel(){

public void paintComponent(Graphics g){
super.paintComponent(g);
final Graphics2D gD =(Graphics2D)g;
moveBALL();
gD.drawOval(x,y,25,25);

p.addMouseListener(new MouseListener(){

@Override
public void mouseReleased(MouseEvent e){
System.out.println( a);
}

@Override
public void mousePressed(MouseEvent e){
System.out.println(b);
}

@Override
public void mouseExited(MouseEvent e){
System.out.println(c);
}

@Override
public void mouseEntered(MouseEvent e){
System.out.println(d);
}

@Override
public void mouseClicked(MouseEvent e){
gD.drawRect(e.getX(),e.​​getY(),10,60);
gD.setColor(Color.green);
System.out.println(clicked);
}
});
}

void moveBALL(){
x = x + xspeed;
y = y + yspeed;
if(x< 0){
x = 0;
xspeed = -xspeed;
} else if(x> p.getWidth() - 20){
x = p.getWidth() - 20;
xspeed = -xspeed;
}
if(y< 0){
y = 0;
yspeed = -yspeed;
} else if(y> p.getHeight() - 20){
y = p.getHeight() - 20;
yspeed = -yspeed;
}
}
};
}

public static void main(String args []){
EventQueue.invokeLater(new Runnable(){
public void run(){
new testclass()。setVisible(true);
p.setBackground(Color.WHITE);
}
});
}
}

实现mouseListener()的正确方法是什么在这个程序中?
谢谢。

解决方案

关于当前代码的一些建议:




  • 观看类命名方案ie testclass 应该是 TestClass 甚至更好测试(但是这样选择)。所有类名以大写字母开头,其后每个新词均大写。


  • 不要扩展 JFrame


  • 不要在 JFrame 上调用 setBounds 而是使用适当的 LayoutManager 和/或覆盖 getPreferredSize() JPanel 并返回适合其内容的维度。


  • 始终调用 pack() $ c> JFrame ,然后再设置为可见(考虑到以上考虑)。


  • 使用 MouseAdapter vs MouseListener


  • 不要调用 moveBall() / code>在 paintComponent 中调用它在您的计时器中重绘屏幕,不仅稍微更好的设计但是我们也不应该在绘图方法中长时间运行任务。




至于你的问题我觉得你的逻辑是有点偏斜。



一种方法ld看到 Rectangle (或 Rectangle2D )被其自己的自定义类替换(这将允许我们存储属性颜色等)。您的也将拥有自己的类,该类具有方法 moveBall(),其属性如 x y 位置等每个 repaint()您的 JPanel 将调用该方法来移动球, JPanel 本身可以将 moveBall()自己的公共方法,我们可以不打电话给定时器重新屏幕。



这是一个代码示例,上面的修复实现(请分析,如果你有任何问题让我知道):



  import java.awt。*; 
import java.awt.event。*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing。*;

public class Test {

private MyPanel p;
私人定时器t;

public Test(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

initComponents();
frame.add(p);

frame.pack();
frame.setVisible(true);

t.start();
}

private void initComponents(){
final ActionListener action = new ActionListener(){
@Override
public void actionPerformed(ActionEvent evt){
p.moveEntities(); //移动球等
p.repaint();
}
};

t = new Timer(50,action);
p = new MyPanel();

p.addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e){
p.addEntity(e.getX(),e .getY(),10,50,Color.GREEN);
System.out.println(clicked);
}
});

p.setBackground(Color.WHITE);
}

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

class MyPanel扩展JPanel {

int width = 300,height = 300;
ArrayList< MyRectangle> entities = new ArrayList<>();
MyBall ball = new MyBall(10,10,25,25,Color.RED,width,height);

void addEntity(int x,int y,int w,int h,Color c){
entities.add(new MyRectangle(x,y,w,h,c));
}

void moveEntities(){
ball.moveBALL();
}

@Override
protected void paintComponent(Graphics grphcs){
super.paintComponent(grphcs);
Graphics2D g2d =(Graphics2D)grphcs;

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

g2d.setColor(ball.getColor());
g2d.fillOval((int)ball.x,(int)ball.y,(int)ball.width,(int)ball.height); (MyRectangle entity:entities)

{
g2d.setColor(entity.getColor());
g2d.fillRect((int)entity.x,(int)entity.y,(int)entity.width,(int)entity.height);
}
}

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

class MyRectangle extends Rectangle2D.Double {

颜色颜色;

public MyRectangle(double x,double y,double w,double h,Color c){
super(x,y,w,h);
color = c;
}

public void setColor(Color color){
this.color = color;
}

public Color getColor(){
return color;
}
}

class MyBall extends Ellipse2D.Double {

int xspeed = 1;
int yspeed = 1;
颜色颜色;
private final int maxWidth;
private final int maxHeight;

public MyBall(double x,double y,double w,double h,Color c,int maxWidth,int maxHeight){
super(x,y,w,h);
color = c;
this.width = w; //设置Rectangle2D的宽度和高度
this.height = h;
//设置最大宽度和高度球可以移动
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
}

public void setColor(Color color){
this.color = color;
}

public Color getColor(){
return color;
}

void moveBALL(){
x = x + xspeed;
y = y + yspeed;
if(x< 0){
x = 0;
xspeed = -xspeed;
} else if(x> maxWidth - ((int)getWidth()/ 2)){//我不喜欢硬编码值它不好的oractice和resuaibilty是diminshed
x = maxWidth - (( int)getWidth()/ 2);
xspeed = -xspeed;
}
if(y< 0){
y = 0;
yspeed = -yspeed;
} else if(y> maxHeight - ((int)getHeight()/ 2)){
y = maxHeight - ((int)getHeight()/ 2);
yspeed = -yspeed;
}
}
}


Here i have a code which draws a rectangle on the mouseClicked position using the paintComponent.I can get the output message but anything related to graphics and .draw() wont work.

Code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public final class testclass extends JFrame {

    static JPanel p;
    Timer t;
    int x = 1;
    int y = 1;
    int xspeed = 1;
    int yspeed = 1;

    public testclass() {
        initComponents();
        this.setBounds(100, 300, 500, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        t.start();
        this.add(p);
    }

    public void initComponents() {
        final ActionListener action = new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                System.out.println("Hello!");
                p.repaint();
            }
        };

        t = new Timer(50, action);
        p = new JPanel() {

            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                final Graphics2D gD = (Graphics2D) g;
                moveBALL();
                gD.drawOval(x, y, 25, 25);

                p.addMouseListener(new MouseListener() {

                    @Override
                    public void mouseReleased(MouseEvent e) {
                        System.out.println("a");
                    }

                    @Override
                    public void mousePressed(MouseEvent e) {
                        System.out.println("b");
                    }

                    @Override
                    public void mouseExited(MouseEvent e) {
                        System.out.println("c");
                    }

                    @Override
                    public void mouseEntered(MouseEvent e) {
                        System.out.println("d");
                    }

                    @Override
                    public void mouseClicked(MouseEvent e) {
                        gD.drawRect(e.getX(), e.getY(), 10, 60);
                        gD.setColor(Color.green);
                        System.out.println("clicked");
                    }
                });
            }

            void moveBALL() {
                x = x + xspeed;
                y = y + yspeed;
                if (x < 0) {
                    x = 0;
                    xspeed = -xspeed;
                } else if (x > p.getWidth() - 20) {
                    x = p.getWidth() - 20;
                    xspeed = -xspeed;
                }
                if (y < 0) {
                    y = 0;
                    yspeed = -yspeed;
                } else if (y > p.getHeight() - 20) {
                    y = p.getHeight() - 20;
                    yspeed = -yspeed;
                }
            }
        };
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new testclass().setVisible(true);
                p.setBackground(Color.WHITE);
            }
        });
    }
}

What is the proper way to implement a mouseListener() in this program? Thanks.

解决方案

Some suggestions on current code:

  • Watch class naming scheme i.e testclass should be TestClass or even better Test (but thats nit picking). All class names begin with capital letter and each new word thereafter is capitalized.

  • Dont extend JFrame unnecessarily.

  • Dont call setBounds on JFrame rather use appropriate LayoutManager and/or override getPreferredSize() of JPanel and return dimensions which fits its content.

  • Always call pack() on JFrame before setting it visible (taking above into consideration).

  • Use MouseAdapter vs MouseListener

  • Dont call moveBall() in paintComponent rather call it in your Timer which repaints the screen, not only slightly better design but we also should not do possibly long running tasks in paint methods.

As for your problem I think your logic is a bit skewed.

One approach would see the Rectangle (or Rectangle2D) get replaced by its own custom class (which will allow us to store attributes like color etc). Your ball would also have its own class which has the method moveBall() and its attributes like x and y position etc. On every repaint() your JPanel would call the method to move the ball, the JPanel itself could wrap the moveBall() in its own public method which we could than call from the timer which repaints the screen.

Here is an example of your code with above fixes implemented (please analyze it and if you have any questions let me know):

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.*;

public class Test {

    private MyPanel p;
    private Timer t;

    public Test() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initComponents();
        frame.add(p);

        frame.pack();
        frame.setVisible(true);

        t.start();
    }

    private void initComponents() {
        final ActionListener action = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                p.moveEntities();//moves ball etc
                p.repaint();
            }
        };

        t = new Timer(50, action);
        p = new MyPanel();

        p.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                p.addEntity(e.getX(), e.getY(), 10, 50, Color.GREEN);
                System.out.println("clicked");
            }
        });

        p.setBackground(Color.WHITE);
    }

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

class MyPanel extends JPanel {

    int width = 300, height = 300;
    ArrayList<MyRectangle> entities = new ArrayList<>();
    MyBall ball = new MyBall(10, 10, 25, 25, Color.RED, width, height);

    void addEntity(int x, int y, int w, int h, Color c) {
        entities.add(new MyRectangle(x, y, w, h, c));
    }

    void moveEntities() {
        ball.moveBALL();
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setColor(ball.getColor());
        g2d.fillOval((int) ball.x, (int) ball.y, (int) ball.width, (int) ball.height);

        for (MyRectangle entity : entities) {
            g2d.setColor(entity.getColor());
            g2d.fillRect((int) entity.x, (int) entity.y, (int) entity.width, (int) entity.height);
        }
    }

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

class MyRectangle extends Rectangle2D.Double {

    Color color;

    public MyRectangle(double x, double y, double w, double h, Color c) {
        super(x, y, w, h);
        color = c;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
}

class MyBall extends Ellipse2D.Double {

    int xspeed = 1;
    int yspeed = 1;
    Color color;
    private final int maxWidth;
    private final int maxHeight;

    public MyBall(double x, double y, double w, double h, Color c, int maxWidth, int maxHeight) {
        super(x, y, w, h);
        color = c;
        this.width = w;//set width and height of Rectangle2D
        this.height = h;
        //set max width and height ball can move
        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

    void moveBALL() {
        x = x + xspeed;
        y = y + yspeed;
        if (x < 0) {
            x = 0;
            xspeed = -xspeed;
        } else if (x > maxWidth - ((int) getWidth() / 2)) {// i dont like hard coding values its not good oractice and resuaibilty is diminshed
            x = maxWidth - ((int) getWidth() / 2);
            xspeed = -xspeed;
        }
        if (y < 0) {
            y = 0;
            yspeed = -yspeed;
        } else if (y > maxHeight - ((int) getHeight() / 2)) {
            y = maxHeight - ((int) getHeight() / 2);
            yspeed = -yspeed;
        }
    }
}

这篇关于Java - MouseListener在paintComponent中的Action事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆