在JTextPane上显示父组件的工具提示

时间:2014-01-15 19:47:44

标签: java swing tooltip jtextpane

我有一个应用程序使用JTextPane基本上作为多行标签,可以居中文本并自动包装(居中是我不使用较轻的组件的原因,但JTextArea会有同样的问题)。它被用作更大实体的一部分,它应该使用一个工具提示。但是,为包含的组件设置工具提示不适用于JTextPane。其他组件按预期显示工具提示。

SSCCE:

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;

public class ToolTipTest {
    ToolTipTest() {
        JFrame frame = new JFrame("Tool tip test");
        frame.setLocationByPlatform(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel bg = new JPanel(new BorderLayout());
        frame.add(bg);
        bg.add(new JLabel("Tooltip shows here"), BorderLayout.NORTH);
        JTextPane text = new JTextPane();
        try {
            text.getStyledDocument().insertString(0, "Lorem ipsum dolor sit"
                    + " amet, consectetur adipiscielit, sed eiusmod tempor"
                    + " incidunt ut labore et dolore magna aliqua.", null);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
        text.setEditable(false);
        text.setFocusable(false);
        bg.add(text);
        bg.setToolTipText("A tooltip, that should show on both the label and the text");
        // Works, but is ugly and results in visible change in tooltip when
        // moving cursor between components
        // text.setToolTipText("A tooltip, that should show on both the label and the text");
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ToolTipTest();
            }
        });
    }
}

在上面的示例中,工具提示显示在JLabel上,但不显示在JTextPane上。我目前正在为文本窗格设置相同的工具提示文本作为解决方法,但是当用户将鼠标光标移动到组件顶部时,这会导致工具提示之间的可见切换。

有没有办法在JTextPane上显示父组件的工具提示?

修改 我尝试重写getToolTipText()方法并使用工具提示管理器注册组件,如评论中所建议的那样。这样,在文本窗格然后从父级获取工具提示文本的意义上。但是,视觉效果与我的解决方法完全相同。

2 个答案:

答案 0 :(得分:4)

基本上,您需要代理工具提示功能,以便在请求时从父级传回值。

您还需要使用ToolTipManager手动注册组件,否则不会要求提供工具提示...

Tooltip

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;

public class ParentToolTip {

    public static void main(String[] args) {
        new ParentToolTip();
    }

    public ParentToolTip() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JTextPane text = new JTextPane() {

                    @Override
                    public String getToolTipText() {
                        return ((JComponent) getParent()).getToolTipText();
                    }

                    @Override
                    public String getToolTipText(MouseEvent event) {
                        return ((JComponent) getParent()).getToolTipText(event);
                    }

                };
                try {
                    text.getStyledDocument().insertString(0, "Lorem ipsum dolor sit"
                            + " amet, consectetur adipiscielit, sed eiusmod tempor"
                            + " incidunt ut labore et dolore magna aliqua.", null);
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }

                ToolTipManager.sharedInstance().registerComponent(text);

                JFrame frame = new JFrame("Testing");
                JPanel panel = new JPanel(new BorderLayout());
                panel.setToolTipText("This is not the tooltip your are looking for");
                frame.setContentPane(panel);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(text);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

答案 1 :(得分:2)

基于mKorbel的想法,我在组件组的顶部做了一个玻璃窗格样式覆盖。在我的例子中,所有组件只提供信息,不需要用户交互,因此玻璃窗格不会打扰调度事件。

我使用OverlayLayout,因为它对我来说最简单和充分。应用于问题中的代码,ToolTipTest构造函数将更改为:

ToolTipTest() {
    JFrame frame = new JFrame("Tool tip test");
    frame.setLocationByPlatform(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // Holds the component group and the glass pane
    JComponent content = new JPanel();
    content.setLayout(new OverlayLayout(content));
    frame.add(content);
    JComponent glassPane = new JComponent(){};
    content.add(glassPane);
    final JPanel bg = new JPanel(new BorderLayout());
    content.add(bg);
    bg.add(new JLabel("Tooltip shows here"), BorderLayout.NORTH);
    JTextPane text = new JTextPane();
    try {
        text.getStyledDocument().insertString(0, "The same tooltip also shows here", null);
    } catch (BadLocationException e) {
        e.printStackTrace();
    }
    text.setEditable(false);
    text.setFocusable(false);
    bg.add(text);
    glassPane.setToolTipText("A tooltip, that shows on both the label and the text");
    JLabel other = new JLabel("This component has another tooltip");
    other.setToolTipText("Another tooltip");
    frame.add(other, BorderLayout.SOUTH);

    frame.pack();
    frame.setVisible(true);
}

编辑:包含带有共享工具提示的组件组外部的标签,以区别于更典型的玻璃窗格使用。