获取JLabel中图标的位置

3
我正在尝试在JLabel的图标上显示网格(以及其他项目),但我无法确定根据其布局获取图标坐标的方法。
附注:由于我需要鼠标支持,所以我不能使用setIcon()在图标内部进行绘制操作。
public class ExtendedJLabel extends JLabel implements MouseMotionListener
{
    private final int GRID_STEP = 16;

    public ExtendedJLabel()
    {
        super();
        setOpaque(true);
        setBackground(UIManager.getColor("controlShadow");
        addMouseMotionListener(this);
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        if(icon == null)
            return;

        // Icon Origin
        int ox = ...;
        int oy = ...;

        // Draw grid
        g.setColor(UIManager.getColor("controlShadow"));

        for(int row = 0; row < getIcon().getIconHeight() / GRID_STEP; row++)
            g.drawLine(ox, oy + row * GRID_STEP, ox + getIcon().getIconWidth(), oy + row * GRID_STEP);

        for(int col = 0; col < getIcon().getIconWidth() / GRID_STEP; col++)
            g.drawLine(ox + col * GRID_STEP, oy, ox + col * GRID_STEP, oy + getIcon().getIconHeight());
    }

    @Override
    public void mouseMoved(MouseEvent me)
    {
        // ...
    }

    @Override
    public void mouseDragged(MouseEvent me)
    {
        // ...
    }
}

尝试在图标上方显示网格(和其他项目)。为什么不直接在制作图标的图像上绘制网格?“其他项目”是什么? - Andrew Thompson
1
我非常确定这是不可能完成的,因为执行此操作的代码深埋在外观和感觉代码内部。 - MadProgrammer
太遗憾了。那我就自己写一个图片显示组件吧。谢谢。 - Tabaqui
@camickr:“我不知道所有的LAF是否都使用这段代码”,而这就是问题所在... - MadProgrammer
似乎被Windows、Nimbus和Metal LAF使用,这是我能测试的全部。 - camickr
显示剩余2条评论
1个回答

3
我无法找到如何根据布局获取图标坐标的方法。
我相信您可以使用 SwingUtilities.layoutCompoundLabel(...) 方法。
您可以:
1.创建自定义的JLabel并覆盖 paintComponent()方法以绘制网格,或
2.使用JLayer
由于我还没有完全熟悉JLayer,所以这里提供一个使用该方法的示例:
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;

public class LabelIconGridUI extends LayerUI<JComponent>
{
    @Override
    public void paint(Graphics g, JComponent c)
    {
        super.paint(g, c);

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor( Color.ORANGE );

        JLayer jlayer = (JLayer)c;
        JLabel label = (JLabel)jlayer.getView();

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

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

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

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

        g2.dispose();
    }

    private static void createAndShowUI()
    {
        JLabel label = new JLabel("Some Text" );
        label.setIcon( new ImageIcon( "DukeWaveRed.gif" ) );

        label.setVerticalAlignment( JLabel.CENTER );
        label.setHorizontalAlignment( JLabel.CENTER );
        label.setVerticalTextPosition( JLabel.BOTTOM );
        label.setHorizontalTextPosition( JLabel.CENTER );

        LayerUI<JComponent> layerUI = new LabelIconGridUI();
        JLayer<JComponent> layer = new JLayer<JComponent>(label, layerUI);

        JFrame frame = new JFrame("Label Icon Grid");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( layer );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

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

1
我尝试了你的示例,它按预期工作。谢谢!我还发现另一种方法:扩展ImageIcon并覆盖其paintIcon方法,在某个地方存储边界,但我选择实现自己的图像绘制组件以获得更多的灵活性。 - Tabaqui
@Tabaqui “我选择实现自己的图像绘制组件以获得更多的灵活性。” - 但这回答了你的问题吗? - camickr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接