2011-05-10 142 views
18

有沒有什麼可以讓你顯示一個小文本彈出窗口(如工具提示)單個單詞或在Swing JTextArea中的字母? (或者一個JTextArea替代具有類似功能。)Swing JTextArea上的Text-mouseover彈出窗口?

我需要什麼樣的行爲應該像一個提示,換句話說,只有鼠標一直徘徊在字一兩秒鐘後顯示彈出式文本,它會自動消失一旦鼠標移開。當然,這裏棘手的部分是,我希望在文本中的字符/字級別,而不是在組件級別......任何建議?

+1

@trashgod和@ camickr說了這一切:-)唯一輕微的討厭是Swing本身:實現依賴位置的工具提示需要子類化。這是一個小的代價,相比於滾動你自己的WhateverHoverManager – kleopatra 2011-05-11 08:23:59

回答

21

您可以根據需要重寫getToolTipText(Mouse Event event)

附錄:JTextComponentJTextArea的母公司通過兩種方法提供位置信息:modelToView()viewToModel()latter應該允許您將鼠標位置轉換爲文檔偏移量。

+0

爲簡單起見。 – MByD 2011-05-10 23:01:56

+0

@ trashgod +1,但我知道someComponet.dispatchEvent(SwingUtilities.convertMouseEvent(..)從Renderer,但如何處理TextArea + Caret – mKorbel 2011-05-10 23:31:49

+0

@mKorbel:好問題。我_think_位置信息在['JTextComponent']( http://download.oracle.com/javase/6/docs/api/javax/swing/text/JTextComponent.html)就足夠了。作爲參考,我已經更新了指向'JTextComponent#getToolTipText()'的鏈接,在'JComponent'中覆蓋。 – trashgod 2011-05-11 00:00:06

0

這聽起來很棘手。這只是我的頭頂,可能不會被投票。但是你也許可以做到這一點。

假設有某種HoverListener或者你可以實現的東西,否則你將不得不實現一個鼠標監聽器並在你自己的等待計時器中構建。但是,一旦你到達這裏,你知道你想要彈出一個工具提示,你只是不知道他們正在寫什麼字母/單詞。我非常確定,可以在屏幕上獲得光標位置。然後使用這個位置,你可能能夠計算出光標在TextArea內的位置,然後你可以抓住該字符。一旦你擁有了角色/位置,你也可以在不需要做太多工作的情況下抓住整個單詞。 (注意,如果文本區域具有滾動條,則計算光標盤旋時文本區域的「視口」將視爲僅顯示屏幕上可見區域)

對不起非常羅嗦的答案,但這是我會嘗試的一般邏輯,如果我有這個功能,我知道Swing不提供它。希望這是一個體面的起點。

+1

你必須添加一個MouseMotionListener到JTextArea。但getToolTipText要簡單得多。 – MeBigFatGuy 2011-05-10 22:54:10

+0

覆蓋工具TipText更簡單,但使用MouseMotionListener我認爲可能會在其事件參數中傳遞光標的位置,但toolTipText也可能如此。它只是一個看到什麼和我猜測什麼可用的問題。就像我說的,我對任何投票都不抱希望,但我至少想提供一些東西來刺激其他人的創意。 – gnomed 2011-05-11 00:00:51

+2

也許它會被投票,向下...創造力是好的,但浪費在重新發明輪子上。只有當你在一天結束時出現一個令人難以置信的增強型車輪時,你纔會得到讚揚。成功的先決條件是對已有的簡單車輪及其侷限性(如果有的話)的深入瞭解......純粹的假設無法幫助。佈道結束:-) – kleopatra 2011-05-11 08:17:48

10

也許

import java.awt.*; 
import java.awt.event.*; 
import java.awt.font.*; 
import java.awt.geom.*; 
import javax.swing.*; 
import java.util.*; 
import javax.swing.event.*; 

public class SimplePaintSurface implements Runnable, ActionListener { 

    private static final int WIDTH = 1250; 
    private static final int HEIGHT = 800; 
    private Random random = new Random(); 
    private JFrame frame = new JFrame("SimplePaintSurface"); 
    private JPanel tableaux; 

    @Override 
    public void run() { 
     tableaux = new JPanel(null); 
     for (int i = 1500; --i >= 0;) { 
      addRandom(); 
     } 
     frame.add(tableaux, BorderLayout.CENTER); 
     JButton add = new JButton("Add"); 
     add.addActionListener(this); 
     frame.add(add, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(WIDTH, HEIGHT); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     tableaux.requestFocusInWindow(); 
    } 

    @Override 
    public void actionPerformed(final ActionEvent e) { 
     addRandom(); 
     tableaux.repaint(); 
    } 

    void addRandom() { 
     Letter letter = new Letter(Character.toString((char) ('a' + random.nextInt(26)))); 
     letter.setBounds(random.nextInt(WIDTH), random.nextInt(HEIGHT), 16, 16); 
     tableaux.add(letter); 
    } 

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

class Letter extends JLabel { 

    private Font font1; 
    private Font font2; 
    private final FontRenderContext fontRenderContext1; 
    private final FontRenderContext fontRenderContext2; 

    public Letter(final String letter) { 
     super(letter); 
     setFocusable(true); 
     setBackground(Color.RED); 
     font1 = getFont(); 
     font2 = font1.deriveFont(48f); 
     fontRenderContext1 = getFontMetrics(font1).getFontRenderContext(); 
     fontRenderContext2 = getFontMetrics(font2).getFontRenderContext(); 
     MouseInputAdapter mouseHandler = new MouseInputAdapter() { 

      @Override 
      public void mouseEntered(final MouseEvent e) { 
       Letter.this.setOpaque(true); 
       setFont(font2); 
       Rectangle bounds = getBounds(); 
       Rectangle2D stringBounds = font2.getStringBounds(getText(), fontRenderContext2); 
       bounds.width = (int) stringBounds.getWidth(); 
       bounds.height = (int) stringBounds.getHeight(); 
       setBounds(bounds); 
      } 

      @Override 
      public void mouseExited(final MouseEvent e) { 
       Letter.this.setOpaque(false); 
       setFont(font1); 
       Rectangle bounds = getBounds(); 
       Rectangle2D stringBounds = font1.getStringBounds(getText(), fontRenderContext1); 
       bounds.width = (int) stringBounds.getWidth(); 
       bounds.height = (int) stringBounds.getHeight(); 
       setBounds(bounds); 
      } 
     }; 
     addMouseListener(mouseHandler); 
    } 
} 
+1

+1對於_tour de force_! – trashgod 2011-05-10 22:57:03

+0

你喜歡隨機代碼片段:-) – kleopatra 2011-05-11 07:34:37

10

當然,這裏的棘手的部分是,我想它在文本

你用鼠標點中的字符/單詞的水平,以確定您是在文本區:

int offset = textArea.viewToModel(...); 

既然你有一個偏移量,你可以得到該位置的字符或單詞。 Utilities類具有諸如getWordStart()和getWordEnd()之類的方法。

然後您使用getText(...)方法獲取單詞或字符。

+0

+1謝謝您驗證此內容。我不確定何時對@mKorbel發表評論,並且當我更新[我的]時,我無意中忽略了你的答案(http://stackoverflow.com/questions/5957241/text-mouseover-popups-over-a-swing-jtextarea/5957412 #5957412)。 – trashgod 2011-05-11 04:31:29

0

這是建立在@trashgods和@camickr答案實際實現:

addToolTip(line,toolTip) 

您可以添加一個工具提示,當你將鼠標懸停在該行會顯示特定行。您可能需要設置debug = true以獲取每個位置的工具提示顯示。

,如果你想顯示線條的通用工具提示,沒有你可能要與

addToolTip(-1,"general tool tip"). 

源代碼添加它特定的一個:

package com.bitplan.swingutil; 

import java.awt.event.MouseEvent; 
import java.util.HashMap; 
import java.util.Map; 

import javax.swing.JTextArea; 
import javax.swing.text.BadLocationException; 

/** 
* Answer for 
* http://stackoverflow.com/questions/5957241/text-mouseover-popups-over-a-swing-jtextarea/35250911#35250911 
* 
* see http://stackoverflow.com/a/35250911/1497139 
* a JTextArea that shows the current Position of the mouse as a tooltip 
* @author wf 
* 
*/ 
public class JToolTipEventTextArea extends JTextArea { 
    // make sure Eclipse doesn't show a warning 
    private static final long serialVersionUID = 1L; 

    // switch to display debugging tooltip 
    boolean debug=false; 

    /** 
    * the map of tool tips per line 
    */ 
    public Map<Integer,String> lineToolTips=new HashMap<Integer,String>(); 

    /** 
    * create me with the given rows and columns 
    * @param rows 
    * @param cols 
    */ 
    public JToolTipEventTextArea(int rows, int cols) { 
    super(rows,cols); 
    // initialize the tool tip event handling 
    this.setToolTipText(""); 
    } 

    /** 
    * add a tool tip for the given line 
    * @param line - the line number 
    * @param tooltip - 
    */ 
    public void addToolTip(int line,String tooltip) { 
    lineToolTips.put(line,tooltip); 
    } 

    /** 
    * get the ToolTipText for the given mouse event 
    * @param event - the mouse event to handle 
    */ 
    public String getToolTipText(MouseEvent event) { 
    // convert the mouse position to a model position 
    int viewToModel =viewToModel(event.getPoint()); 
    // use -1 if we do not find a line number later 
    int lineNo=-1; 
    // debug information 
    String line=" line ?"; 
    // did we get a valid view to model position? 
    if(viewToModel != -1){ 
     try { 
     // convert the modelPosition to a line number 
     lineNo = this.getLineOfOffset(viewToModel)+1; 
     // set the debug info 
     line=" line "+lineNo; 
     } catch (BadLocationException ble) { 
     // in case the line number is invalid ignore this 
     // in debug mode show the issue 
     line=ble.getMessage(); 
     } 
    } 
    // try to lookup the tool tip - will be null if the line number is invalid 
    // if you want to show a general tool tip for invalid lines you might want to 
    // add it with addToolTip(-1,"general tool tip") 
    String toolTip=this.lineToolTips.get(lineNo); 
    // if in debug mode show some info 
    if (debug) { 
     // different display whether we found a tooltip or not 
     if (toolTip==null) { 
     toolTip="no tooltip for line "+lineNo; 
     } else { 
     toolTip="tooltip: "+toolTip+" for line "+lineNo; 
     } 
     // generally we add the position info for debugging 
     toolTip+=String.format(" at %3d/%3d ",event.getX(),event.getY()); 
    } 
    // now return the tool tip as wanted 
    return toolTip; 
    } 
}