我有一个弹出菜单,其中包含带有图标(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内部的情况下检索最大文本/图标偏移量?
答案 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会使用相同的布局。