负责移动/调整大小的协作者是 DesktopPaneManager。所以我会尝试将移动限制在窗格内。这是一个快速而肮脏的概念证明:
JDesktopPane background = new JDesktopPane();
JInternalFrame internalFrame = new JInternalFrame("Internal Frame",
true, true, true, true);
DesktopManager manager = new DefaultDesktopManager() {
/** This moves the <code>JComponent</code> and repaints the damaged areas. */
@Override
public void setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) {
boolean didResize = (f.getWidth() != newWidth || f.getHeight() != newHeight);
if (!inBounds((JInternalFrame) f, newX, newY, newWidth, newHeight)) return;
f.setBounds(newX, newY, newWidth, newHeight);
if(didResize) {
f.validate();
}
}
protected boolean inBounds(JInternalFrame f, int newX, int newY, int newWidth, int newHeight) {
if (newX < 0 || newY < 0) return false;
if (newX + newWidth > f.getDesktopPane().getWidth()) return false;
if (newY + newHeight > f.getDesktopPane().getHeight()) return false;
return true;
}
};
background.setDesktopManager(manager);
显然有一些问题需要解决:-) Fi
- 使用适合 LAF 的管理器,这可以通过实现一个包装器 DesktopManager 来完成,该包装器将其他所有内容委托给安装的 LAF
- 检查副作用(在撞墙后拖动出现无响应,可能需要其他东西)
编辑
只是为了澄清:“无响应”是指用户必须释放并再次按下/拖动(一旦内部框架触及桌面边界)以进一步移动。这并不奇怪,因为 BorderListener(即由 BasicInternalFrame 安装的 mouseListener)保持与初始按下相关的一些状态,然后请求相对于该初始位置重新定位。在框架卡在某处的情况下拖动鼠标会混淆该内部状态。
有趣的是,看代码,似乎有人打算限制运动不将其推到外面,
// Make sure we stay in-bounds
if(newX + i.left <= -__x)
newX = -__x - i.left + 1;
if(newY + i.top <= -__y)
newY = -__y - i.top + 1;
if(newX + __x + i.right >= pWidth)
newX = pWidth - __x - i.right - 1;
if(newY + __y + i.bottom >= pHeight)
newY = pHeight - __y - i.bottom - 1;
不过,这是相对于当前鼠标位置的。