2014-01-15 3 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?

Edit: Я попытался перекрывая getToolTipText() методы и регистрацию компоненты с менеджером режущей кромки инструмента, как это было предложено в комментариях. Это работает в том смысле, что текстовая панель затем получает текст подсказки инструмента от родителя. Однако визуальный эффект точно такой же, как и в моем обходном пути.

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

Edit: Включена метка, которая находится за пределами группы компонентов с общим наконечником инструмента, дифференцироваться от более типичного использования стекла стекла.

+0

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

+1

@mKorbel Это обычный способ и будет работать для примера :-) В моем реальном коде группа компонентов не охватывает все окно, поэтому я не могу использовать корневую панель (без дополнительных обманов, чтобы вручную обрабатывать координаты). Я размышлял между 'JLayeredPane' и' OverlayLayout', и последний был более простым для моего конкретного варианта использования, поэтому я решил для него. Для типичного использования стеклянной панели 'getRootPane(). SetGlassPane()' определенно способ пойти. Я должен, вероятно, изменить пример, чтобы включить компонент, который не должен делиться подсказкой инструмента. – kiheru

+0

btw Спасибо за хороший вопрос, даже не стоит оценивать – 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

Смежные вопросы