我最近为此构建了自己的原型。也许你会发现这很有用。
它使用2个不同的组件,一个在另一个之上。与 Rob Camick 的 ComponentResizer 不同,这是受其启发的,设置为 JFrame 中组件的鼠标侦听器将正常工作。您不会让 JFrame 捕获所有鼠标事件,因此将侦听器附加到 JFrame 中的组件变得毫无用处。它仅在必须显示双向箭头的时间和位置捕获鼠标事件。
关键是顶部组件中的此方法:
@Override
public boolean contains(int x, int y) {
return x < insets.left || y < insets.top
|| getHeight() - y < insets.bottom
|| getWidth() - x < insets.right;
}
代码如下:
import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class BackgroundComponentDragger implements MouseMotionListener {
private Component controlledComponent;
/*
* Point where cursor was last clicked.
*/
private Point originPoint;
public BackgroundComponentDragger(Component component) {
this.controlledComponent = component;
}
@Override
public void mouseDragged(MouseEvent e) {
Point currentFramePosition = controlledComponent.getLocation();
Point newFramePosition = new Point(currentFramePosition.x + e.getX()
- originPoint.x, currentFramePosition.y + e.getY() - originPoint.y);
controlledComponent.setLocation(newFramePosition);
}
@Override
public void mouseMoved(MouseEvent e) {
originPoint = e.getPoint();
}
}
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
import java.util.Map;
public class ComponentBorderDragger implements MouseMotionListener {
private Component controlledComponent;
private byte direction;
protected static final byte NORTH = 1;
protected static final byte WEST = 2;
protected static final byte SOUTH = 4;
protected static final byte EAST = 8;
private Cursor sourceCursor;
private static Map<Byte, Integer> cursors = new HashMap<Byte, Integer>();
{
cursors.put((byte) 1, Cursor.N_RESIZE_CURSOR);
cursors.put((byte) 2, Cursor.W_RESIZE_CURSOR);
cursors.put((byte) 4, Cursor.S_RESIZE_CURSOR);
cursors.put((byte) 8, Cursor.E_RESIZE_CURSOR);
cursors.put((byte) 3, Cursor.NW_RESIZE_CURSOR);
cursors.put((byte) 9, Cursor.NE_RESIZE_CURSOR);
cursors.put((byte) 6, Cursor.SW_RESIZE_CURSOR);
cursors.put((byte) 12, Cursor.SE_RESIZE_CURSOR);
}
private Insets dragInsets;
private Dimension minSize;
private Point basePoint;
public ComponentBorderDragger(Component controlledComponent, Insets dragInsets,
Dimension minSize) {
super();
this.controlledComponent = controlledComponent;
this.dragInsets = dragInsets;
this.minSize = minSize;
}
@Override
public void mouseDragged(MouseEvent e) {
if (direction == 0) {
return;
}
Point newPoint = e.getPoint();
int x, y, width, height, newBasePointX, newBasePointY;
x = controlledComponent.getX();
y = controlledComponent.getY();
width = controlledComponent.getWidth();
height = controlledComponent.getHeight();
newBasePointX = newPoint.x;
newBasePointY = newPoint.y;
if ((direction & EAST) == EAST) {
int newWidth;
newWidth = Math.max(minSize.width, width + newPoint.x
- basePoint.x);
width = newWidth;
}
if ((direction & SOUTH) == SOUTH) {
int novoAlto;
novoAlto = Math.max(minSize.height, height + newPoint.y
- basePoint.y);
height = novoAlto;
}
if ((direction & WEST) == WEST) {
int newWidth, newX;
newWidth = Math.max(minSize.width, width - newPoint.x
+ basePoint.x);
newX = Math.min(x + width - minSize.width, x + newPoint.x
- basePoint.x);
// Changing coordenates of new base point to refer to the new component position
newBasePointX -= newX - x;
x = newX;
width = newWidth;
}
if ((direction & NORTH) == NORTH) {
int newHeigth, newY;
newHeigth = Math.max(minSize.height, height - newPoint.y
+ basePoint.y);
newY = Math.min(y + height - minSize.height, y + newPoint.y
- basePoint.y);
// Changing coordenates of new base point to refer to the new component position
newBasePointY -= newY - y;
y = newY;
height = newHeigth;
}
controlledComponent.setBounds(x, y, width, height);
basePoint = new Point(newBasePointX, newBasePointY);
}
@Override
public void mouseMoved(MouseEvent e) {
Component originator = e.getComponent();
if (direction == 0) {
sourceCursor = originator.getCursor();
}
calculateDirection(e.getPoint(), e.getComponent().getSize());
setCursor(e.getComponent());
basePoint = e.getPoint();
}
private void setCursor(Component component) {
if (direction == 0) {
component.setCursor(sourceCursor);
} else {
int cursorType = cursors.get(direction);
Cursor cursor = Cursor.getPredefinedCursor(cursorType);
component.setCursor(cursor);
}
}
private void calculateDirection(Point point, Dimension componentSize) {
direction = 0;
if (point.x < dragInsets.left) {
direction |= WEST;
}
if (point.y < dragInsets.top) {
direction |= NORTH;
}
if (point.x > componentSize.width - dragInsets.right) {
direction |= EAST;
}
if (point.y > componentSize.height - dragInsets.bottom) {
direction |= SOUTH;
}
}
}
import java.awt.Insets;
import javax.swing.JComponent;
public class FrameComponent extends JComponent {
private static final long serialVersionUID = 3383070502274306213L;
private Insets insets;
@Override
public boolean contains(int x, int y) {
return x < insets.left || y < insets.top || getHeight() - y < insets.bottom || getWidth() - x < insets.right;
}
public FrameComponent(Insets insets) {
this.insets = insets;
}
}
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI {
private JFrame compoundFrame;
private JPanel backgroundPanel;
Dimension gUISize = new Dimension(400, 400);
public GUI() {
buildResizeableFrame();
}
public void activate() {
compoundFrame.setVisible(true);
}
private void buildResizeableFrame() {
compoundFrame = new JFrame();
FrameComponent frame = new FrameComponent(new Insets(5, 5, 5, 5));
backgroundPanel = new JPanel();
compoundFrame.setLayout(null);
compoundFrame.add(frame);
compoundFrame.add(backgroundPanel);
setFrameSizeController(frame, backgroundPanel);
setFrameController(frame);
setBackgroundPanelController(backgroundPanel);
Dimension dimPant = Toolkit.getDefaultToolkit().getScreenSize();
compoundFrame.setBounds(dimPant.width / 4, dimPant.height / 4, dimPant.width / 2, dimPant.height / 2);
compoundFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
compoundFrame.setUndecorated(true);
}
private void setFrameSizeController(FrameComponent frame, JPanel panel) {
compoundFrame.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
Dimension sizeIn = ((JFrame) e.getComponent()).getContentPane().getSize();
frame.setSize(sizeIn);
panel.setSize(sizeIn);
}
});
}
private void setFrameController(FrameComponent frame) {
ComponentBorderDragger controller = new ComponentBorderDragger(compoundFrame,
new Insets(5, 5, 5, 5), new Dimension(10, 10));
frame.addMouseMotionListener(controller);
}
private void setBackgroundPanelController(JPanel panel) {
panel.addMouseMotionListener(new BackgroundComponentDragger(compoundFrame));
}
public static void main(String[] args) {
new GUI().activate();
}
}
注意:此代码设置一个空布局管理器和一个容器侦听器,以便在需要时调整内部组件的大小。不鼓励这种做法。应将此逻辑移动到自定义布局管理器。