TITLE:JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする
Posted by at 2010-01-18

JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする

JFrameのタイトルバーなどを非表示にして独自に描画し、これに移動リサイズなどの機能も追加します。
  • category: swing folder: CustomDecoratedFrame title: JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする tags: [JFrame, MouseListener, MouseMotionListener, JPanel, JLabel, ContentPane, Transparent] author: aterai pubdate: 2010-01-18T11:27:29+09:00 description: JFrameのタイトルバーなどを非表示にして独自に描画し、これに移動リサイズなどの機能も追加します。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTKV1P7mYI/AAAAAAAAAV0/u4qjd-ItBYU/s800/CustomDecoratedFrame.png hreflang:
       href: https://java-swing-tips.blogspot.com/2010/05/custom-decorated-titlebar-jframe.html
       lang: en

概要

JFrameのタイトルバーなどを非表示にして独自に描画し、これに移動リサイズなどの機能も追加します。
CustomDecoratedFrame.png

サンプルコード

サンプルコード

class ResizeWindowListener extends MouseAdapter {
  private Rectangle startSide = null;
  private final JFrame frame;
  public ResizeWindowListener(JFrame frame) {
    this.frame = frame;
  }
#spanadd

#spanend
  @Override public void mousePressed(MouseEvent e) {
    startSide = frame.getBounds();
  }
#spanadd

#spanend
  @Override public void mouseDragged(MouseEvent e) {
    if(startSide==null) return;
    if (startSide == null) return;
    Component c = e.getComponent();
    if(c==topleft) {
    if (c == topleft) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==top) {
    } else if (c == top) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
    }else if(c==topright) {
    } else if (c == topright) {
      startSide.y += e.getY();
      startSide.height -= e.getY();
      startSide.width += e.getX();
    }else if(c==left) {
    } else if (c == left) {
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==right) {
    } else if (c == right) {
      startSide.width += e.getX();
    }else if(c==bottomleft) {
    } else if (c == bottomleft) {
      startSide.height += e.getY();
      startSide.x += e.getX();
      startSide.width -= e.getX();
    }else if(c==bottom) {
    } else if (c == bottom) {
      startSide.height += e.getY();
    }else if(c==bottomright) {
    } else if (c == bottomright) {
      startSide.height += e.getY();
      startSide.width += e.getX();
    }
    frame.setBounds(startSide);
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルではタイトルバーを、setUndecorated(true)で非表示にし、移動可能にしたJPanelを追加してタイトルバーにしています。 リサイズは、Swing - Undecorated and resizable dialogやBasicInternalFrameUI.java、MetalRootPaneUI#MouseInputHandlerなどを参考にして、周辺にそれぞれ対応するリサイズカーソルを設定したJLabelを配置しています。
  • - JDK 1.7.0 の場合、JFrameの背景色を透明(frame.setBackground(new Color(0,0,0,0)))にし、ContentPaneの左右上の角をクリアして透明にしています。

解説

上記のサンプルではJFrameの元のタイトルバーをsetUndecorated(true)で非表示にし、マウスドラッグで移動可能にしたJPanelを追加してタイトルバーの代わりにしています。

参考リンク

コメント

  • blogspotで、指摘されていたように、このサンプルを1.6.0_xx+WebStartで実行すると、画面の外にフレームをドラッグすることが出来なかったのですが、JREのバージョンを 1.7.0 にすると、WebStartで起動しても画面外に移動可能になっているみたいです。もしかしてデュアルディスプレイでも移動できるようになっているのかも?(確認してないですが...) -- aterai
    • <java version="1.7+" /> にしたjnlp http://terai.xrea.jp/swing/customdecoratedframe/example2.jnlp -- aterai
      #spanend
      #spanadd
      // package example;
      #spanend
      
      #spanadd
      import java.awt.*;
      #spanend
      #spanadd
      import java.awt.event.*;
      #spanend
      #spanadd
      import javax.swing.*;
      #spanend
      #spanadd
      
      #spanend
      #spanadd
      public class MainPanel {
      #spanend
        private static final Color BG_COLOR = Color.ORANGE;
        public JComponent makeTitleBar() {
          JLabel label = new JLabel("Title", SwingConstants.CENTER);
          label.setOpaque(true);
          label.setForeground(Color.WHITE);
          label.setBackground(BG_COLOR);
          DragWindowListener dwl = new DragWindowListener();
          label.addMouseListener(dwl);
          label.addMouseMotionListener(dwl);
      #spanadd
      
      #spanend
          JPanel title = new JPanel(new BorderLayout());
          title.setBorder(BorderFactory.createMatteBorder(0, 2, 2, 2, BG_COLOR));
          title.add(label);
          title.add(makeCloseButton(), BorderLayout.EAST);
          return title;
        }
      #spanadd
      
      #spanend
        public JComponent makeUI() {
          return new JScrollPane(new JTree());
        }
      #spanadd
      
      #spanend
        private static JButton makeCloseButton() {
          JButton button = new JButton(new CloseIcon());
          button.setContentAreaFilled(false);
          button.setFocusPainted(false);
          button.setBorder(BorderFactory.createEmptyBorder());
          button.setOpaque(true);
          button.setBackground(BG_COLOR);
          button.addActionListener(e -> {
            JComponent b = (JComponent) e.getSource();
            Container c = b.getTopLevelAncestor();
            if (c instanceof Window) {
              Window w = (Window) c;
              w.dispatchEvent(new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
            }
          });
          return button;
        }
      #spanadd
      
      #spanend
        public static void main(String[] args) {
          EventQueue.invokeLater(MainPanel::createAndShowGUI);
        }
      #spanadd
      
      #spanend
        public static void createAndShowGUI() {
          JFrame frame = new JFrame();
          frame.setUndecorated(true);
      #spanadd
      
      #spanend
          MainPanel demo = new MainPanel();
          JRootPane root = frame.getRootPane();
          root.setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
          root.setBorder(BorderFactory.createMatteBorder(2, 4, 4, 4, BG_COLOR));
          JLayeredPane layeredPane = root.getLayeredPane();
          Component c = layeredPane.getComponent(1);
          if (c instanceof JComponent) {
            JComponent orgTitlePane = (JComponent) c;
            orgTitlePane.removeAll();
            orgTitlePane.setLayout(new BorderLayout());
            orgTitlePane.add(demo.makeTitleBar());
          }
          frame.setMinimumSize(new Dimension(300, 120));
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      #spanadd
      
      #spanend
          try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
            Toolkit.getDefaultToolkit().beep();
          }
      #spanadd
      
      #spanend
          frame.getContentPane().add(demo.makeUI());
          frame.setSize(320, 240);
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
        }
      #spanadd
      }
      #spanend
      #spanadd
      
      #spanend
      #spanadd
      class DragWindowListener extends MouseAdapter {
      #spanend
        private final Point startPt = new Point();
        private Window window;
        @Override public void mousePressed(MouseEvent me) {
          if (window == null) {
            Object o = me.getSource();
            if (o instanceof Window) {
              window = (Window) o;
            } else if (o instanceof JComponent) {
              window = SwingUtilities.windowForComponent(me.getComponent());
            }
          }
          startPt.setLocation(me.getPoint());
        }
      #spanadd
      
      #spanend
        @Override public void mouseDragged(MouseEvent me) {
          if (window != null) {
            Point pt = new Point();
            pt = window.getLocation(pt);
            int x = pt.x - startPt.x + me.getX();
            int y = pt.y - startPt.y + me.getY();
            window.setLocation(x, y);
          }
        }
      #spanadd
      }
      #spanend
      #spanadd
      
      #spanend
      #spanadd
      class CloseIcon implements Icon {
      #spanend
        @Override public void paintIcon(Component c, Graphics g, int x, int y) {
          Graphics2D g2 = (Graphics2D) g.create();
          g2.translate(x, y);
          g2.setPaint(Color.WHITE);
          g2.drawLine(4, 4, 11, 11);
          g2.drawLine(4, 5, 10, 11);
          g2.drawLine(5, 4, 11, 10);
          g2.drawLine(11, 4, 4, 11);
          g2.drawLine(11, 5, 5, 11);
          g2.drawLine(10, 4, 4, 10);
          g2.dispose();
        }
      #spanadd
      
      #spanend
        @Override public int getIconWidth() {
          return 16;
        }
      #spanadd
      
      #spanend
        @Override public int getIconHeight() {
          return 16;
        }
      #spanadd
      }
      #spanend
      #spanadd
      

参考リンク

コメント