按下鼠标指针,按下时创建一个对象

时间:2013-03-10 18:33:55

标签: java swing jpanel paintcomponent

我想制作一个在屏幕上有对象的程序,然后当你按下它们时它将跟随鼠标指针,直到你释放鼠标然后它将不再跟随鼠标。

这是我必须向屏幕添加球的代码,所以如果可以只调整代码就会很棒。它分为3个类

import java.awt.BorderLayout;
import java.awt.event.*;
 import java.util.Random;
import javax.swing.*;


public class DrawBalls {
JFrame frame = new JFrame();
final DrawPanel drawPanel = new DrawPanel();
JPanel controlPanel = new JPanel();
JButton createBallButton = new JButton("Add ball");

DrawBalls(){
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    controlPanel.add(createBallButton);
    frame.add(drawPanel);
    frame.add(controlPanel, BorderLayout.SOUTH);
     frame.pack();
    frame.setVisible(true);
     {
         drawPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
            super.mouseMoved(e);
            for (Ball b : drawPanel.getBalls()) {
                if (b.getBounds().contains(me.getPoint())) {
                  //this has it being the same coordinates as the mouse i don't know   
                  //how to have it run constantly so when i move it, it doesn't work  

                  b.setx(me.getX()-(b.radius/2));
                  b.sety( me.getY()-(b.radius/2));   
                     drawPanel.repaint();
            }

        }
    }



     });
         createBallButton.addActionListener(new ActionListener() {
        Random rand = new Random();
        private int counter = 1;
 int noOfClicks = 1;

        public void actionPerformed(ActionEvent e) {


            if(noOfClicks<=10){

            int ballRadius = 10;
            int x = rand.nextInt(drawPanel.getWidth());
            int y = rand.nextInt(drawPanel.getHeight());

            //check that we dont go offscreen by subtarcting its radius unless its x and y are not bigger than radius
            if (y > ballRadius) {
                y -= ballRadius;
            }
            if (x > ballRadius) {
                x -= ballRadius;
            }

            drawPanel.addBall(new Ball(x, y, ballRadius, counter));//add ball to panel to be drawn
            counter++;//increase the ball number
        noOfClicks++;
        }
            }
    });        
}
public static void main(String[] args) {
   SwingUtilities.invokeLater(new Runnable() {
         @Override
        public void run() {
            new DrawBalls();
        }
    });
}

球类

import java.awt.*;
import java.awt.geom.*;

 public class Ball {
 private Color color;
 private int x, y;
 private int radius;
 private final int number;

Ball(int x, int y, int radius, int counter) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.number = counter;

    this.color = Color.RED;
  }
 public void draw(Graphics2D g2d) {
    Color prevColor = g2d.getColor();
    g2d.drawString(number + "", x + radius, y + radius);
    g2d.setColor(color);
    g2d.fillOval(x, y, radius, radius);
    g2d.setColor(prevColor);
}
public Rectangle2D getBounds() {
    return new Rectangle2D.Double(x, y, radius, radius);

}
int getNumber() {
    return number;
}
}

DrawPanel

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

 public class DrawPanel extends JPanel {
  ArrayList<Ball> balls = new ArrayList<Ball>();

   public void addBall(Ball b) {
      balls.add(b);
       repaint();
    }

   public ArrayList<Ball> getBalls() {
      return balls;
}
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    for (Ball ball : balls) {
        ball.draw(g2d);
    }
}
    @Override
public Dimension getPreferredSize() {
    return new Dimension(300, 300);
}

}

1 个答案:

答案 0 :(得分:2)

一种方法是使您的Ball类成为实际的Swing组件。然后你可以使用ComponentMover类。

编辑:

  

如何将课程变成一个摇摆组件

基本上,您将draw(...)代码移动到JComponent的paintComponent()方法中。这是一个简单的示例,可以为您完成所有自定义绘制,因为绘制基于Shape对象。您仍然需要修改代码以绘制“数字”。

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

public class ShapeComponent extends JComponent
{
    Shape shape;

    public ShapeComponent(Shape shape)
    {
        this.shape = shape;
        setOpaque( false );
    }

    public Dimension getPreferredSize()
    {
        Rectangle bounds = shape.getBounds();
        return new Dimension(bounds.width, bounds.height);
    }

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

        g2d.setColor( getForeground() );
        g2d.fill( shape );
    }

    @Override
    public boolean contains(int x, int y)
    {
        return shape.contains(x, y);
    }

    private static void createAndShowUI()
    {
        ShapeComponent ball = new ShapeComponent( new Ellipse2D.Double(0, 0, 50, 50) );
        ball.setForeground(Color.GREEN);
        ball.setSize( ball.getPreferredSize() );
        ball.setLocation(10, 10);

        ShapeComponent square = new ShapeComponent( new Rectangle(30, 30) );
        square.setForeground(Color.ORANGE);
        square.setSize( square.getPreferredSize() );
        square.setLocation(50, 50);

        JFrame frame = new JFrame();
        frame.setLayout(null);
        frame.add(ball);
        frame.add(square);
        frame.setSize(200, 200);
        frame.setVisible(true);

        MouseListener ml = new MouseAdapter()
        {
            public void mouseClicked( MouseEvent e )
            {
                System.out.println( "clicked " );
            }
        };

        ball.addMouseListener( ml );
        square.addMouseListener( ml );
    }

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

这种方法与trashgod使用Icon的建议之间的主要区别在于鼠标事件仅在鼠标悬停在球上时生成,而不是球的矩形角,因为contains(...)方法尊重形状你画的是什么。