在Panel中绘制一个球并使用mouseDragged移动球

时间:2017-05-27 21:41:09

标签: java graphics awt java-2d

我正在练习在面板中画一个球并在球被拖动时显示球的坐标。

这是我第一次练习绘画练习(?)

这是我的代码。

import java.awt.*;
 import java.awt.event.*;

public class MovingBall extends Frame {
Panel ballPanel = new Panel();
Label ballLabel = new Label();
Panel coordinatePanel = new Panel();
Label coordinateLabel = new Label();
int x0=0,y0 =0, x=20,y=30;
int nowX, nowY;
Label nowXcoordinateLabel = new Label("Now X :"+nowX);
Label nowYcoordinateLabel = new Label("Now Y :"+nowY);
MovingBall(){
    setLayout(new GridLayout(1,1));
    ballPanel.add(ballLabel); coordinatePanel.add(coordinateLabel);

    add(ballPanel);
    add(coordinatePanel);
    ballPanel.setBackground(Color.white);

    coordinatePanel.setBackground(Color.LIGHT_GRAY);
    nowXcoordinateLabel.setBackground(Color.WHITE);
    nowYcoordinateLabel.setBackground(Color.WHITE);
    coordinatePanel.add(nowXcoordinateLabel);
    coordinatePanel.add(nowYcoordinateLabel);
    setVisible(true);
    setSize(400,400);

    MouseMotionListener ml = new MouseMotionAdapter(){
   public void mouseDragged(MouseEvent e){
      Point p = new Point();
      nowX = (int) p.getX();
      nowY = (int) p.getY();
  }  
};
    addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
        dispose();
     }
    }
   );
  }
   public void paintComponent(Graphics2D gg){
   // super.paintComponents(gg);
    ballPanel.paintComponents(gg);
    gg.setColor(Color.BLUE);
    gg.fillOval(x0, y0, 10, 10);

}



public static void main(String[]arg){
    MovingBall mb = new MovingBall();
}
}

我有两个问题

  1. 我使用fillOvalpaintComponent来绘制并展示一个球,但我在屏幕上看不到。为什么?
  2. 如果我想使用mouseDragged移动球,请知道如何移动球?我需要一些线程吗?

3 个答案:

答案 0 :(得分:1)

让我们从

开始
  • Frame没有paintComponent方法,因此没有任何内容可以调用它。
  • 即使它确实如此,位置0x0会在框架的边框下绘制圆圈,所以你不会看到它
  • 您应该从Point获取MouseEvent,而不是从您创建的新Point对象获取
  • 管理鼠标拖动或绘画不是框架的责任,框架负责提供其他所有添加的初始容器

由此,您应该将绘画和鼠标拖动管理的功能移动到它自己的类。这为您提供了两件事,第一,您可以绘制的表面,以及框架边框中包含的表面,鼠标事件将自动转换为面板上下文(0x0将是左上角小组)

这提出了有关如何更新标签的问题。好吧,您可以从AWT API中获取一个叶子,并使用简单的观察者模式在更改坐标时生成事件,例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;

public class MovingBall extends Frame {

    BallPane ballPanel = new BallPane();
    Label ballLabel = new Label();
    int x0 = 0, y0 = 0, x = 20, y = 30;
    int nowX, nowY;
    Label nowXcoordinateLabel = new Label("Now X :" + nowX);
    Label nowYcoordinateLabel = new Label("Now Y :" + nowY);

    MovingBall() {
        setLayout(new BorderLayout());
        ballPanel.add(ballLabel);

        add(ballPanel);
        ballPanel.setBackground(Color.white);

        nowXcoordinateLabel.setBackground(Color.WHITE);
        nowYcoordinateLabel.setBackground(Color.WHITE);
        setVisible(true);
        setSize(400, 400);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                dispose();
            }
        });

        Panel coordinates = new Panel(new FlowLayout());
        coordinates.add(nowXcoordinateLabel);
        coordinates.add(nowYcoordinateLabel);
        coordinates.setBackground(Color.LIGHT_GRAY);
        add(coordinates, BorderLayout.SOUTH);

        ballPanel.addCoordinateListene(new CoordinateListener() {
            @Override
            public void coordinatesChanged(CoordinateEvent evt) {
                nowXcoordinateLabel.setText("Now X: " + evt.getCoordinate().getX());
                nowYcoordinateLabel.setText("Now X: " + evt.getCoordinate().getY());
                revalidate();
                repaint();
            }
        });

    }

    public static void main(String[] arg) {
        MovingBall mb = new MovingBall();
    }

    public class CoordinateEvent extends EventObject {
        private final Point p;

        public CoordinateEvent(Object source, Point p) {
            super(source);
            this.p = p;
        }

        public Point getCoordinate() {
            return p;
        }
    }

    public interface CoordinateListener {
        public void coordinatesChanged(CoordinateEvent evt);
    }

    public class BallPane extends Panel {

        int x0 = 0, y0 = 0, x = 20, y = 30;
        private List<CoordinateListener> coordinateListeners;

        public BallPane() {
            MouseMotionListener ml = new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent e) {
                    x0 = (int) e.getX();
                    y0 = (int) e.getY();
                    fireCoordinateChange(new Point(e.getPoint()));
                    repaint();
                }
            };
            addMouseMotionListener(ml);
            coordinateListeners = new ArrayList<>(5);
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(Color.BLUE);
            g.fillOval(x0, y0, 10, 10);
        }

        public void addCoordinateListene(CoordinateListener listener) {
            coordinateListeners.add(listener);
        }

        public void removeCoordinateListene(CoordinateListener listener) {
            coordinateListeners.remove(listener);
        }

        protected void fireCoordinateChange(Point p) {
            CoordinateEvent evt = new CoordinateEvent(this, p);
            for (CoordinateListener listener : coordinateListeners) {
                listener.coordinatesChanged(evt);
            }
        }

    }
}

答案 1 :(得分:1)

让您的课程延长Panel并准备好使用覆盖paint方法进行绘制,并添加MouseMotionListener以列出您的面板。获取X和Y坐标以便在{{1方法,最后将您的绘图面板添加到paint

简单代码:更新

Frame

答案 2 :(得分:0)

获取鼠标的位置而不是:

nowX = (int) p.getX();

写下这个:

nowX = (int) e.getX();

每次用户触发鼠标拖动事件时,您还需要重绘椭圆