编程语言
首页 > 编程语言> > java – 在当前鼠标位置检测图像仅适用于图像的一部分

java – 在当前鼠标位置检测图像仅适用于图像的一部分

作者:互联网

我有一个JTextPane,我添加了文本,而一些文本有一个通过StyleConstants.setIcon()设置的图像.我还向JTextPane添加了一个鼠标监听器,以检测鼠标在图像上单击/悬停的时间,但它只在图像的左侧部分检测到它.难道我做错了什么?

SSCCE(将鼠标悬停在图像上会更改鼠标光标以指示何时检测到图像):

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

/**
 * SSCCE to show how detecting an image under the current mouse position only
 * works on part of the image. It adds a simple image to the document of the
 * JTextPane and changes the mouse cursor when it detects the mouse hovering
 * over the image.
 */
public class JTextPaneImage {

    private static void createWindow() {

        // Create window
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create JTextPane and add to window
        final JTextPane textPane = new JTextPane();
        textPane.setEditable(false);
        textPane.addMouseMotionListener(new MouseAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {
                AttributeSet style = getAttributes(e);
                if (style != null && StyleConstants.getIcon(style) != null) {
                    textPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                } else {
                    textPane.setCursor(Cursor.getDefaultCursor());
                }
            }
        });
        frame.add(new JScrollPane(textPane));

        try {
            StyledDocument doc = (StyledDocument)textPane.getDocument();

            // Add some text
            doc.insertString(0, "Some text ", null);

            // Add the image
            SimpleAttributeSet style = new SimpleAttributeSet();
            StyleConstants.setIcon(style, createImage());
            doc.insertString(doc.getLength(), "test", style);
        } catch (BadLocationException ex) {
            Logger.getLogger(JTextPaneImage.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Display everything
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    /**
     * Retrieves the style of where the mouse is positioned (assuming this is
     * a JTextPane).
     * 
     * @param e The mouse event containing the mouse position
     * @return The AttributeSet or null if none could be found
     */
    private static AttributeSet getAttributes(MouseEvent e) {
        JTextPane text = (JTextPane)e.getSource();
        Point mouseLocation = new Point(e.getX(), e.getY());
        int pos = text.viewToModel(mouseLocation);

        if (pos >= 0) {
            StyledDocument doc = text.getStyledDocument();
            Element element = doc.getCharacterElement(pos);
            return element.getAttributes();
        }
        return null;
    }

    /**
     * Creates a single 28x28 image filled with a single color.
     * 
     * @return The created ImageIcon
     */
    public static ImageIcon createImage() {
        BufferedImage image = new BufferedImage(28,28, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.GREEN);
        g.fillRect(0, 0, 28, 28);
        g.dispose();
        return new ImageIcon(image);
    }

    public static final void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createWindow();
            }
        });
    }
}

解决方法:

您使用强text.viewToModel(mouseLocation)来检测偏移量,然后从获得的偏移量中检索样式.

逻辑是返回更接近鼠标位置的偏移量.因此,当您单击视图的右半部分时,将返回下一个偏移(视图后的偏移).您可以尝试相同的设置一个大字母(例如m大字体).当你clikc接近字母结束时,插入符号设置在字母后面.这里的逻辑是一样的.

所以你得到了图像之后的位置并从位置获取样式但是在图像视图文本元素之后没有属性中的图标而你没有图像.

更新:

为了提供正确的行为,我建议使用modelToView()并传递获得的偏移量.从矩形中你可以弄清楚你的X位置是否已经过时了.矩形的X.如果插入矩形的x大于鼠标X,则可以尝试前一个偏移.

UPDATE2:您可以覆盖IconView并使用paint()方法存储图像视图的最后一个绘制矩形.存储在最后绘制的地图中.在鼠标移动/单击时,检查地图以查找其中一个矩形是否包含该点.

要么

你可以使用View的方法getChildAllocation()类似的东西被描述为here来计算图像边界.从根视图开始,然后向下直到叶子计算X,Y的正确视图.如果叶子视图是IconView,则你的图像已经过了.

标签:jtextpane,java,swing
来源: https://codeday.me/bug/20190830/1770404.html