防止JInternalFrame移出JDesktopPane

当我在JDesktopPane中有一个JInternalFrame时,JInternalFrame是可移动的(这很好)。 但是,可以将它移到JDesktopPane的可见范围之外(我不是很喜欢)

为了亲眼看看,这里有一些示例代码:

public static void main(String[] args) { JFrame frame = new JFrame("JDesktopPane"); JDesktopPane tableDisplay = new JDesktopPane(); JInternalFrame internalFrame = new JInternalFrame("JInternalFrame",true,true,true,true); internalFrame.setContentPane(new JLabel("Content")); internalFrame.pack(); internalFrame.setVisible(true); tableDisplay.add(internalFrame, JDesktopPane.POPUP_LAYER); frame.setContentPane(tableDisplay); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setMinimumSize(new Dimension(400, 300)); frame.setVisible(true); } 

是否可以设置JInternalFrame或JDesktopPane以便它们不允许这样做?

负责移动/resize的协作者是DesktopPaneManager。 所以我会尝试将移动限制在窗格内。 这是一个快速而肮脏的概念certificate:

  JDesktopPane background = new JDesktopPane(); JInternalFrame internalFrame = new JInternalFrame("Internal Frame", true, true, true, true); DesktopManager manager = new DefaultDesktopManager() { /** This moves the JComponent 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; 

但这与当前鼠标位置有关。

完全归功于kleopatra让我指向正确的方向。

我想我已经解决了无反应问题,并且在这里分享我的解决方案。 按照kleopatra的回答,如果鼠标点位于窗格之外,则内部框架位于窗格的边缘。 此外,这继续跟随鼠标 – 即如果您将鼠标移离窗格底部,然后向窗口的右侧移动,框架将沿着窗格的底部,然后向右移动窗格的沙子。

 public class BoundedDesktopManager extends DefaultDesktopManager { @Override public void beginDraggingFrame(JComponent f) { // Don't do anything. Needed to prevent the DefaultDesktopManager setting the dragMode } @Override public void beginResizingFrame(JComponent f, int direction) { // Don't do anything. Needed to prevent the DefaultDesktopManager setting the dragMode } @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)) { Container parent = f.getParent(); Dimension parentSize = parent.getSize(); int boundedX = (int) Math.min(Math.max(0, newX), parentSize.getWidth() - newWidth); int boundedY = (int) Math.min(Math.max(0, newY), parentSize.getHeight() - newHeight); f.setBounds(boundedX, boundedY, newWidth, newHeight); } else { 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; } } 

尝试设置JFrame的FlowLayout并使用add()方法添加JDesktopPane。

 frame.setLayout(new FlowLayout()); tableDisplay.setPreferredSize(new Dimension(100,100)); frame.add(tableDisplay); 

重要的是JInternalFrame的顶部不会被隐藏,因为这是它的抓杆和控制按钮所在的位置。 因此,作为设置边界之前的最后一步,请确保您的y值不是负数:例如,使用y = Math.max(0,y)之类的语句。