Index > マウスカーソル位置の単語を自動選択してハイライトするJEditorPane
Mon, February 4, 2008

マウスカーソル位置の単語を自動選択してハイライトするJEditorPane

JEditorPaneは、簡易HTMLブラウザとして使うことができます。 JEditorPane上に表示されている文字列をコピーして使いたいのですが、 いちいちマウスで該当する文字列を選択させたくなかったので、 マウスを該当の単語の上に重ねるだけで、単語を選択したように 見せかける機能を GlassPaneの機能を使って実現しました。

コード

TestFrame.java

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.Document;

public class TestFrame extends JFrame{

    private static final String SAMPLE_HTML=("<html><h1>Hello world!</h1><p>There was a farmer had a dog and BINGO was his name, oh.</p>");

    private MyGlassPane glassPane;
    private JEditorPane editorPane;

    private ChunkManager chunkManager;



    public TestFrame() {
        super();

        chunkManager=new ChunkManager();

        glassPane=new MyGlassPane();
        setGlassPane(glassPane);
        glassPane.setVisible(false);

        editorPane=new JEditorPane();
        editorPane.setEditable(false);
        editorPane.setContentType("text/html");





        editorPane.addMouseMotionListener(new MouseMotionAdapter(){
            //@Override
            public void mouseMoved(MouseEvent e) {

                Point pt=e.getPoint();
                int offset=editorPane.viewToModel(pt);

                if(offset>0){
                    offset--;
                }


                Chunk myChunk=chunkManager.getChunk(offset);
                if(myChunk!=null){

                    Rectangle rect1=null;
                    Rectangle rect2=null;

                    try{
                        rect1=editorPane.modelToView(myChunk.start);
                        rect2=editorPane.modelToView(myChunk.end);
                    }
                    catch(Exception ex){
                        hideGlassPane();
                        return ;
                    }

                    int w=rect2.x-rect1.x;
                    int h=rect1.height;

                    if(w>0 && h>0){
                        Point loc=new Point(rect1.x,rect1.y);

                        SwingUtilities.convertPointToScreen(loc, editorPane);
                        SwingUtilities.convertPointFromScreen(loc, glassPane);

                        glassPane.setImgLocation(loc);
                        glassPane.setImgSize(new Dimension(w,h));

                        glassPane.setVisible(true);
                        TestFrame.this.repaint();
                    }
                    else{
                        hideGlassPane();
                        return ;
                    }
                }
                else{
                    hideGlassPane();
                    return ;
                }
            }
        });



        // layout
        doMyLayout();

        // init
        editorPane.setText(SAMPLE_HTML);

        try{
            Document doc=editorPane.getDocument();
            int len=doc.getLength();
            String text=doc.getText(0, len);

            chunkManager.setText(text);
        }
        catch(Exception ex){
            System.out.println(ex);
        }

    }

    private void doMyLayout(){

        JPanel panel=new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        panel.add(new JLabel("Test"),BorderLayout.NORTH);
        panel.add(editorPane,BorderLayout.CENTER);

        Container pane=getContentPane();
        pane.add(panel,BorderLayout.CENTER);

    }

    private void hideGlassPane(){
        glassPane.setVisible(false);
        repaint();
    }

    public static void main(String[] args) {

        TestFrame frame = new TestFrame();

        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        frame.setSize(320, 360);
        frame.setVisible(true);
    }
}

Chunk.java

class Chunk {
    public int start;
    public int end;
    public String word;
    public Chunk(String word,int start,int end){
        this.word=word;
        this.start=start;
        this.end=end;
    }
    public boolean contains(int pos){
        if(start<=pos && pos<end){
            return true;
        }
        return false;
    }
}

ChunkManager.java

import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Locale;


class ChunkManager{

    private ArrayList chunkList=new ArrayList();
    //private ArrayList<Chunk> chunkList=new ArrayList<Chunk>();

    public void setText(String text){

        chunkList.clear();

        //BreakIterator
        BreakIterator boundary = BreakIterator.getWordInstance(Locale.ENGLISH);
        boundary.setText(text);
        int start = boundary.first();
        for (int end = boundary.next(); end != BreakIterator.DONE;start = end, end = boundary.next()) {
            String word = text.substring(start, end);
            chunkList.add( new Chunk(word,start,end) );
        }
    }
    public Chunk getChunk(int offset){
        Chunk myChunk=null;
        for(int i=0; i<chunkList.size(); i++){
            Chunk c=(Chunk)chunkList.get(i);
            if(c.contains(offset)){
                myChunk=c;
                break;
            }
        }
        return myChunk;

        /*
        for(Chunk c : chunkList){
            if(c.contains(offset)){
                myChunk=c;
            }
        }
        return myChunk;
        */
    }

}

MyGlassPane.java

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;

import javax.swing.JComponent;



class MyGlassPane extends JComponent{

    private static Composite composite=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f);


    private Point loc;
    void setImgLocation(Point loc){
        this.loc=loc;
    }
    private Dimension size;
    void setImgSize(Dimension size){
        this.size=size;
    }
    //@Override
    protected void paintComponent(Graphics g) {
        if(loc==null || size==null)
            return ;

        super.paintComponent(g);

        Graphics2D g2=(Graphics2D)g;
        Composite keepComp=g2.getComposite();
        Color keepC=g2.getColor();
        {
            g2.setComposite(composite);
            g2.setColor(Color.BLUE);
            g2.fill(new Rectangle(loc.x,loc.y,size.width,size.height));
        }
        g2.setComposite(keepComp);
        g2.setColor(keepC);

    }
}
 Twitter
follow me on Twitter
 Categories