首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止将JInternalFrame移出JDesktopPane

防止将JInternalFrame移出JDesktopPane
EN

Stack Overflow用户
提问于 2011-11-15 21:19:01
回答 4查看 7K关注 0票数 8

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

为了自己看一下,下面是一些示例代码:

代码语言:javascript
复制
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,使它们不允许这样做?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-15 23:42:56

负责移动/调整大小的协作者是DesktopPaneManager。因此,我会尝试将移动限制在窗格内。这是一个快速而粗糙的概念证明:

代码语言:javascript
复制
    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);

显然,有一些问题需要解决:-) F.i.

  • 为LAF使用适当的管理器,这可以通过实现一个包装器DesktopManager来完成,该包装器将其他所有内容委托给LAF DesktopManager以产生副作用(在撞到墙上后,拖动显示为无响应,可能还需要其他东西)

编辑

只是为了澄清一下:“无响应”是指用户必须松开并再次按下/拖动(一旦内部框架达到桌面边界)来进一步移动。这并不奇怪,因为BorderListener (由BasicInternalFrame安装的mouseListener )保留了与初始按下相关的一些状态,然后请求相对于该初始位置进行重新定位。将鼠标拖到框架所在的位置会混淆这种内部状态。

有趣的是,看一下代码,似乎有限制移动的意图,不把它推到外面,

代码语言:javascript
复制
    // 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;

不过,这是相对于当前鼠标位置的。

票数 8
EN

Stack Overflow用户

发布于 2011-11-16 20:11:46

完全归功于克利奥帕特拉为我指明了正确的方向。

我想我已经解决了无响应的问题,并在这里分享我的解决方案。根据kleopatra的回答,如果鼠标指针位于窗格外部,则内部框架位于窗格的边缘。此外,这将继续跟随鼠标-即,如果您移动鼠标离开窗格的底部,然后转到窗格的右侧,框架将沿着窗格的底部,然后向上移动到窗格的右侧沙子。

代码语言:javascript
复制
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;
  }
}
票数 8
EN

Stack Overflow用户

发布于 2011-11-15 21:29:45

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

代码语言:javascript
复制
frame.setLayout(new FlowLayout());
tableDisplay.setPreferredSize(new Dimension(100,100));
frame.add(tableDisplay);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8136944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档