0

我想创建一个可以使用鼠标在程序中移动图片的程序这是我的代码。我的代码是用 tempX 和 tempY 设置形状的位置,我将它设置为在拖动鼠标时获取鼠标位置,图片将沿鼠标移动。
* 我不能在拖动鼠标时重新绘制这张图片我错过了什么?* 添加 chagnePositionVectors()

public class SiaemsiMouse extends JPanel implements MouseListener,MouseMotionListener {

int tempX = 330;
int tempY = 95;

// position of Siaemsi box
int posX[] = {tempX-30,tempX-30,tempX-30};
int posY[] = {tempY+305,tempY+80,tempY+55};

// position of Siaemsi stick
int posXS1[] = {tempX,tempX,tempX-3,tempX+8,tempX+20,tempX+17};
int posXS2[] = {tempX+20,tempX+20,tempX+17,tempX+28,tempX+40,tempX+37};
int posXS3[] = {tempX+40,tempX+40,tempX+37,tempX+48,tempX+60,tempX+57};
int posXS4[] = {tempX+60,tempX+60,tempX+57,tempX+68,tempX+80,tempX+77};
int posXS5[] = {tempX+80,tempX+80,tempX+77,tempX+88,tempX+100,tempX+97};
int posXS6[] = {tempX+100,tempX+100,tempX+97,tempX+108,tempX+120,tempX+117};
int posXS7[] = {tempX+120,tempX+120,tempX+117,tempX+128,tempX+140,tempX+137};

// All of y for stick are equals
int posYS1[] = {tempY,tempY,tempY-10,tempY-15,tempY-10,tempY};

public SiaemsiMouse(){
    addMouseMotionListener(this);
    addMouseListener(this);
}

public static void main(String[] args) {
    SiaemsiMouse siaemsimouse = new SiaemsiMouse();
    JFrame frame = new JFrame();
    frame.add(siaemsimouse);
    frame.setSize(800,600);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void paintComponent(Graphics graphics){
    super.paintComponent(graphics);
    Graphics2D g2 = (Graphics2D) graphics;
    Random random = new Random();

    // Draw Siaemsi
    Ellipse2D.Double floor = new Ellipse2D.Double(posX[0],posY[0],200,50);
    Rectangle2D.Double body = new Rectangle2D.Double(posX[1],posY[1],200,250);
    Ellipse2D.Double top = new Ellipse2D.Double(posX[2],posY[2],200,50);
    g2.setPaint(Color.RED);
    g2.fill(floor);
    g2.fill(body);
    g2.setPaint(Color.BLACK);
    g2.fill(top);

    // Draw siaemsi's stick
    Rectangle2D.Double stick1 = new Rectangle2D.Double(posXS1[0],posYS1[0],18,100);
    GeneralPath path1 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS1.length);
    path1.moveTo(posXS1[1],posYS1[1]);
    for (int i = 2; i < posXS1.length; i++) {
        path1.lineTo(posXS1[i],posYS1[i]);
    }
    path1.closePath();

    Rectangle2D.Double stick2 = new Rectangle2D.Double(posXS2[0],posYS1[0],18,100);
    GeneralPath path2 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS2.length);
    path2.moveTo(posXS2[1],posYS1[1]);
    for (int i = 2; i < posXS2.length; i++) {
        path2.lineTo(posXS2[i],posYS1[i]);
    }
    path2.closePath();

    Rectangle2D.Double stick3 = new Rectangle2D.Double(posXS3[0],posYS1[0],18,100);
    GeneralPath path3 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS3.length);
    path3.moveTo(posXS3[1],posYS1[1]);
    for (int i = 2; i < posXS3.length; i++) {
        path3.lineTo(posXS3[i],posYS1[i]);
    }
    path3.closePath();

    Rectangle2D.Double stick4 = new Rectangle2D.Double(posXS4[0],posYS1[0],18,100);
    GeneralPath path4 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS4.length);
    path4.moveTo(posXS4[1],posYS1[1]);
    for (int i = 2; i < posXS4.length; i++) {
        path4.lineTo(posXS4[i],posYS1[i]);
    }
    path4.closePath();

    Rectangle2D.Double stick5 = new Rectangle2D.Double(posXS5[0],posYS1[0],18,100);
    GeneralPath path5 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS5.length);
    path5.moveTo(posXS5[1],posYS1[1]);
    for (int i = 2; i < posXS5.length; i++) {
        path5.lineTo(posXS5[i],posYS1[i]);
    }
    path5.closePath();

    Rectangle2D.Double stick6 = new Rectangle2D.Double(posXS6[0],posYS1[0],18,100);
    GeneralPath path6 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS6.length);
    path6.moveTo(posXS6[1],posYS1[1]);
    for (int i = 2; i < posXS6.length; i++) {
        path6.lineTo(posXS6[i],posYS1[i]);
    }
    path6.closePath();

    Rectangle2D.Double stick7 = new Rectangle2D.Double(posXS7[0],posYS1[0],18,100);
    GeneralPath path7 = new GeneralPath(GeneralPath.WIND_EVEN_ODD,posXS7.length);
    path7.moveTo(posXS7[1],posYS1[1]);
    for (int i = 2; i < posXS7.length; i++) {
        path7.lineTo(posXS7[i],posYS1[i]);
    }
    path7.closePath();

    g2.setPaint(new Color(153,153,0));
    g2.fill(stick1);
    g2.fill(path1);
    g2.setPaint(Color.BLACK);
    g2.draw(stick1);
    g2.draw(path1);
    g2.setPaint(new Color(153, 76, 0));
    g2.fill(stick2);
    g2.fill(path2);
    g2.setPaint(Color.BLACK);
    g2.draw(stick2);
    g2.draw(path2);
    g2.setPaint(new Color(255, 255, 0));
    g2.fill(stick3);
    g2.fill(path3);
    g2.setPaint(Color.BLACK);
    g2.draw(stick3);
    g2.draw(path3);
    g2.setPaint(new Color(0, 255, 128));
    g2.fill(stick4);
    g2.fill(path4);
    g2.setPaint(Color.BLACK);
    g2.draw(stick4);
    g2.draw(path4);
    g2.setPaint(new Color(102, 0, 56));
    g2.fill(stick5);
    g2.fill(path5);
    g2.setPaint(Color.BLACK);
    g2.draw(stick5);
    g2.draw(path5);
    g2.setPaint(new Color(255, 0, 127));
    g2.fill(stick6);
    g2.fill(path6);
    g2.setPaint(Color.BLACK);
    g2.draw(stick6);
    g2.draw(path6);
    g2.setPaint(new Color(224, 224, 56));
    g2.fill(stick7);
    g2.fill(path7);
    g2.setPaint(Color.BLACK);
    g2.draw(stick7);
    g2.draw(path7);

}

@Override
public void mouseClicked(MouseEvent e) {

}

@Override
public void mousePressed(MouseEvent e) {

}

@Override
public void mouseReleased(MouseEvent e) {

}

@Override
public void mouseEntered(MouseEvent e) {

}

@Override
public void mouseExited(MouseEvent e) {

}

@Override
public void mouseDragged(MouseEvent e) {
    changePositionVectors(e.getX(),e.getY());
}

@Override
public void mouseMoved(MouseEvent e) {

}
public void changePositionVectors(int xPos, int yPos){
    tempX = xPos;
    tempY = yPos;
    repaint();
}
}
4

2 回答 2

2

试试这个,这里根据@HovercraftFullOfEels 的评论,我已经从paintComponent()...

编辑 1:
添加了地板、身体和顶部物体。在 O/P 屏幕上引发空指针异常但有效

编辑2:
仍然显示NPE,固定:图像(蛋糕)没有移动,因为posX,posY,......数组没有更新

class SiaemsiMouse extends JPanel implements MouseListener, MouseMotionListener {

    private int tempX = 330;
    private int tempY = 95;
    // position of Siaemsi box
    private int posX[] = {tempX - 30, tempX - 30, tempX - 30};
    private int posY[] = {tempY + 305, tempY + 80, tempY + 55};
    // position of Siaemsi stick
    private int posXS1[] = {tempX, tempX, tempX - 3, tempX + 8, tempX + 20, tempX + 17};
    private int posXS2[] = {tempX + 20, tempX + 20, tempX + 17, tempX + 28, tempX + 40, tempX + 37};
    private int posXS3[] = {tempX + 40, tempX + 40, tempX + 37, tempX + 48, tempX + 60, tempX + 57};
    private int posXS4[] = {tempX + 60, tempX + 60, tempX + 57, tempX + 68, tempX + 80, tempX + 77};
    private int posXS5[] = {tempX + 80, tempX + 80, tempX + 77, tempX + 88, tempX + 100, tempX + 97};
    private int posXS6[] = {tempX + 100, tempX + 100, tempX + 97, tempX + 108, tempX + 120, tempX + 117};
    private int posXS7[] = {tempX + 120, tempX + 120, tempX + 117, tempX + 128, tempX + 140, tempX + 137};
    // All of y for stick are equals
    private int posYS1[] = {tempY, tempY, tempY - 10, tempY - 15, tempY - 10, tempY};

    public SiaemsiMouse() {
        addMouseMotionListener(this);
        addMouseListener(this);
    }

    public static void main(String[] args) throws InterruptedException {
        SiaemsiMouse siaemsimouse = new SiaemsiMouse();
        JFrame frame = new JFrame();
        frame.add(siaemsimouse);
        frame.setSize(800, 600);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    //added objects here
    private Rectangle2D.Double stick1, stick2, stick3, stick4, stick5, stick6, stick7;
    private GeneralPath path1, path2, path3, path4, path5, path6, path7;
    //added more objects 
    private Ellipse2D.Double floor;
    private Rectangle2D.Double body;
    private Ellipse2D.Double top;

    @Override
    public void paintComponent(Graphics graphics) {
        Graphics2D g2 = (Graphics2D) graphics;
        super.paintComponent(graphics);     //If you use paintComponents() the previous image persists
        //Random random = new Random(); //No use for Random??

        // Draw Siaemsi
        g2.setPaint(Color.RED);
        g2.fill(floor);
        g2.fill(body);
        g2.setPaint(Color.BLACK);
        g2.fill(top);

        g2.setPaint(new Color(153, 153, 0));
        g2.fill(stick1);
        g2.fill(path1);
        g2.setPaint(Color.BLACK);
        g2.draw(stick1);
        g2.draw(path1);
        g2.setPaint(new Color(153, 76, 0));
        g2.fill(stick2);
        g2.fill(path2);
        g2.setPaint(Color.BLACK);
        g2.draw(stick2);
        g2.draw(path2);
        g2.setPaint(new Color(255, 255, 0));
        g2.fill(stick3);
        g2.fill(path3);
        g2.setPaint(Color.BLACK);
        g2.draw(stick3);
        g2.draw(path3);
        g2.setPaint(new Color(0, 255, 128));
        g2.fill(stick4);
        g2.fill(path4);
        g2.setPaint(Color.BLACK);
        g2.draw(stick4);
        g2.draw(path4);
        g2.setPaint(new Color(102, 0, 56));
        g2.fill(stick5);
        g2.fill(path5);
        g2.setPaint(Color.BLACK);
        g2.draw(stick5);
        g2.draw(path5);
        g2.setPaint(new Color(255, 0, 127));
        g2.fill(stick6);
        g2.fill(path6);
        g2.setPaint(Color.BLACK);
        g2.draw(stick6);
        g2.draw(path6);
        g2.setPaint(new Color(224, 224, 56));
        g2.fill(stick7);
        g2.fill(path7);
        g2.setPaint(Color.BLACK);
        g2.draw(stick7);
        g2.draw(path7);         
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        changePositionVectors(e.getX(), e.getY());
    }

    @Override
    public void mouseMoved(MouseEvent e) {
    }

    @SuppressWarnings("empty-statement")
    public void changePositionVectors(int xPos, int yPos) {
        tempX = xPos;
        tempY = yPos;

        //calc pos...        
        posX = new int[]{tempX - 30, tempX - 30, tempX - 30};
        posY = new int[]{tempY + 305, tempY + 80, tempY + 55};
        // position of Siaemsi stick
        posXS1 = new int[]{tempX, tempX, tempX - 3, tempX + 8, tempX + 20, tempX + 17};
        posXS2 = new int[]{tempX + 20, tempX + 20, tempX + 17, tempX + 28, tempX + 40, tempX + 37};
        posXS3 = new int[]{tempX + 40, tempX + 40, tempX + 37, tempX + 48, tempX + 60, tempX + 57};
        posXS4 = new int[]{tempX + 60, tempX + 60, tempX + 57, tempX + 68, tempX + 80, tempX + 77};
        posXS5 = new int[]{tempX + 80, tempX + 80, tempX + 77, tempX + 88, tempX + 100, tempX + 97};
        posXS6 = new int[]{tempX + 100, tempX + 100, tempX + 97, tempX + 108, tempX + 120, tempX + 117};
        posXS7 = new int[]{tempX + 120, tempX + 120, tempX + 117, tempX + 128, tempX + 140, tempX + 137};
        // All of y for stick are equals
        posYS1 = new int[]{tempY, tempY, tempY - 10, tempY - 15, tempY - 10, tempY};

        floor = new Ellipse2D.Double(posX[0], posY[0], 200, 50);
        body = new Rectangle2D.Double(posX[1], posY[1], 200, 250);
        top = new Ellipse2D.Double(posX[2], posY[2], 200, 50);

        // Draw siaemsi's stick
        stick1 = new Rectangle2D.Double(posXS1[0], posYS1[0], 18, 100);
        path1 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS1.length);
        path1.moveTo(posXS1[1], posYS1[1]);
        for (int i = 2; i < posXS1.length; i++) {
            path1.lineTo(posXS1[i], posYS1[i]);
        }
        path1.closePath();

        stick2 = new Rectangle2D.Double(posXS2[0], posYS1[0], 18, 100);
        path2 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS2.length);
        path2.moveTo(posXS2[1], posYS1[1]);
        for (int i = 2; i < posXS2.length; i++) {
            path2.lineTo(posXS2[i], posYS1[i]);
        }
        path2.closePath();

        stick3 = new Rectangle2D.Double(posXS3[0], posYS1[0], 18, 100);
        path3 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS3.length);
        path3.moveTo(posXS3[1], posYS1[1]);
        for (int i = 2; i < posXS3.length; i++) {
            path3.lineTo(posXS3[i], posYS1[i]);
        }
        path3.closePath();

        stick4 = new Rectangle2D.Double(posXS4[0], posYS1[0], 18, 100);
        path4 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS4.length);
        path4.moveTo(posXS4[1], posYS1[1]);
        for (int i = 2; i < posXS4.length; i++) {
            path4.lineTo(posXS4[i], posYS1[i]);
        }
        path4.closePath();

        stick5 = new Rectangle2D.Double(posXS5[0], posYS1[0], 18, 100);
        path5 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS5.length);
        path5.moveTo(posXS5[1], posYS1[1]);
        for (int i = 2; i < posXS5.length; i++) {
            path5.lineTo(posXS5[i], posYS1[i]);
        }
        path5.closePath();

        stick6 = new Rectangle2D.Double(posXS6[0], posYS1[0], 18, 100);
        path6 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS6.length);
        path6.moveTo(posXS6[1], posYS1[1]);
        for (int i = 2; i < posXS6.length; i++) {
            path6.lineTo(posXS6[i], posYS1[i]);
        }
        path6.closePath();

        stick7 = new Rectangle2D.Double(posXS7[0], posYS1[0], 18, 100);
        path7 = new GeneralPath(GeneralPath.WIND_EVEN_ODD, posXS7.length);
        path7.moveTo(posXS7[1], posYS1[1]);
        for (int i = 2; i < posXS7.length; i++) {
            path7.lineTo(posXS7[i], posYS1[i]);
        }
        path7.closePath();

        repaint();
    }
}
于 2013-08-13T15:08:34.497 回答
2

我明白我认为是你的问题。

  • 您假设如果您更改 tempX 和 tempY,那么从它们派生的所有变量也会发生变化,
  • 但事实并非如此。使用 tempX 或 tempY 创建的任何变量在创建后都不会神奇地知道要更改。
  • 您需要更改任何需要自己更改的变量,最简单的方法是创建一个方法,该方法采用您的 tempX 和 tempY 值并重新计算所有其他需要重新计算的字段。
  • 考虑在paintComponent之外创建和移动Shape 和path 对象,可能在鼠标适配器代码中,并在paintComponent 中简单地绘制Shape。

IE,

public void changePositionVectors(int xPos, int yPos) {
  // set the fields that need to be set with x and y
  repaint();
}

编辑
关于您的新代码:

public void changePositionVectors(int xPos, int yPos){
    tempX = xPos;
    tempY = yPos;
    repaint();
}

这没有解决任何问题,因为所有这些都是 set 的 tempX 和 tempY,并且再次更改这些值不会神奇地更改最初使用这些字段创建的任何值。同样,您的 changePositionVectors 方法必须包含更多代码,这些代码实际上设置了绘制 GUI 所需的所有向量的值。


编辑我会采取与你和装箱的做法完全不同的方法。我会:

  • 将所有内容绘制到 BufferedImage
  • 将该 BufferedImage 放入 ImageIcon
  • 将该 ImageIcon 放入 JLabel
  • 将该 JLabel 放入 JLayeredPane
  • 将 MouseListener 和 MouseMotionListener 添加到 JLabel。
  • 完毕。

例如:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleDrawing {
   private static final int PREF_W = 780;
   private static final int PREF_H = 570;
   private static final int GAP = 1;
   private static final int BI_WIDTH = 200 + 2 * GAP;
   private static final int BI_HEIGHT = 300 + 2 * GAP;
   private static final int ELLIPSE_WIDTH = BI_WIDTH - 2 * GAP;
   private static final int ELLIPSE_HEIGHT = 50;
   private static final Color CAN_COLOR = Color.red;
   private JLayeredPane layeredPane = new JLayeredPane() {
      public Dimension getPreferredSize() {
         return SimpleDrawing.this.getPreferredSize();
      };
   };
   private JLabel imageLabel;
   private Point imageLabelPoint = new Point();

   public SimpleDrawing() {
      layeredPane.setOpaque(true);
      layeredPane.setBackground(Color.white);

      imageLabel = drawImageLabel();
      imageLabel.setLocation(imageLabelPoint);
      imageLabel.setSize(imageLabel.getPreferredSize());

      layeredPane.add(imageLabel, JLayeredPane.DEFAULT_LAYER);

      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      imageLabel.addMouseListener(myMouseAdapter);
      imageLabel.addMouseMotionListener(myMouseAdapter);
   }

   private JLabel drawImageLabel() {
      BufferedImage img = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(CAN_COLOR);
      int x = GAP;
      int y = BI_HEIGHT - ELLIPSE_HEIGHT - GAP;
      int width = ELLIPSE_WIDTH;
      int height = ELLIPSE_HEIGHT;
      g2.fillOval(x, y, width, height);

      y = GAP + ELLIPSE_HEIGHT / 2;
      width = ELLIPSE_WIDTH;
      height = BI_HEIGHT - ELLIPSE_HEIGHT / 2 - GAP - y;
      g2.fillRect(x, y, width, height);

      g2.setColor(Color.black);
      y = GAP;
      height = ELLIPSE_HEIGHT;
      g2.fillOval(x, y, width, height);

      g2.dispose();
      ImageIcon icon = new ImageIcon(img);      
      return new JLabel(icon);      
   }

   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public JLayeredPane getLayeredPane() {
      return layeredPane;
   }

   private class MyMouseAdapter extends MouseAdapter {
      private boolean dragging = false;
      private Point srcLoc;
      private Point msePressLoc;

      @Override
      public void mousePressed(MouseEvent e) {
         if (e.getButton() != MouseEvent.BUTTON1) {
            return;
         }

         dragging = true;
         srcLoc = ((Component) e.getSource()).getLocation();
         msePressLoc = e.getLocationOnScreen();
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         if (e.getButton() != MouseEvent.BUTTON1) {
            return;
         }

         dragging = false;
         moveTo(e);
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         if (!dragging) {
            return;
         }
         moveTo(e);
      }

      private void moveTo(MouseEvent e) {
         Point loc = e.getLocationOnScreen();
         Component comp = (Component) e.getSource();
         int x = loc.x - msePressLoc.x + srcLoc.x;
         int y = loc.y - msePressLoc.y + srcLoc.y;
         comp.setLocation(x, y);
         layeredPane.repaint();
      }
   }

   private static void createAndShowGui() {
      SimpleDrawing simpleDrawing = new SimpleDrawing();

      JFrame frame = new JFrame("Simple Drawing");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(simpleDrawing.getLayeredPane());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
于 2013-08-13T13:37:05.107 回答