如何去掉JMenu和JMenuItems中的白边

How to take out white borders in JMenu and JMenuItems

我正在用 Swing 做这个图形界面。我遇到的问题是我无法将 JMenuItems 周围的白色边框全部涂成黑色。这是一张图片:

我想这样画(我已经用paint编辑了图片:D):

有人可以帮助我吗?我将不胜感激任何帮助。谢谢!

我刚刚做了这个快速测试,使用

UIManager.put("PopupMenu.border", new LineBorder(Color.RED));

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                UIManager.put("PopupMenu.border", new LineBorder(Color.RED));

                JMenuBar menuBar = new JMenuBar();
                JMenu menu = new JMenu("Stuff");
                menu.add(new JMenuItem("A"));
                menu.add(new JMenuItem("BB"));
                menu.add(new JMenuItem("CCC"));
                menuBar.add(menu);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.setJMenuBar(menuBar);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

现在,这可能是不可取的,因为这会影响程序中的所有弹出菜单

已更新

我查看了 JMenu 并通过它的 UI 委托,弹出菜单似乎是在 JMenuprivate 方法中创建的,称为 ensurePopupMenuCreated,这将是注入自定义代码的绝佳位置。

该方法实际上在许多不同的地方被调用,但可能 getPopupMenu 是最容易访问的

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JMenuBar menuBar = new JMenuBar();
                JMenu menu = new JMenu("Stuff") {
                    private Border border = new LineBorder(Color.RED);
                    @Override
                    public JPopupMenu getPopupMenu() {
                        JPopupMenu menu = super.getPopupMenu();
                        menu.setBorder(border);
                        return menu;
                    }

                };
                JMenuItem mi = new JMenuItem("Help", 'H');
                mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.META_MASK));
                menu.add(new JMenuItem("A"));
                menu.add(new JMenuItem("BB"));
                menu.add(new JMenuItem("CCC"));
                menu.add(mi);
                menuBar.add(menu);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.setJMenuBar(menuBar);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

我正在添加第二种方法。您可以使用 setBorder 方法:

menuBar.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));

这个解决方案的优点是可以设置粗细级别。在上面的示例中,厚度级别设置为 2。

您还可以在许多组件中使用 setBorder 来绘制各种边框,如下例所示:

首先是基本代码:

主要class:

import javax.swing.*;

public class Main {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> {
            CustomGUI sw = new CustomGUI();
            sw.setVisible(true);
        });

    }
} 

CustomGui.class:

import java.awt.*;
import javax.swing.*;

public class CustomGUI extends JFrame {

    public CustomGUI()  {
        super("Simple example");
        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        setSize(500,500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(Color.DARK_GRAY);



        JMenuBar menuBar = new JMenuBar();
        JMenu menu1 = new JMenu("menu B");
        menuBar.add(menu1);

        JMenuItem item = new JMenuItem("A text-only menu item");
        menu1.add(item);

        JMenu menu2 = new JMenu("menu B");
        menuBar.add(menu2);

        JMenuItem item2 = new JMenuItem("A text-only menu item");
        menu2.add(item2);


        add(menuBar);
    }
}

现在添加行:

menuBar.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));

CustomGUI() 中我们得到:

现在,如果我们想为 jmenu 添加边框(这是 OP 要求的),还要添加:

menu1.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.BLUE, 4));
menu2.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.BLUE, 4));

(正如你在图片中看到的,我没有为菜单栏设置边框,但这可以按照上面的描述使用: menuBar.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2)); 我还添加了另一个项目,只是为了让菜单更大,更容易看到边框...)