import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
public class IconMenuExample {
public static void main(String[] args) throws Exception {
// we set the Windows Look And Feel
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Menu Icon Example");
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
// we create sample actions using programmatic sixteen by sixteen ImageIcon instances
Action openAction = newAction(
"Open",
createColorIcon(Color.BLUE),
true,
e -> System.out.println("Open")
);
Action saveAction = newAction(
"Save",
createColorIcon(Color.GREEN),
true,
e -> System.out.println("Save")
);
Action exitAction = newAction(
"Exit",
createColorIcon(Color.RED),
true,
e -> System.exit(0)
);
// we attach the actions to menu items
fileMenu.add(new JMenuItem(openAction));
fileMenu.add(new JMenuItem(saveAction));
fileMenu.addSeparator();
fileMenu.add(new JMenuItem(exitAction));
menuBar.add(fileMenu);
frame.setJMenuBar(menuBar);
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
public static Action newAction(String name, boolean enable, ActionListener listener) {
return new AbstractAction(name) {
{
setEnabled(enable);
}
@Override
public void actionPerformed(ActionEvent e) {
listener.actionPerformed(e);
}
};
}
public static Action newAction(String name, ImageIcon icon, boolean enable, ActionListener listener) {
Action action = newAction(name, enable, listener);
action.putValue(Action.SMALL_ICON, icon);
return action;
}
// we create a programmatic sixteen by sixteen ImageIcon filled with the given color
private static ImageIcon createColorIcon(Color color) {
int size = 16;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
try {
g.setColor(color);
g.fillRect(0, 0, size, size);
} finally {
g.dispose();
}
return new ImageIcon(image);
}
}
Вероятно, это не ошибка, а особенность. Я предполагаю, что это новое зарезервированное место для значков, но понятия не имею, как бы я его использовал.
Проблема начала проявляться после обновления с Java 21 до 25. В Java 21 мои меню выглядели так: [img]https://i.sstatic.net/bIcYARUr.png[/img]
В Java 25 начал появляться желоб: [img]https://i.sstatic.net/TMc8LkEJ.png[/img]
Я создал минимальный портативный пример для воспроизведения: [code]import java.awt.Color; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage;
// we attach the actions to menu items fileMenu.add(new JMenuItem(openAction)); fileMenu.add(new JMenuItem(saveAction)); fileMenu.addSeparator(); fileMenu.add(new JMenuItem(exitAction));
// we create a programmatic sixteen by sixteen ImageIcon filled with the given color private static ImageIcon createColorIcon(Color color) { int size = 16; BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); try { g.setColor(color); g.fillRect(0, 0, size, size); } finally { g.dispose(); } return new ImageIcon(image); } } [/code] Вероятно, это не ошибка, а особенность. Я предполагаю, что это новое зарезервированное место для значков, но понятия не имею, как бы я его использовал.