JPopupMenu菜单项和组件

时间:2015-11-30 20:50:12

标签: java swing jpopupmenu

我有一个弹出菜单,其中包含带有图标(I)和JList的JMenuItem。见下图。

------------------------
| I | Clear            |
|----------------------|
|   | List           |^|
|   | Item A         | |
|   | Item B         | |
|   | Item C         | |
|   |                |v|
------------------------

当我最初创建弹出窗口时,列表已对齐到左侧,并未考虑图标偏移。

我能够找到一种使用sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET客户端属性移动列表的方法。

// Move the items out of the gutter (Run inside of the show(Component, int, int) method)
final Integer gutter = (Integer) getClientProperty(SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET);
panelList.removeAll();
panelList.add(Box.createHorizontalStrut(gutter));
panelList.add(scrollList);

但是,我无法在生产代码中使用该常量(因为它在sun包中)。

如何在不依赖Java内部的情况下检索最大文本/图标偏移量?

1 个答案:

答案 0 :(得分:2)

一个常见的解决方案是为每个菜单项添加一个空图标,其大小与菜单的图标大小相同。

您可以使用以下代码中使用的概念:

SwingUtilities.layoutCompoundLabel(...);

基本上,它获取标签的布局信息,以确定文本和图标相对于整个标签的实际绘制位置。如果您知道这些信息,那么您应该获得抵消。

此示例仅在标签中的Icon上绘制网格线:

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

public class LabelLayout extends JLabel
{
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics grid = g.create();
        grid.setColor( Color.ORANGE );

        Rectangle viewR = new Rectangle();
        viewR.width = getSize().width;
        viewR.height = getSize().height;
        Rectangle iconR = new Rectangle();
        Rectangle textR = new Rectangle();

        String clippedText = SwingUtilities.layoutCompoundLabel
        (
            this,
            grid.getFontMetrics(),
            getText(),
            getIcon(),
            getVerticalAlignment(),
            getHorizontalAlignment(),
            getVerticalTextPosition(),
            getHorizontalTextPosition(),
            viewR,
            iconR,
            textR,
            getIconTextGap()
        );

        int gridSize = 10;
        int start = iconR.x;
        int end = iconR.x + iconR.width;

        System.out.println( iconR );

        for (int i = start; i < end; i += gridSize)
        {
            grid.drawLine(i, iconR.y, i, iconR.y + iconR.height);
        }

        grid.dispose();

//      g.setColor( getForeground() );
//      g.drawString(display, textR.x, textR.y + fm.getHeight());
//      System.out.println(iconR + " : " + textR);
    }

    private static void createAndShowGUI()
    {
        LabelLayout label = new LabelLayout();
        label.setBorder( new LineBorder(Color.RED) );
        label.setText( "Some Text" );
        label.setIcon( new ImageIcon( "DukeWaveRed.gif" ) );
        label.setVerticalAlignment( JLabel.CENTER );
        label.setHorizontalAlignment( JLabel.CENTER );
//      label.setVerticalTextPosition( JLabel.BOTTOM );
        label.setVerticalTextPosition( JLabel.TOP );
        label.setHorizontalTextPosition( JLabel.CENTER );

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( label );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setSize(300, 200);
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

我认为JMenu会使用相同的布局。