JMenuItemの選択ロールオーバーをラウンド矩形で描画する
Total: 927, Today: 1, Yesterday: 1
Posted by aterai at
Last-modified:
Summary
JMenuItemの選択ロールオーバーを矩形ではなくラウンド矩形で描画するよう設定します。
Screenshot

Advertisement
Source Code Examples
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, KotlinDescription
MetalLookAndFeel、MotifLookAndFeelWindowsLookAndFeel以外の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には未対応
WindowsLookAndFeelWindowsMenuItemUI.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);
}
}
}
Reference
- JPopupMenuの角を丸める
JPopupMenuの角丸はリンク先と同一のRoundedPopupMenuUI.javaを使用している
- Windowの縁をソフトクリッピングでなめらかにする