• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JInternalFrameをJFrameとして表示する
#navi(../)
RIGHT:Posted by [[terai]] at 2009-08-31
*JInternalFrameをJFrameとして表示する [#tf5e5ced]
JFrameのタイトルバーなどを非表示にし、JInternalFrameのタイトルバーでこれらを代用します。

-&jnlp;
-&jar;
-&zip;

#screenshot

**サンプルコード [#k636189e]
#code{{
final JInternalFrame internal = new JInternalFrame("@title@");
BasicInternalFrameUI ui = (BasicInternalFrameUI)internal.getUI();
Component title = ui.getNorthPane();
for(MouseMotionListener l:title.getListeners(MouseMotionListener.class)) {
  title.removeMouseMotionListener(l);
}
DragWindowListener dwl = new DragWindowListener();
title.addMouseListener(dwl);
title.addMouseMotionListener(dwl);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(new JTree()));
p.add(new JButton(new AbstractAction("close") {
  public void actionPerformed(ActionEvent e) {
    Window w = SwingUtilities.windowForComponent((Component)e.getSource());
    //w.dispose();
    w.getToolkit().getSystemEventQueue().postEvent(
      new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
  }
}), BorderLayout.SOUTH);
internal.getContentPane().add(p);
internal.setVisible(true);

KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(new PropertyChangeListener() {
  public void propertyChange(PropertyChangeEvent e) {
    String prop = e.getPropertyName();
    if("activeWindow".equals(prop)) {
      try{
        internal.setSelected(e.getNewValue()!=null);
      }catch(PropertyVetoException ex) {
        ex.printStackTrace();
      }
    }
  }
});
}}

**解説 [#d219693c]
上記のサンプルでは、JInternalFrameのタイトルバーを使用することで、タイトルバーに閉じるボタンのないフレームを作成しています。

-JFrame#setUndecorated(true) で、JFrameのタイトルバーなどを非表示
-BasicInternalFrameUI#getNorthPane()でJInternalFrameのタイトルバーを取得
--元のMouseMotionListenerを削除
--JInternalFrameをドラッグすると親のJFrameが移動するMouseMotionListenerを追加

-制限
--最大化、最小化、リサイズなどには未対応
---Alt+Spaceで最大化、最小化できるが、元のサイズに戻せなくなる場合がある
--角の透明化には未対応
---目立たなくするために、LookAndFeelはNimbusに変更
---JDK 1.7.0 なら、frame.setBackground(new Color(0,0,0,0));frame.add(p=new MainPanel());p.setOpaque(false); で角の透明化が可能

**参考リンク [#y4fccd48]
-[[JWindowをマウスで移動>Swing/DragWindow]]
-[[JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする>Swing/CustomDecoratedFrame]]

**コメント [#b720b8d7]
- JFrameのアクティブ状態が変わったら、JInternalFrameの選択状態も変化するように変更。 -- [[terai]] &new{2009-11-13 (金) 14:57:18};
- リサイズ可能?にする場合のテスト -- [[terai]] &new{2010-06-10 (木) 15:07:18};
#code{{
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class InternalFrameJFrame {
  public JComponent makeUI() {
    final JInternalFrame internal = new JInternalFrame("@title@");
    BasicInternalFrameUI ui = (BasicInternalFrameUI)internal.getUI();
    Component title = ui.getNorthPane();
    for (MouseMotionListener l:title.getListeners(MouseMotionListener.class)) {
      title.removeMouseMotionListener(l);
    }
    DragWindowListener dwl = new DragWindowListener();
    title.addMouseListener(dwl);
    title.addMouseMotionListener(dwl);
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(new JTree()));
    p.add(new JButton(new AbstractAction("close") {
      @Override public void actionPerformed(ActionEvent e) {
        Window w = SwingUtilities.windowForComponent((Component)e.getSource());
        //w.dispose();
        w.getToolkit().getSystemEventQueue().postEvent(
          new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
      }
    }), BorderLayout.SOUTH);
    internal.getContentPane().add(p);
    internal.setVisible(true);

    KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    focusManager.addPropertyChangeListener(new PropertyChangeListener() {
      @Override public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        //System.out.println(prop);
        if ("activeWindow".equals(prop)) {
          try {
            internal.setSelected(e.getNewValue()!=null);
          } catch (PropertyVetoException ex) {
            ex.printStackTrace();
          }
          //System.out.println("---------------------");
        }
      }
    });

    JPanel panel = new JPanel(new BorderLayout());
    panel.add(internal);
    //panel.setOpaque(false);
    panel.setBorder(BorderFactory.createEmptyBorder(0,0,4,4));
    panel.setBackground(new Color(1,1,1,.01f));
    panel.setPreferredSize(new Dimension(320, 200));
    return panel;
  }
  static class DragWindowListener extends MouseAdapter {
    private MouseEvent start;
    private Point  loc;
    private Window window;
    @Override public void mousePressed(MouseEvent me) {
      start = me;
    }
    @Override public void mouseDragged(MouseEvent me) {
      if (window==null) {
        window = SwingUtilities.windowForComponent(me.getComponent());
      }
      loc = window.getLocation(loc);
      int x = loc.x - start.getX() + me.getX();
      int y = loc.y - start.getY() + me.getY();
      window.setLocation(x, y);
    }
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame.setDefaultLookAndFeelDecorated(true);
    JFrame frame = new JFrame();
    //frame.setUndecorated(true);
    com.sun.awt.AWTUtilities.setWindowOpaque(frame, false);
    try {
      //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      for (UIManager.LookAndFeelInfo laf:UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(laf.getName()))
          UIManager.setLookAndFeel(laf.getClassName());
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    frame.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
    JRootPane root = frame.getRootPane();
    JLayeredPane layeredPane = root.getLayeredPane();
    Component c = layeredPane.getComponent(1);
    if (c instanceof JComponent) {
      JComponent oldTitlePane = (JComponent)c;
      System.out.println(c);
      oldTitlePane.setVisible(false);
      layeredPane.remove(oldTitlePane);
    }
    JComponent titlePane = new JLabel();
    layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER);
    titlePane.setVisible(true);

    frame.setMinimumSize(new Dimension(300, 120));
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new InternalFrameJFrame().makeUI());
    //JDK 1.7 frame.setBackground(new Color(0,0,0,0));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
}}
- 英数のみのコメントは書き込みできません。 -- [[snow]] &new{2010-08-01 (Sun) 08:19:26};

#comment