2014-01-15 63 views
2

我有一個應用程序,它基本上使用JTextPane作爲一個多行標籤,可以將文本居中並自動換行(居中是我不使用較輕組件的原因,但JTextArea會有同樣的問題)。它被用作較大實體的一部分,它應該使用一個工具提示。但是,設置包含組件的工具提示不適用於JTextPane。其他組件按預期顯示工具提示。在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上顯示父組件的工具提示?

編輯: 我試圖重寫​​方法和註冊與刀尖管理器的組件,如意見提出。這是有效的,因爲文本窗格從父節點獲取工具提示文本。但是,視覺效果與我的解決方法完全相同。

+1

,我不知道這是否會需要繼承,如果覆蓋'getToolTipText()'和'getToolTipText(MouseEvent事件)'並返回父項的工作。我沒有測試過這個。 –

+0

@HovercraftFullOfEels不幸的是,不行。 – kiheru

+0

您可能需要向工具提示管理器註冊組件,以便它觸發getToolTipText方法 – MadProgrammer

回答

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); 
} 

編輯:包括一個標籤,該標籤組件組外與共享刀尖,從更典型使用玻璃來區分窗格。

+0

[getRootPane.setGlassPane](http:// stackoverflow。com/q/8715807/714968) – mKorbel

+1

@mKorbel這是正常的方式,可以用於這個例子:-)在我的真實代碼中,組件組不覆蓋整個窗口,所以我不能使用根窗格沒有額外的手段來手動處理座標)。我在'JLayeredPane'和'OverlayLayout'之間思考,後者對於我的特殊用例來說更簡單,所以我爲它付出了代價。對於玻璃板的典型用途,'getRootPane()。setGlassPane()'是絕對要走的路。我應該修改這個例子足以包含一個組件不應該共享的工具提示。 – kiheru

+0

順便說一句,謝謝你的好問題,即使不讚賞 – mKorbel

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); 
      } 
     }); 
    } 

} 
+0

我最終以其他方式完成了它,但是正確地記錄了這一點(而不是將它留給問題的評論)方法值得讚賞。我的條件有點特別,這可能更適合其他人。 – kiheru