8

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 を設定することは可能ですか?

4

4 に答える 4

8

移動/サイズ変更を担当する共同作業者は、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 に応じてマネージャーを使用します。これは、インストールされている LAF に他のすべてを委譲するラッパー DesktopManager を実装することで実行できます。
  • 副作用をチェックします(壁にぶつかった後、ドラッグが反応しないように見えます。他に必要なものがあるかもしれません)

編集

明確にするために:「応答しない」とは、ユーザーがリリースして再度押したりドラッグしたりして(内部フレームがデスクトップの境界に達したら)、さらに移動する必要があることを意味します。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;

ただし、これは現在のマウスの位置に相対的です。

于 2011-11-15T15:42:55.660 に答える
8

私を正しい方向に向けてくれた 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;
  }
}
于 2011-11-16T12:11:45.690 に答える
0

JInternalFrame の上部が非表示にならないようにすることが重要です。これは、グラブ バーとコントロール ボタンが配置されている場所だからです。したがって、境界を設定する前の最後のステップとして、y の値が負でないことを確認してください。たとえば、y = Math.max(0, y) のようなステートメントを使用します。

于 2015-08-26T00:00:10.390 に答える
0

FlowLayoutJFrameを設定し、add()メソッドを使用して JDesktopPane を追加してみてください。

frame.setLayout(new FlowLayout());
tableDisplay.setPreferredSize(new Dimension(100,100));
frame.add(tableDisplay);
于 2011-11-15T13:29:44.830 に答える