调整jpanel中的2个矩形

时间:2014-01-04 16:11:57

标签: java swing jframe jpanel

我无法调整两个矩形的大小,但只能调整右边的矩形。我应该在代码中添加什么? 我还希望当移动左边矩形的下边缘时,它也会移动右边矩形的上边缘。

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

public class Resizing extends JPanel {

Rectangle rect = new Rectangle(100,100,150,150);
Rectangle rect2 = new Rectangle(300,100,150,150);

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(new Color(0, 0, 200));
    g2.fill(rect);
    g2.setColor(new Color(0, 0, 200));
    g2.fill(rect2);
}

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Resizing essai = new Resizing();
    Resizer1 rectangle = new Resizer1(essai);
    essai.addMouseListener(rectangle);
    essai.addMouseMotionListener(rectangle);
    f.add(essai);

    Resizing test2 = new Resizing();
    Resizer2 rectangle2 = new Resizer2(test2);
    test2.addMouseListener(rectangle2);
    test2.addMouseMotionListener(rectangle2);
    f.add(test2);

    f.setSize(600,400);
    f.setLocation(100,100);
    f.setVisible(true);
}
}

class Resizer1 extends MouseAdapter {

Resizing component;
boolean dragging = false;
// Give user some leeway for selections.
final int PROX_DIST = 3;

public Resizer1(Resizing r) {
    component = r;
}
@Override
public void mousePressed(MouseEvent e) {
    if(component.getCursor() != Cursor.getDefaultCursor()) {
        // If cursor is set for resizing, allow dragging.
        dragging = true;
    }
}
@Override
public void mouseReleased(MouseEvent e) {
    dragging = false;
}
@Override
public void mouseDragged(MouseEvent e) {
    if(dragging){
        Point p = e.getPoint();
        Rectangle r = component.rect;
        int type = component.getCursor().getType();
        int dy = p.y - r.y;
        switch(type) {
            case Cursor.N_RESIZE_CURSOR:
                int height = r.height - dy;
                r.setRect(r.x, r.y+dy, r.width, height);
                break;
            case Cursor.S_RESIZE_CURSOR:
                height = dy;
                r.setRect(r.x, r.y, r.width, height);
                break;
            default:
                System.out.println("unexpected type: " + type);
        }
        component.repaint();
    }
}
@Override
public void mouseMoved(MouseEvent e) {
    Point p = e.getPoint();
    if(!isOverRect(p)) {
        if(component.getCursor() != Cursor.getDefaultCursor()) {
            // If cursor is not over rect reset it to the default.
            component.setCursor(Cursor.getDefaultCursor());
        }
        return;
    }
    // Locate cursor relative to center of rect.
    int outcode = getOutcode(p);
    Rectangle r = component.rect;
    switch(outcode) {
        case Rectangle.OUT_TOP:
            if(Math.abs(p.y - r.y) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.N_RESIZE_CURSOR));
            }
            break;
        case Rectangle.OUT_BOTTOM:
            if(Math.abs(p.y - (r.y+r.height)) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.S_RESIZE_CURSOR));
            }
            break;
        default:    // center
            component.setCursor(Cursor.getDefaultCursor());
    }
}

/**
 * Make a smaller Rectangle and use it to locate the
 * cursor relative to the Rectangle center.
 */
private int getOutcode(Point p) {
    Rectangle r = (Rectangle)component.rect.clone();
    r.grow(-PROX_DIST, -PROX_DIST);
    return r.outcode(p.x, p.y);
}

/**
 * Make a larger Rectangle and check to see if the
 * cursor is over it.
 */
private boolean isOverRect(Point p) {
    Rectangle r = (Rectangle)component.rect.clone();
    r.grow(PROX_DIST, PROX_DIST);
    return r.contains(p);
}
}

class Resizer2 extends MouseAdapter {

Resizing component;
boolean dragging = false;
// Give user some leeway for selections.
final int PROX_DIST = 3;

public Resizer2(Resizing r) {
    component = r;
}
@Override
public void mousePressed(MouseEvent e2) {
    if(component.getCursor() != Cursor.getDefaultCursor()) {
        // If cursor is set for resizing, allow dragging.
        dragging = true;
    }
}
@Override
public void mouseReleased(MouseEvent e2) {
    dragging = false;
}
@Override
public void mouseDragged(MouseEvent e2) {
    if(dragging){
        Point p = e2.getPoint();
        Rectangle r = component.rect2;
        int type = component.getCursor().getType();
        int dy = p.y - r.y;
        switch(type) {
            case Cursor.N_RESIZE_CURSOR:
                int height = r.height - dy;
                r.setRect(r.x, r.y+dy, r.width, height);
                break;
            case Cursor.S_RESIZE_CURSOR:
                height = dy;
                r.setRect(r.x, r.y, r.width, height);
                break;
            default:
                System.out.println("unexpected type: " + type);
        }
        component.repaint();
    }
}

@Override
public void mouseMoved(MouseEvent e2) {
    Point p = e2.getPoint();
    if(!isOverRect(p)) {
        if(component.getCursor() != Cursor.getDefaultCursor()) {
            // If cursor is not over rect reset it to the default.
            component.setCursor(Cursor.getDefaultCursor());
        }
        return;
    }
    // Locate cursor relative to center of rect.
    int outcode = getOutcode(p);
    Rectangle r = component.rect2;
    switch(outcode) {
        case Rectangle.OUT_TOP:
            if(Math.abs(p.y - r.y) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.N_RESIZE_CURSOR));
            }
            break;
        case Rectangle.OUT_BOTTOM:
            if(Math.abs(p.y - (r.y+r.height)) < PROX_DIST) {
                component.setCursor(Cursor.getPredefinedCursor(
                                    Cursor.S_RESIZE_CURSOR));
            }
            break;
        default:    // center
            component.setCursor(Cursor.getDefaultCursor());
    }
}

/**
 * Make a smaller Rectangle and use it to locate the
 * cursor relative to the Rectangle center.
 */
private int getOutcode(Point p) {
    Rectangle r = (Rectangle)component.rect2.clone();
    r.grow(-PROX_DIST, -PROX_DIST);
    return r.outcode(p.x, p.y);
}

/**
 * Make a larger Rectangle and check to see if the
 * cursor is over it.
 */
private boolean isOverRect(Point p) {
    Rectangle r = (Rectangle)component.rect2.clone();
    r.grow(PROX_DIST, PROX_DIST);
    return r.contains(p);
}
}

1 个答案:

答案 0 :(得分:2)

我在检查您的代码时看到的问题:

  • 您正在向JFrame添加2个JPanel,但只有一个会显示,因为它们是以默认方式添加到BorderLayout使用容器中。 编辑:我现在看到你为什么要这样做,但正如下面所解释的,你不应该这样做。仅创建一个Resizing对象并将其添加到JFrame一次。 Resizing将显示两个矩形,并且应编码单个MouseAdapter以允许您与两个矩形进行交互。
  • 您不是将Rectangle字段设为私有,而是允许外部类(即Resizer1)直接访问和缩小字段。你最好使用公共方法,允许其他类有选择地查询你的类的状态或改变你的类的状态。
  • 不要使用两个Resizer类,Resizer1和Resizer2,这就是你向JFrame添加两个Resizing对象,这实际上是你遇到问题的主要原因。相反,只使用一个Resizer类,并将其用作添加到单个Resizing对象的单个MouseAdapter。然后在这个单一类中,允许更改两个矩形。

如果您有任何问题,请发表评论。


你问:

  

谢谢,但是如何允许更改两个矩形?在Resizer类中,只有一个组件(r)?

只有一个组件,但它包含 两个 矩形,它知道两个矩形之间的区别,因为它有两个矩形变量。


编辑2
考虑:

  • 编辑原始问题并将新代码添加到底部,删除多余的新问题。
  • 创建一个非GUI对象,比如名为MyRectangle,它包含一个Rectangle对象。
  • 这个新类可以有一些方法允许你传入一个Point或x和y位置,并返回信息让调用代码知道鼠标是否在顶部或底部边缘(你的代码已经这样做了,所以这对你来说应该没问题。)
  • 这个新类将有mutator(setter)方法,允许外部类设置其矩形y位置和高度。
  • 新类将有一个fill方法,它接受Graphics2D参数并使用它来填充它所拥有的Rectangle。
  • 然后给你的Resizer类一个List<MyRectangle>,实际上是它们的一个ArrayList,比如名为myRectangleList,你可以添加两个MyRectangle对象
  • 然后为Resizer提供一个返回列表的getMyRectangleList方法。
  • 然后在MouseAdapter中,遍历List以查看鼠标是否在边缘
  • 等...

如,

class MyRectangle {
   private Rectangle rect;
   private String name;

   public MyRectangle(int x, int y, int width, int height, String name) {
      rect = new Rectangle(x, y, width, height);
      this.name = name;
   }

   public void fill(Graphics2D g2) {
      g2.fill(rect);
   }

   public int getOutcode(Point p) {
      // return ... do what you need to figure tihs out
   }

   public boolean isOverRect(Point p) {
      // return ... do what you need to figure tihs out
   }

   public String getName() {
      return name;
   }

   @Override
   public String toString() {
      return name + " " + rect.toString();
   }
}

然后像:

public class Resizing2 extends JPanel {

   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private static final Color RECT_COLOR = Color.blue;
   private List<MyRectangle> rectangleList = new ArrayList<>();

   public Resizing2() {
      rectangleList.add(new MyRectangle(100, 100, 150, 150, "Rect 1"));
      rectangleList.add(new MyRectangle(300, 100, 150, 150, "Rect 2"));
   }

   public List<MyRectangle> getRectangleList() {
      return rectangleList;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setColor(RECT_COLOR);
      for (MyRectangle rect : rectangleList) {
         rect.fill(g2);
      }
   }

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

   // ..... etc...