使用鼠标移动图像的Java实现

3

好的,我相对Java比较陌生,现在在完成一个分配给我的项目时遇到了问题。我无法将我的CTetrimino对象移动到JFrame上。这是我的CTetrimino类:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

public class CTetriMino {

public CTetriMino(int type, int x, int y, int w, int h, Color c) 
{
    CMino m = new CMino();
    d = m.getDiameter();
    Type=type;
    X=x;
    Y=y;
    Width=w;
    Height=h;
    FillColor=c;
}

public CTetriMino(CTetriMino src) { // copy constructor
    Type=src.Type;
    X=src.X;
    Y=src.Y;
    Width=src.Width;
    Height=src.Height;
    FillColor=src.FillColor;
}

public int getX() { return X; }
public void setX(int x) { X=x; }
public int getY() { return Y; }
public void setY(int y) { Y=y; }

public void draw(Graphics g) {
    g.setColor(FillColor);
    switch (Type) {
    case 0:
        //g.fillOval(X, Y, Width, Height);
        //break;
        g.fillOval(X, Y, d, d);
        g.fillOval(X+d,Y, d, d);
        g.fillOval(X+d,Y-d, d, d);
        g.fillOval(X+d+d,Y-d, d, d);
        break;
    case 1:
        g.fillRect(X, Y, Width, Height);
        //g.fillOval(X, Y, d, d);
        //g.fillOval(X+d,Y, d, d);
        //g.fillOval(X+d,Y+d, d, d);
        //g.fillOval(X+d+d,Y+d, d, d);
        break;
    case 2:
        g.fillOval(X, Y, d, d);
        g.fillOval(X+d,Y, d, d);
        g.fillOval(X,Y-d, d, d);
        g.fillOval(X+d,Y-d, d, d);
        break;
    case 3:
        g.fillOval(X, Y, d, d);
        g.fillOval(X,Y+d, d, d);
        g.fillOval(X,Y+d+d, d, d);
        g.fillOval(X,Y-d, d, d);
        break;
    case 4:
        g.fillOval(X, Y, d, d);
        g.fillOval(X,Y+d, d, d);
        g.fillOval(X,Y-d, d, d);
        g.fillOval(X+d,Y-d, d, d);
        break;
    case 5:
        g.fillOval(X, Y, d, d);
        g.fillOval(X,Y+d, d, d);
        g.fillOval(X,Y-d, d, d);
        g.fillOval(X-d,Y-d, d, d);
        break;
    case 6:
        g.fillOval(X, Y, d, d);
        g.fillOval(X+d,Y, d, d);
        g.fillOval(X,Y-d, d, d);
        g.fillOval(X-d,Y, d, d);
        break;
        }
    }

public boolean containPoint(int x, int y) {
        switch (Type) {
        case 0:
            {
                double a=Width/2.0;
                double b=Height/2.0;
                double xc=X+a;
                double yc=Y+b;
                System.out.println(a);
                System.out.println(b);
                System.out.println(xc);
                System.out.println(yc);
                System.out.println(((x-xc)*(x-xc)/(a*a)+(y-yc)*(y-yc)/(b*b)<=1.0));
                return ((x-xc)*(x-xc)/(a*a)+(y-yc)*(y-yc)/(b*b)<=1.0);

            }
        case 1:
            return (x>=X && y>=Y && x<X+Width && y<Y+Height);

        }

        return false;
    }





private int Type;   
private int X;
private int Y;
private int Width;
private int Height;
private Color FillColor;
private int d;
}

这是我的面板类,我将其添加到TestNewTetris类中的Jframe中。

import java.awt.Color;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.*;

import java.util.*;



public class Panel extends JPanel 
implements MouseListener, MouseMotionListener
{


private ArrayList<CTetriMino> originals;  
private ArrayList<CTetriMino> duplicates;

private CTetriMino BlockToBeMoved;
private int m_nOffsetX; // difference between cursor and top-left corner
private int m_nOffsetY;

// double buffering
private Image backBuffer;
private Graphics gBackBuffer;

boolean isInitialized;

// init and register mouse event handler
public Panel()
{
    isInitialized=false;
    // handle mouse and mouse motion events
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
}

// Set up the initial state after the panel is created
void init()
{
    // Initial state
    duplicates = new ArrayList<CTetriMino>();
    originals = new ArrayList<CTetriMino>();
    Color[] colors = {Color.red, Color.green, Color.blue, Color.magenta, Color.cyan, Color.yellow, Color.orange};
    int count=colors.length;
    int dx=10;
    int dy=30;
    int gap=20;
    int length=(getSize().height-2*dy-(count-1)*gap)/count;
    for (int i=0; i<count; i++) { 
        //originals.add(new CTetriMino((i<count/2)?0:1, dx, dy+i*(length+gap), length, length, colors[i]));
        System.out.println(length);
        originals.add(new CTetriMino(i, dx, dy, length, length, colors[i])); 
        dx = dx+110;

    }
    BlockToBeMoved=null; // no shape selected

    // create the back buffer
    backBuffer = createImage(getSize().width, getSize().height);
    gBackBuffer = backBuffer.getGraphics();
}

// State Presentation
public void paintComponent( Graphics g )
{
    // super.paintComponent( g ); // clears drawing area

    if (!isInitialized) {
        isInitialized=true;
        init();
    }
    // State Presentation, using double buffers
    // First, clear the back buffer
    gBackBuffer.setColor(Color.white);
    gBackBuffer.clearRect(0, 0, getSize().width, getSize().height);
    // draw the originals to back buffer
    for (int i=0; i<originals.size(); i++) {
        originals.get(i).draw(gBackBuffer);
    }
    // draw the duplicates to back buffer
    for (int i=0; i<duplicates.size(); i++) {
        duplicates.get(i).draw(gBackBuffer);
    }
    // copy from back buffer to front
    g.drawImage(backBuffer, 0, 0, null);
    g.fillRect(0, 100, 800, 4);
    g.fillRect(0, 400, 800, 4);
} // end method paintComponent

// MouseListener event handlers
public void mouseClicked( MouseEvent e )
{
    if (e.isMetaDown()) {   // right button
        for (int i=duplicates.size()-1; i>=0; i--) {
            if (duplicates.get(i).containPoint(e.getX(), e.getY())) {
                duplicates.remove(i);
                repaint();
                break;
            }
        }
    }
}

public void mousePressed( MouseEvent e )
{
    if (e.isMetaDown()) return; // ignore right button

    // First, check the originals, from top down (i.e. back to front)
    for (int i=duplicates.size()-1; i>=0; i--) {
        CTetriMino p=duplicates.get(i);
        if (p.containPoint(e.getX(), e.getY())) {
            duplicates.remove(i);
            duplicates.add(p);  // move to the end, i.e. the top
            BlockToBeMoved=p;
            m_nOffsetX=e.getX()-BlockToBeMoved.getX();
            m_nOffsetY=e.getY()-BlockToBeMoved.getY();
            repaint();
            return;
        }
    }
    // Second, check the orginals 
    for (int i=originals.size()-1; i>=0; i--) {
        CTetriMino p=originals.get(i);
        System.out.println(p.containPoint(e.getX(), e.getY()));
        if (p.containPoint(e.getX(), e.getY())) {
            CTetriMino p2=new CTetriMino(p); // make a copy of p
            duplicates.add(p2); // add to the end
            BlockToBeMoved=p2;  // p2 is selected, to be moved
            m_nOffsetX=e.getX()-BlockToBeMoved.getX();
            m_nOffsetY=e.getY()-BlockToBeMoved.getY();
            repaint();
            return;
        }
    }
}

public void mouseReleased( MouseEvent e )
{
    BlockToBeMoved=null; // no shape selected
}

public void mouseEntered( MouseEvent e )
{
}

public void mouseExited( MouseEvent e )
{
}

public void mouseMoved( MouseEvent e )
{
}

public void mouseDragged( MouseEvent e )
{
    if (e.isMetaDown()) return; // ignore right button
    System.out.println(BlockToBeMoved);
    if (BlockToBeMoved!=null) {
        BlockToBeMoved.setX(e.getX()-m_nOffsetX);
        BlockToBeMoved.setY(e.getY()-m_nOffsetY);
        repaint();
    }

} // end method mouseDragged






}

我想展示一下我的程序在运行时的效果,但由于我的声望还不够高,所以无法展示。

如果我更改了这段代码,下方的Jframe将会被编译:

case 0:
g.fillOval(X, Y, d, d);
g.fillOval(X+d,Y, d, d);
g.fillOval(X+d,Y-d, d, d);
g.fillOval(X+d+d,Y-d, d, d);
break;

转换为:

case 0:
g.fillOval(X, Y, Width, Height);
break;

在这两个变体中,我可以拖动绿色正方形。在第二个变体中,我能够拖动红色圆圈。但是,我无法移动我的红色俄罗斯方块。我只是想知道为什么我不能移动我的红色俄罗斯方块。最终,我希望能够移动所有的俄罗斯方块并将它们拖到第二条黑线下以删除它们。我还希望能够通过按右键旋转俄罗斯方块。非常感谢任何代码或建议。如果您需要更多信息,我会尽快提供。谢谢。

2
这个网站上有很多使用Swing允许鼠标拖动图形的例子,其中一些是由我和MadProgrammer等人编写的。你需要搜索这个网站并学习这些例子。 - Hovercraft Full Of Eels
谢谢!我会看一看它们。 - coolbiscuit
@HovercraftFullOfEels 我看了很多例子,仍然有困难。我能够移动一个圆,但不能移动4个小圆的组合。如果您可以再次查看我的代码,我将不胜感激。 - coolbiscuit
2
我已经尝试查看您的代码,但遇到了一些障碍。1)它的格式很差,很难阅读。我们是志愿者,在自己的空闲时间里付出努力,如果您在提问时也付出努力使其易于理解,包括发布格式良好且符合通用Java格式标准的代码(您可以通过Google轻松找到),我们将非常感激。2)我无法运行您的代码,因为它不是完全自包含的,也不是MCVE -- 请查看链接。 - Hovercraft Full Of Eels
2
我完全理解。虽然您没有回答我的问题,但您给了我很大的帮助。下次我会尽量让我的问题更容易理解。 - coolbiscuit
1
在StackOverflow中,你的学习成果得到了+1的认可 - 欢迎加入我们! - Martin Frank
1个回答

3
如果我理解得正确,以下是解决方案: 请按照下面的方式创建图像包。您需要为标签鼠标拖动和标签鼠标按下两个事件进行设置。将图标添加到标签中,它应该是您的图片。
关键进口内容:
    import java.awt.Point;

事件

   private void jLabel1MousePressed(java.awt.event.MouseEvent evt) {                                     
          initialClick = evt.getPoint();
    }  





     private void jLabel1MouseDragged(java.awt.event.MouseEvent evt) {                                     

        int thisX = jLabel1.getLocation().x;
        int thisY = jLabel1.getLocation().y;

        // Determine how much the mouse moved since the initial click
        int xMoved = (thisX + evt.getX()) - (thisX + initialClick.x);
        int yMoved = (thisY + evt.getY()) - (thisY + initialClick.y);

        // Move picture to this position
        int X = thisX + xMoved;
        int Y = thisY + yMoved;

        jLabel1.setLocation(X, Y);
        jLabel1.repaint();


    }                                    

+1 个赞给漂亮的回答。我在我的绘画应用程序中使用了这种方法,但是我遇到了一些小问题。在使用鼠标定位图像后,我想要获取可绘制区域(可移动图片+空白区域)的屏幕截图。通过 Robot() 进行屏幕截图后,标签不会出现在照片(屏幕截图)中,只有空隙出现。你有任何关于此的想法吗?非常感谢。 - Coder ACJHP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接