【问题标题】:Clickable thumbnail image in a tooltip工具提示中的可点击缩略图
【发布时间】:2014-10-09 14:49:40
【问题描述】:

我希望当用户将鼠标光标悬停在树表中的特定项目上时出现一种特殊的工具提示。此工具提示将是 PDF 的缩略图,对应于树表中光标所指的项目。此外,我希望用户能够将光标移到缩略图上并单击它,这应该会在他们系统的默认 PDF 阅读器(Acrobat、Adobe Reader 等)中打开完整的 PDF。

我意识到这是一项艰巨的任务,但我已经完成了大部分工作。我已经确切地发现在我的大型程序中我需要使用setToolTip() 方法,以便它可以检索适当的缩略图。此外,由于我发现让 Java 动态地从 PDF 创建缩略图太难了,所以我已经做好了准备,所以会预先制作缩略图 JPG。因此,所有setToolTip() 命令需要做的就是以某种方式检索适当的JPG。现在是最困难的部分了。

起初,这似乎很容易。我试过this really convenient hack for putting an image in a tooltip,它肯定会正确显示缩略图。但是,用锚标记 (<a href="...">...</a>) 围绕 <img> 标记似乎不太有效。缩略图被蓝色边框包围,好吧,但图像仍然无法点击。此外,工具提示有时会在其图像被点击之前消失。

所以我想我可能需要做一些比简单的 html hack 更深入的事情。我试过this more involved way of putting an image in a tooltip,但似乎只适用于静态图像。我需要根据鼠标光标悬停的内容来改变图像。此外,如何设置我的方法以使用此“自定义版本的工具提示”而不是内置的?

为了提供更多上下文,setToolTip() 方法似乎工作的位置位于 getTreeCellRendererComponent() 方法内部,该方法是扩展 JPanel 并实现 TreeCellRenderer 的自定义类的一部分。如果被问到,我会发布代码,但它可能会相当复杂且难以理解。有什么想法吗?

编辑 2014 年 9 月 10 日下午 4:57: 大部分代码可能会造成混淆,为此,我深表歉意。可以说它与在 JXTreeTable 中放置一个三态复选框有关。无论如何,我希望重要的部分应该很容易挑选出来。如您所见,这个类已经扩展了JPanel,所以我不能让它也扩展JToolTip

package info.chrismcgee.sky.treetable;

import info.chrismcgee.beans.OrderDetail;
import info.chrismcgee.components.ImageToolTip;
import info.chrismcgee.components.TristateCheckBox;
import info.chrismcgee.components.TristateState;
import info.chrismcgee.enums.OSType;

import java.awt.BorderLayout;
import java.io.File;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;

public class SkyCheckTreeCellRenderer extends JPanel implements
        TreeCellRenderer {
    /**
     * 
     */
    private static final long serialVersionUID = -2728513730497144120L;
    private SkyCheckTreeSelectionModel selectionModel;
    private TreeCellRenderer delegate;
    private boolean showRootNodeCheckBox;
    private TristateCheckBox checkBox = new TristateCheckBox("");
    protected SkyCheckTreeManager.CheckBoxCustomizer checkBoxCustomer;
    private String jobsFolderStr = OSType.getOSType() == OSType.MAC
            ? "/Volumes/ArtDept/ArtDept/JOBS"
            : "//SKYFS/ArtDept/ArtDept/JOBS";

    public SkyCheckTreeCellRenderer(TreeCellRenderer delegate,
            SkyCheckTreeSelectionModel selectionModel,
            boolean showRootNodeCheckBox) {
        this.delegate = delegate;
        this.selectionModel = selectionModel;
        this.showRootNodeCheckBox = showRootNodeCheckBox;
        setLayout(new BorderLayout());
        setOpaque(false);
        checkBox.setOpaque(false);
    }

    public JToolTip createToolTip() {
        return new ImageToolTip();
    }

    private String getToolTipText(DefaultMutableTreeTableNode node)
    {
        if (node.getUserObject() instanceof OrderDetail)
        {
            OrderDetail od = (OrderDetail) node.getUserObject();
            String thousandsFolderStr = jobsFolderStr + "/"
                    + od.getOrderId().substring(0, 3) + "000-"
                    + od.getOrderId().substring(0, 3) + "999/";

            String productFolderStr = thousandsFolderStr + od.getOrderId()
                    + " Folder/";
            if (!od.getProductDetail().equals(""))
                productFolderStr = thousandsFolderStr + od.getOrderId() + "/";

            String img = productFolderStr + od.getOrderId() + "_THUMB.jpg";
            if (!od.getProductDetail().equals(""))
                img = productFolderStr + od.getOrderId() + "_" + od.getProductDetail() + "_THUMB.jpg";

            if (new File(img).exists())
                return "<html><img src=\"file://" + img + "\"></html>";
        }
        return null;
    }

    public JComponent getTreeCellRendererComponent(JTree tree, Object value,
            boolean selected, boolean expanded, boolean leaf, int row,
            boolean hasFocus)
    {
        JComponent renderer = (JComponent) delegate.getTreeCellRendererComponent(tree, value,
                selected, expanded, leaf, row, hasFocus);

        if (!showRootNodeCheckBox && tree.getModel().getRoot() == value)
        {
            renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
            return renderer;
        }

        TreePath path = tree.getPathForRow(row);
        if (path != null) {
            if (checkBoxCustomer != null && !checkBoxCustomer.showCheckBox(path))
            {
                renderer.setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
                return renderer;
            }
            if (selectionModel.isPathSelected(path, selectionModel.isDigged()))
                checkBox.getTristateModel().setState(TristateState.SELECTED);
            else
                checkBox.getTristateModel().setState(selectionModel.isDigged()
                        && selectionModel.isPartiallySelected(path)
                            ? TristateState.INDETERMINATE
                            : TristateState.DESELECTED);
        }
        removeAll();
        add(checkBox, BorderLayout.WEST);
        add(renderer, BorderLayout.CENTER);
        setToolTipText(getToolTipText((DefaultMutableTreeTableNode)value));
        return this;
    }

}

我知道我需要以某种方式扩展 JToolTip,并且此 SkyCheckTreeCellRenderer 类需要以某种方式引用该自定义工具提示。我想所有这一切都变得如此复杂和复杂,以至于我简单的大脑无法处理所有这些。我很抱歉。

【问题讨论】:

    标签: java image swing tooltip clickable


    【解决方案1】:

    如何设置我的方法以使用这个“自定义版本的工具提示”而不是内置的?

    如示例所示,您需要扩展组件以使用自定义工具提示。

    我需要根据鼠标光标悬停的内容来改变图像

    然后您需要重写getToolTipText(MouseEvent) 方法以返回一个文本字符串来表示您要显示的图像。

    但是,用锚标记 (...) 包围标记似乎不太有效

    如果要响应超链接,则需要使用 JEditorPane。阅读 JEditorPane API 以获取示例。

    所以基本上我建议您需要使用自定义 JToolTip,它使用 JEditorPane 来显示带有适当超链接的适当图像。这是一个示例,展示了如何将 JLabel 用作工具提示的添加组件。您应该能够修改代码以使用 JEditorPane。

    此外,您需要扩展您的树表以使用此自定义 JToolTip。

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.net.URL;
    import java.io.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class ToolTipImage extends JToolTip
    {
        private Image image;
    
        public ToolTipImage(Image image)
        {
            this.image = image;
    
            setLayout( new BorderLayout() );
            add( new JLabel( new ImageIcon( image) ) );
        }
    
        @Override
        public Dimension getPreferredSize()
        {
            return new Dimension(image.getWidth(this), image.getHeight(this));
        }
    
        private static void createAndShowGUI() throws Exception
        {
            final BufferedImage testImage = ImageIO.read(new File("dukewavered.gif"));
    
            String[] columnNames = {"Column 0", "Column 1"};
    
            Object[][] data =
            {
                {"Cell 0,0", "Cell 0,1"},
                {"Cell 1,0", "Cell 1,1"}
            };
    
            JTable table = new JTable(data, columnNames)
            {
                public JToolTip createToolTip()
                {
                    return new ToolTipImage( testImage );
                }
            };
    
            // Set tool tip text so that table is registered w/ tool tip manager
            table.setToolTipText(" ");
    
            JFrame frame = new JFrame("Tool Tip Image");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( new JScrollPane(table) );
            frame.setLocationByPlatform( true );
            frame.pack();
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        createAndShowGUI();
                    }
                    catch(Exception e) { System.out.println(e); }
                }
            });
        }
    }
    

    【讨论】:

    • 我知道你打算用这个去哪里,但是我已经扩展了相关的类JPanel。查看我的编辑以了解我来自哪里。有什么想法,@camickr 或 @ControlAltDel?
    • @Sturm As you can see, this class already extends JPanel, so I cannot have it extend JToolTip as well. 我从来没有说过你也必须扩展 JToolTip。在我给你的例子中,ToolTipImage 类是一个单独的类。
    【解决方案2】:

    听起来您需要构建一个自定义工具提示,如detailed in JToolTip

    单击后,您应该使用运行时从命令行打开文件。在 Windows 中执行此操作的方法已发布 here。在 ubuntu 上执行此操作的方法发布在 here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多