JMenuItemの選択ロールオーバーをラウンド矩形で描画する
Total: 343
, Today: 1
, Yesterday: 3
Posted by aterai at
Last-modified:
概要
JMenuItem
の選択ロールオーバーを矩形ではなくラウンド矩形で描画するよう設定します。
Screenshot
Advertisement
サンプルコード
class BasicRoundMenuItemUI extends BasicMenuItemUI {
@Override protected void paintBackground(
Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel m = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
if (menuItem.isOpaque()) {
if (m.isArmed() || (menuItem instanceof JMenu && m.isSelected())) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2.clearRect(0, 0, menuWidth, menuHeight);
g2.setPaint(menuItem.getBackground());
g2.fillRect(0, 0, menuWidth, menuHeight);
g2.setColor(bgColor);
g2.fillRoundRect(2, 2, menuWidth - 4, menuHeight - 4, 8, 8);
g2.dispose();
} else {
g.setColor(menuItem.getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
}
g.setColor(oldColor);
} else if (m.isArmed() || (menuItem instanceof JMenu && m.isSelected())) {
g.setColor(bgColor);
g.fillRoundRect(2, 2, menuWidth - 4, menuHeight - 4, 8, 8);
g.setColor(oldColor);
}
}
}
View in GitHub: Java, Kotlin解説
MetalLookAndFeel
、MotifLookAndFeel
WindowsLookAndFeel
以外のBasicMenuItemUI
を継承するMenuItemUI
でJMenuItem
の選択ロールオーバーをラウンド矩形で描画するようBasicMenuItemUI#paintBackground(...)
をオーバーライドJMenu#add(String)
、JPopupMenu#add(String)
などをオーバーライドしてこのメソッドで生成されるJMenuItem
にBasicRoundMenuItemUI
を設定JMenuItem
のフチ描画はUIManager.put("MenuItem.borderPainted", Boolean.FALSE)
で描画しないよう設定JCheckBoxMenuItem
やJRadioButtonMenuItem
の選択ロールオーバー描画には影響しないSynthMenuItemUI
を継承するNimbusLookAndFeel
などのJMenuItem
には未対応
WindowsLookAndFeel
WindowsMenuItemUI.isVistaPainting()
やWindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor)
などがパッケージプライベートなので選択ハイライトをラウンド矩形でソフトクリップしたBufferedImage
(またはVolatileImage
)を生成してWindowsMenuItemUI#paintBackground(...)
内で描画
class WindowsRoundMenuItemUI extends WindowsMenuItemUI {
private BufferedImage buffer;
@Override protected void paintBackground(
Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel model = menuItem.getModel();
if (model.isArmed() ||
(menuItem instanceof JMenu && model.isSelected())) {
int width = menuItem.getWidth();
int height = menuItem.getHeight();
if (buffer == null ||
buffer.getWidth() != width || buffer.getHeight() != height) {
buffer = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = buffer.createGraphics();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.fill(new RoundRectangle2D.Float(0f, 0f, width, height, 8f, 8f));
g2.setComposite(AlphaComposite.SrcAtop);
super.paintBackground(g2, menuItem, bgColor);
g2.dispose();
g.drawImage(buffer, 0, 0, menuItem);
} else {
super.paintBackground(g, menuItem, bgColor);
}
}
}
class WindowsRoundMenuItemUI2 extends WindowsMenuItemUI {
private VolatileImage buffer;
@Override protected void paintBackground(
Graphics g, JMenuItem menuItem, Color bgColor) {
ButtonModel model = menuItem.getModel();
if (model.isArmed() ||
(menuItem instanceof JMenu && model.isSelected())) {
int width = menuItem.getWidth();
int height = menuItem.getHeight();
GraphicsConfiguration config = ((Graphics2D) g)
.getDeviceConfiguration();
do {
int status = VolatileImage.IMAGE_INCOMPATIBLE;
if (buffer != null) {
status = buffer.validate(config);
}
if (status == VolatileImage.IMAGE_INCOMPATIBLE ||
status == VolatileImage.IMAGE_RESTORED) {
if (buffer == null ||
buffer.getWidth() != width ||
buffer.getHeight() != height ||
status == VolatileImage.IMAGE_INCOMPATIBLE) {
if (buffer != null) {
buffer.flush();
}
buffer = config.createCompatibleVolatileImage(
width, height, Transparency.TRANSLUCENT);
}
Graphics2D g2 = buffer.createGraphics();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, width, height);
g2.setPaintMode(); // g2.setComposite(AlphaComposite.Src);
g2.setPaint(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(
0f, 0f, width, height, 8f, 8f));
g2.setComposite(AlphaComposite.SrcAtop);
super.paintBackground(g2, menuItem, bgColor);
g2.dispose();
}
} while (buffer.contentsLost());
g.drawImage(buffer, 0, 0, menuItem);
} else {
super.paintBackground(g, menuItem, bgColor);
}
}
}
参考リンク
- JPopupMenuの角を丸める
JPopupMenu
の角丸はリンク先と同一のRoundedPopupMenuUI.java
を使用している
- Windowの縁をソフトクリッピングでなめらかにする