JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする
Total: 21736
, Today: 3
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JFrame
のタイトルバーなどを非表示にして独自に描画し、これに移動リサイズなどの機能も追加します。
Screenshot
Advertisement
サンプルコード
class ResizeWindowListener extends MouseAdapter {
private Rectangle startSide = null;
private final JFrame frame;
public ResizeWindowListener(JFrame frame) {
this.frame = frame;
}
@Override public void mousePressed(MouseEvent e) {
startSide = frame.getBounds();
}
@Override public void mouseDragged(MouseEvent e) {
if (startSide == null) return;
Component c = e.getComponent();
if (c == topleft) {
startSide.y += e.getY();
startSide.height -= e.getY();
startSide.x += e.getX();
startSide.width -= e.getX();
} else if (c == top) {
startSide.y += e.getY();
startSide.height -= e.getY();
} else if (c == topright) {
startSide.y += e.getY();
startSide.height -= e.getY();
startSide.width += e.getX();
} else if (c == left) {
startSide.x += e.getX();
startSide.width -= e.getX();
} else if (c == right) {
startSide.width += e.getX();
} else if (c == bottomleft) {
startSide.height += e.getY();
startSide.x += e.getX();
startSide.width -= e.getX();
} else if (c == bottom) {
startSide.height += e.getY();
} else if (c == bottomright) {
startSide.height += e.getY();
startSide.width += e.getX();
}
frame.setBounds(startSide);
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルではJFrame
の元のタイトルバーをsetUndecorated(true)
で非表示にし、マウスドラッグで移動可能にしたJPanel
を追加してタイトルバーの代わりにしています。
- マウスドラッグでのフレームのリサイズはSwing - Undecorated and resizable dialogや
BasicInternalFrameUI.java
、MetalRootPaneUI#MouseInputHandler
などを参考にして、周辺にそれぞれ対応するリサイズカーソルを設定したJLabel
を配置して実行 JDK 1.7.0
の場合JFrame#setBackground(new Color(0x0, true))
でJFrame
の背景色を透明化、かつContentPane
の左右上の角をクリアして透明化- JRootPaneにリサイズのための装飾を設定するのように
JRootPane#setWindowDecorationStyle(JRootPane.PLAIN_DIALOG)
を使用してリサイズする方法もある
// package example;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainPanel {
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);
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;
}
public JComponent makeUI() {
return new JScrollPane(new JTree());
}
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;
}
public static void main(String[] args) {
EventQueue.invokeLater(MainPanel::createAndShowGUI);
}
public static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setUndecorated(true);
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);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
Toolkit.getDefaultToolkit().beep();
}
frame.getContentPane().add(demo.makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class DragWindowListener extends MouseAdapter {
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());
}
@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);
}
}
}
class CloseIcon implements Icon {
@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();
}
@Override public int getIconWidth() {
return 16;
}
@Override public int getIconHeight() {
return 16;
}
}
参考リンク
- Swing - Undecorated and resizable dialog
- JWindowをマウスで移動
- JInternalFrameをJFrameとして表示する
- JRootPaneにリサイズのための装飾を設定する