如何在 Java Swing 中创建可拖动和调整大小的组件?
就像 MS Paint 中的“文本工具”文本框功能,在图像中以红色边框突出显示。
我只想要拖动和调整大小功能,而不是文本格式。
如何使用 Java Swing 实现这个组件?
为了解决这个问题,我找到了 Piccolo2d ZUI 库。
这正是我要找的!然而,仅仅实现一个“可拖动和调整大小的文本框”可能不是最好的方法,但我使用 Piccolo2d 在不到一个小时的时间内就让它工作了。所以,我在这里发布代码,如果有人觉得它有用的话。
这是示例应用程序的屏幕截图!
我试图使代码尽可能可描述,所以它有点长。
您需要piccolo2d-core-XXX.jar
&piccolo2d-extras-XXX.jar
来运行此代码,该代码可以从Maven Central Repository下载。我用的是 3.0 版,没有用任何其他版本测试过!
自定义组件类
class PBox extends PNode {
private PCanvas canvas;
private Rectangle2D rectangle;
private Cursor moveCursor;
public PBox(PCanvas canvas) {
this(0, 0, 50, 50, canvas);
}
public PBox(double x, double y, double width, double height, PCanvas canvas) {
this.canvas = canvas;
rectangle = new Rectangle2D.Double();
moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
addAnchors(x, y, width, height);
setBounds(x, y, width, height);
setInputEventListener();
}
private void addAnchors(double x, double y, double width, double height) {
addChild(new Anchor(SwingConstants.NORTH));
addChild(new Anchor(SwingConstants.NORTH_EAST));
addChild(new Anchor(SwingConstants.EAST));
addChild(new Anchor(SwingConstants.SOUTH_EAST));
addChild(new Anchor(SwingConstants.SOUTH));
addChild(new Anchor(SwingConstants.SOUTH_WEST));
addChild(new Anchor(SwingConstants.WEST));
addChild(new Anchor(SwingConstants.NORTH_WEST));
}
private void setInputEventListener() {
addInputEventListener(new PBasicInputEventHandler() {
@Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(moveCursor);
}
@Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
}
@Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(PBox.this);
translate(delta.width, delta.height);
event.setHandled(true);
}
});
}
@Override
protected void layoutChildren() {
Iterator iterator = getChildrenIterator();
int position = SwingConstants.NORTH;
while (iterator.hasNext()) {
PNode anchor = (PNode) iterator.next();
anchor.setBounds(getAnchorBounds(position));
++position;
}
}
private Rectangle2D getAnchorBounds(int position) {
double x = 0, y = 0;
Rectangle2D b = getBounds();
switch (position) {
case SwingConstants.NORTH:
x = b.getX()+b.getWidth()/2;
y = b.getY();
break;
case SwingConstants.NORTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY();
break;
case SwingConstants.EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.SOUTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH:
x = b.getX()+b.getWidth()/2;
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH_WEST:
x = b.getX();
y = b.getY()+b.getHeight();
break;
case SwingConstants.WEST:
x = b.getX();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.NORTH_WEST:
x = b.getX();
y = b.getY();
break;
}
return new Rectangle2D.Double(x-2, y-2, 4, 4);
}
@Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
rectangle.setFrame(x, y, width, height);
return true;
}
return false;
}
@Override
public boolean intersects(Rectangle2D localBounds) {
return rectangle.intersects(localBounds);
}
@Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setPaint(Color.BLACK);
g2.setStroke(new BasicStroke(1.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
1.0f, new float[]{4.0f}, 0));
g2.draw(rectangle);
}
class Anchor extends PNode {
private Rectangle2D point;
private Cursor resizeCursor;
Anchor(int position) {
point = new Rectangle2D.Double();
setCursor(position);
setInputEventListener(position);
}
private void setCursor(int position) {
switch (position) {
case SwingConstants.NORTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
break;
case SwingConstants.EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
break;
case SwingConstants.WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
break;
default:
resizeCursor = Cursor.getDefaultCursor();
}
}
private void setInputEventListener(final int position) {
addInputEventListener(new PBasicInputEventHandler() {
@Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(resizeCursor);
event.setHandled(true);
}
@Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
event.setHandled(true);
}
@Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(Anchor.this);
PNode parent = getParent();
if (position == SwingConstants.EAST
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.SOUTH_EAST) {
parent.setWidth(parent.getWidth() + delta.width);
} else if (position == SwingConstants.WEST
|| position == SwingConstants.NORTH_WEST
|| position == SwingConstants.SOUTH_WEST) {
parent.setX(parent.getX() + delta.width);
parent.setWidth(parent.getWidth() - delta.width);
}
if (position == SwingConstants.SOUTH
|| position == SwingConstants.SOUTH_EAST
|| position == SwingConstants.SOUTH_WEST) {
parent.setHeight(parent.getHeight() + delta.height);
} else if (position == SwingConstants.NORTH
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.NORTH_WEST) {
parent.setY(parent.getY() + delta.height);
parent.setHeight(parent.getHeight() - delta.height);
}
event.setHandled(true);
}
});
}
@Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
point.setFrame(x, y, width, height);
return true;
}
return false;
}
@Override
public boolean intersects(Rectangle2D localBounds) {
return point.intersects(localBounds);
}
@Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setColor(Color.WHITE);
g2.fill(point);
g2.setStroke(new BasicStroke(1.0f));
g2.setColor(Color.BLACK);
g2.draw(point);
}
}
}
而且,主课
public class Piccolo2DExample extends PFrame {
@Override
public void initialize() {
PCanvas canvas = getCanvas();
PNode text = new PText("Draggable & Resizable Box using Piccolo2d");
text.scale(2.0);
canvas.getCamera().addChild(text);
PLayer layer = canvas.getLayer();
PNode aLayerNode = new PText("A_Layer_Node");
aLayerNode.setOffset(10, 50);
layer.addChild(aLayerNode);
// Adding the component to layer
layer.addChild(new PBox(50, 100, 250, 50, canvas));
}
public static void main(String[] args) {
PFrame frame = new Piccolo2DExample();
frame.setSize(800, 640);
}
}