java - 布局JPopupMenu : How to provide different size for menu items in same menu

标签 java swing jpopupmenu

我需要在菜单中包含两列菜单项。这可以使用弹出菜单的 GridBagLayout 来实现。我的问题是:两列具有相同的宽度,即菜单中最大菜单项的宽度(但不在列中,因为 GridBagLayout 必须如此)。当我用按钮替换菜单中的菜单项时 - 布局工作正常。那么我如何建议菜单中的项目应该具有不同的宽度?

以下是屏幕:

当我使用菜单项时 - 两列具有相同的宽度(错误) Wrong layout for menu items

当我使用按钮时 - 列具有不同的宽度(正确) Correct layout for buttons

下面是代码示例:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;

public class MenuTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Menu test");
        JMenuBar menuBar = new JMenuBar();
        JMenu m1 = new JMenu("Menu items");
        m1.getPopupMenu().setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        m1.getPopupMenu().add(new JMenuItem("Very very very very long text"), gbc);
        gbc.gridx = 1;
        m1.getPopupMenu().add(new JMenuItem("Short text"), gbc);
        menuBar.add(m1);

        JMenu m2 = new JMenu("Buttons");
        m2.getPopupMenu().setLayout(new GridBagLayout());
        gbc.gridx = 0;
        m2.getPopupMenu().add(new JButton("Very very very very long text"), gbc);
        gbc.gridx = 1;
        m2.getPopupMenu().add(new JButton("Short text"), gbc);
        menuBar.add(m2);
        frm.setJMenuBar(menuBar);
        frm.add(new JScrollPane(new JTextArea("Sample text", 10, 40)));
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.pack();
        frm.setVisible(true);
    }
}

最佳答案

显然,JMenuItem 布局基于同一父组件中所有包含的 JMenuItem 的最大宽度。查看 Sun/Oracle 的代码后,似乎很难干扰这一点,并且每个 JMenuItem 的首选大小将是等效的。

然而,我找到了一种方法来克服这个问题,通过重写 JMenutItemgetPreferredSize() ,虽然不太漂亮,但似乎有效:

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;

public class MenuTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Menu test");
        JMenuBar menuBar = new JMenuBar();
        JMenu m1 = new JMenu("Menu items");
        m1.getPopupMenu().setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        JMenuItem comp1 = new JMenuItem("Very very very very long text") {
            @Override
            public Dimension getPreferredSize() {
                return new JMenuItem(getText(), getIcon()).getPreferredSize();
            }
        };
        m1.getPopupMenu().add(comp1, gbc);
        gbc.gridx = 1;
        JMenuItem comp2 = new JMenuItem("Short text") {
            @Override
            public Dimension getPreferredSize() {
                return new JMenuItem(getText(), getIcon()).getPreferredSize();
            }
        };
        m1.getPopupMenu().add(comp2, gbc);
        menuBar.add(m1);

        JMenu m2 = new JMenu("Buttons");
        m2.getPopupMenu().setLayout(new GridBagLayout());
        gbc.gridx = 0;
        m2.getPopupMenu().add(new JButton("Very very very very long text"), gbc);
        gbc.gridx = 1;
        m2.getPopupMenu().add(new JButton("Short text"), gbc);
        menuBar.add(m2);
        frm.setJMenuBar(menuBar);
        frm.add(new JScrollPane(new JTextArea("Sample text", 10, 40)));
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.pack();
        frm.setVisible(true);
        comp1.setVerticalTextPosition(SwingConstants.TOP);
        comp2.setVerticalTextPosition(SwingConstants.TOP);
    }
}

当然,如果您使用 JMenuItem 的其他属性来修改 JMenuItem 的 UI,则需要将其传递给“内部”JMenuItem,如下所示出色地。它也可能很难维护,并且无法在所有 L&F 中工作。

您还可以通过在不同的调用中重复使用相同的“内部”JMenuItem 来改进这一点。

关于java - 布局JPopupMenu : How to provide different size for menu items in same menu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29166669/

相关文章:

java - 不阻塞执行的模态 JDialog

java - 用Java计算全连接的网状拓扑网络数量

java - Android:随机数决定玩家的回合

java - 重绘时复制了 JButton?

java - 向 JPopupMenu 添加垂直滚动?

java - 在 JTree 节点 Swing 处右键单击显示弹出框

java - Spring Boot中@RequestMapping和Locale有什么关系?

java - Java 中的 "val$title"(美元符号表示)是什么?

java - 当我在文本字段中输入 "1"时,如何使按钮起作用?

java - 单击 JPopupMenu 时 JPopupPanel 关闭